目录
一、数组
1.定义:类型 数组名[元素个数]
2.数组不能动态定义
3.如何访问数组中的元素:数组名[下标]
4.循环与数组的关系
5.数组的初始化
二、C99标准中的数组
三、字符串处理函数
1.字符数组
2.获取字符串的长度:strlen
(1)函数概要
(2)函数原型
3.拷贝字符串:strcpy和strncpy
4.连接字符串:strcat和strncat
5.比较字符串:strcmp和strncmp
一、数组
1.定义:类型 数组名[元素个数]
int a[6];char b[24];double c[3];思考:上述几个类型,占用多少个字节的内存?
分别如下:
2.数组不能动态定义
3.如何访问数组中的元素:数组名[下标]
a[0];// 访问a数组中的第一个元素b[1];// 访问a数组中的第二个元素c[5];// 访问a数组中的第六个元素注意:
int a[5];// 创建一个具有五个元素的数组a[0];// 访问第一个元素的下标是0,不是1a[5];// 报错,因为第五个元素的下标是a[4]
4.循环与数组的关系
举个栗子:实现一个执行10次的循环,通常是这么写:
for(i = 0; i < 10; i++){……}
而不是这样:
for(i = 1; i <= 10; i++){……}
这是因为我们常常需要用循环来访问数组:
int a[10];for(i = 0; i < 10; i++){a[i] = i;}
代码实战:尝试使用数组存放10位同学的数学成绩,并计算出平均数
#include <stdio.h>#define NUM 10int main(){int s[NUM];int i,sum = 0;for(i = 0;i < 10; i++){printf("请输入第%i位同学的成绩:",i + 1);scanf("%d",&s[i]); sum += s[i];}printf("成绩录入完毕,该次考试的平均分是:%.2f\n",(double)sum / NUM);return 0;}
运行结果:
5.数组的初始化
将数组中所有元素初始化为0:int a[10] = {0};// 事实上这里只是将第一个元素赋值为0
代码举例:
#include <stdio.h>int main(){int a[10] = {0};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}return 0;}
运行结果:
如果是赋予不同的值,则用逗号分隔开:
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
代码举例:
#include <stdio.h>int main(){int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}return 0;}
运行结果:
还可以只给一部分元素赋值,未被赋值的元素自动初始化为0:
int a[10] = {1, 2, 3, 4, 5, 6}; //表示前面6个元素赋值,后面4个元素系统自动初始化为0
代码举例:
#include <stdio.h>int main(){int a[10] = {1, 2, 3, 4, 5, 6};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}return 0;}
运行结果:
有时也可只给出各个元素的值,而不指定数组的长度(因为编译器会根据值的个数自动判断数组的长度):
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
代码举例:
#include <stdio.h>int main(){int a[] = {1, 2, 3, 4, 5, 6};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}return 0;}
运行结果:
C99增加了一种新特性:指定初始化的元素。这样就可以只对数组中的某些指定元素进行初始化赋值,而未被赋值的元素自动初始化为0:
int a[10] = { [3] = 3, [5] = 5,[8] = 8 };
代码举例:
#include <stdio.h>int main(){int a[10] = { [3] = 3, [5] = 5,[8] = 8};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}return 0;}
运行结果:
补充:sizeof
计算占用空间的大小若后边写的是数组名,则计算数组占用的内存的大小
代码举例:
#include <stdio.h>int main(){int a[10] = { [3] = 3, [5] = 5,[8] = 8};int i;for(i = 0; i < 10; i++){printf("%d\n",a[i]);}printf("%d\n",sizeof(a));return 0;}
运行结果:
二、C99标准中的数组
数组的尺寸如果是整型常量或者整型常量表达式时,或确定其尺寸时,数组的类型就不是一个可变长度的数组;否则它就是可变长度的数组。也就是说,在C99标准时,C语言已经支持可变数组了。
注意:这里说的可变长度或者变长数组指的是数组的长度在运行时才被决定,即用变量来指定数组的长度。
代码举例1:
#include <stdio.h>int main(){int n,i;printf("请输入字符的个数:");scanf("%d",&n);char a[n+1]; printf("请开始输入字符:");getchar();for(i = 0;i < n;i++) {scanf("%c",&a[i]);}a[n] = '\0';printf("你输入的字符串是:%s",a);return 0;}
运行结果:
代码举例2:
#include <stdio.h>int main(){int a[10],i;for(i = 0;i <= 10; i++)//此处为试错操作,开发中尽量不要出现=号,可能会出现数组越界问题 {a[i] = i; }for(i = 0;i <= 10;i++){printf("%d\n",a[i]);}return 0;}
运行结果:
三、字符串处理函数
1.字符数组
字符串常量:“FishC”,“小甲鱼”,“鱼C工作室”字符数组:2.获取字符串的长度:strlen
(1)函数概要
strlen函数用于返回指定字符串的长度。C语言字符串的长度取决于结束符('\0')的位置。一个字符串的长度指的是从起始位置到结束符的字符个数(不包含结束符本身)。注意:不要混消字符串的长度和字符串数组的大小。
(2)函数原型
#include <string.h>…size_t strlen(const char * str );
返回值:
如果该函数调用成功,返回值是指定字符串的长度(字符个数,不包含结束符 '\0' )。
注意: size_t 被定义于 stddef.h 头文件中,它事实上就是无符号整形(unsigned int)
代码举例:
#include <stdio.h>#include <string.h>int main(){char str[] = "I love C!";printf("sizeof str = %d\n",sizeof(str));printf("strlen str = %u\n",strlen(str));return 0;}
运行结果:
3.拷贝字符串:strcpy和strncpy
(1)strcpy
使用此函数一定要保证目标字符串(目标字符数组)的长度要足以容纳源字符串(源数组)。否则,会出现问题(但不报错)。
代码举例:
#include <stdio.h>#include <string.h>int main(){char str1[] = "Original String";char str2[] = "New String";char str3[100];strcpy(str1,str2);//① strcpy(str3,"Copy Successful");printf("str1:%s\n",str1);printf("str2:%s\n",str2);printf("str3:%s\n",str3);return 0;}
运行结果:
若将上述代码①处改为:strcpy(str2,str1); 则会有问题产生。因此在程序实现拷贝的时候,应该限制源字符串的长度,确保目标字符串在执行完拷贝之后不会发生溢出。此时即可使用strncpy。
(2)strncpy
①函数概要
和 strcpy 函数一样,strncpy 函数将拷贝源字符串的 n 个字符到目标数组中,如果源字符串的长度小于 n,那么就用 '\0' 填充额外的空间。如果源字符串的长度大于或等于 n,那么只有 n 个字符被拷贝到目标数组中(注意:这样的话将不会以结束符 '\0' 结尾)。
为了使该函数更“安全”,建议使用 dest[n-1] = '\0';语句确保目标字符串是以 '\0' 结尾。源字符串和目标数姐的位置不应该重叠。
代码举例:
#include <stdio.h>#include <string.h>int main(){char str1[] = "To be or not to be";char str2[40];strncpy(str2, str1, 5);//参数5用于限制拷贝的长度str2[5] = '\0';//①printf("str2:%s\n",str2);return 0;}
运行结果:
4.连接字符串:strcat和strncat
要求目标数组中已经包含一个字符串(可以是空字符串),它会找到该字符串的末尾,并将源字符串连接过去。
代码举例:
#include <stdio.h>#include <string.h>int main(){char str1[] = "I love";char str2[] = "C!";strcat(str1, " ");strcat(str1,str2);printf("str1: %s\n",str1);return 0;}
运行结果:
注意:strncat与strncpy不同,它总是在连接后面会自动加一个结束符 '\0' ,
5.比较字符串:strcmp和strncmp
(1)strcmp
用来比较两个字符串是否完全一致,若一致,则返回值为0;否则,则根据情况返回大于0或小于0的值原理:从第一个字符串开始依次对比两个字符串每个字符的ASCII码,如果第一个字符串的ASCII码小于第二个字符串对应的字符,则返回一个小于0的值;如果第一个字符串的ASCII码大于第二个字符串对应的字符,则返回一个大于0的值。
代码举例:
#include <stdio.h>#include <string.h>int main(){char str1[] = "!";//①char str2[] = "!";if(!strcmp(str1,str2)){printf("两个字符串完全一致!\n");}else{printf("两个字符串存在差异!\n");}return 0;}
运行结果:
若将上述代码①出的大写C 改为 小写c,则运行结果如下:
(2)strncmp
增加一个参数n用于指定只对比前面的n个字符