时隔3个多月,终于更新了这篇博客,这次终于来到了第六章——数组。这三个月因为放假本身没怎么学习,刚好这学期学校也有c语言课程,我就边自学后面,边把老师讲的当做复习,而且这两天花时间重新复习了前面五章,现在开始正式学习第六章。
注:本博客所有知识点均出自C程序设计(第五版)
C语言规定用方括号中的数字来表示下标。
定义一维数组的一般形式为
类型说明符 数组名[常量表达式]
说明:
(1)数组名的命名规则和变量名相同,遵循标识符命名规则。
(2)在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。例如,a[10],表示a数组有10个元素。但有一点要注意,这个下标是从0开始。按上面的定义,不存在数组元素a[10]。
(3)常量表达式中可以包括常量和符号常量,如“int a[3+5];”是合法的。不能包括变量,如“int a[n];”是不合法的。
在定义数组并对其中各元素赋值后,就可以引用数组中的元素。应注意:只能引用数组元素而不能一次整体调用整个数组全部元素的值。
引用数组元素的表示形式为:数组名[下标]
注:定义数组时用到的“数组名[常量表达式]”和引用数组元素时用的“数组名[下标]”形式相同,但含义不同。
【例6.1】对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,要求按逆序输出。
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
int i, a[10]; //定义整形i和包含十个元素的数组a
for (i = 0; i <= 9; i++) //for循环,i赋值0,当i小于等于9时,第i个数组元素等于i的值,然后i自加1
a[i] = i;
for (i = 9; i >= 0; i--) //for循环,i赋值9,当i大于等于0时。输出第i个数组元素,然后i自减1
printf("%d", a[i]);
printf("\n"); //输出换行符
return 0; //函数值返回0
} //函数结束
注:数组元素的下标从0开始,如果用int a[10]定义数组,则最大下标为9,不存在数组元素a[10]。
在定义数组的同时给各数组元素赋值,称为数组的初始化。
(1)将数组中各元素的初值顺序放在一对花括号内,数据间用逗号隔开。
如:int a[10]={0,1,2,3,4,5,6,7,8,9};
(2)也可以只给数组中的一部分元素赋值,剩下未赋值的元素系统默认赋值0。
如:int a[10]={0,1,2,3,4};
(3)在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组长度。
如:int a[5]={1,2,3,4,5};可以写成int a[ ]={1,2,3,4,5};
【例6.2】用数组来处理求Fibonacci数列问题。
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
int i; //定义整形i
int f[20] = { 1,1 }; //定义数组f含20个元素,前两个元素赋值为1
for (i = 2; i < 20; i++) //for循环,i赋值为2,当i小于20时,f[i]为前两个元素相加,然后i自加1
f[i] = f[i - 2] + f[i - 1];
for (i = 0; i < 20; i++) //这个for循环是整格式的,之前写过,不在赘述
{
if (i % 5 == 0)printf("\n");
printf("%12d", f[i]);
}
printf("\n"); //输出换行符
return 0; //函数值返回0
} //函数结束
【例6.3】有10个地区的面积,要求对它们按由小到大的顺序排列。
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
int a[10]; //定义整型数组包含十个元素
int i, j, t; //定义整形i,j,t
printf("input 10 numbers:\n"); //输出input 10 numbers:\n
for (i = 0; i < 10; i++) //for循环,使数组十个元素赋上输入的十个值
scanf_s("%d", &a[i]);
printf("\n");
for (j = 0 ; j < 9; j++) //for循环,执行起泡法比较,使元素按从小到大比较
for(i=0;i<9-j;i++)
if (a[i] > a[i + 1])
{
t = a[i]; a[i] = a[i + 1]; a[i + 1] = t;
}
printf("the sorted number:\n"); //输出the sorted number:\n
for (i = 0; i < 10; i++) //for循环,输出十个数组
printf("%d ", a[i]);
printf("\n");
return 0; //函数值返回0
} //函数结束
运行结果如下:
input 10 numbers:
34 67 90 43 124 87 65 99 132 26
the sorted number:
26 34 43 65 67 87 90 99 124 132
可以看到,在写出例6.3时,使用了一种比较的方法,起泡法,其基本思路是每次将相邻两个数比较,将小的调到前面。除此之外,排序的算法有多种,常用的还有选择法,希尔法,后续遇到了再介绍。
二维数组常称为矩阵。
二维数组定义的一般形式为:类型说明符 数组名[常量表达式][常量表达式]
二维数组元素的表示形式为:数组名[下标][下标]
注:要区分定义数组时用的a[3][4]和引用元素时的a[3][4]的区别,前者的3和4来定义数组的维数和各维的大小,后者的3和4是数组元素的下标值,代表行序号为3,列序号为4的元素。
可以用“初始化列表”对二维数组初始化。
(1)分行给二维数组赋初值。
如:int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}
(2)可以将所有数据写在一个花括号内,按数组元素在内存中的排列顺序对各元素赋初值。
如:int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}
(3)可以对部分元素赋初值。
如:int a[3][4]={{1},{5},{9}}
其他没赋值的元素自动为0。
【例6.4】将一个二维数组行和列的元素互换,存到另一个二维数组中。
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
int a[2][3] = { {1,2,3},{4,5,6} }; //定义二维数组a有2行3列并赋值
int b[3][2], i, j; //定义二维数组b有3行2列,定义整形i,j
printf("array a:\n");
for (i = 0; i <= 1; i++) //for循环,处理a数组中的一行各元素
{
for (j = 0; j <= 2; j++) //for循环,处理a数组中每一行各列的元素
{
printf("%5d", a[i][j]); //输出a数组的一个元素
b[j][i] = a[i][j]; //将a数组元素的值赋给b数组相应元素
}
printf("\n");
}
printf("array b:\n");
for (i = 0; i <= 2; i++) //for循环,处理b数组中一行中各元素
{
for (j = 0; j <= 1; j++) //for循环,处理b数组中每一行各列的元素
printf("%5d", b[i][j]); //输出b数组的一个元素
printf("\n");
}
return 0; //函数值返回0
} //函数结束
【例6.5】有一个3*4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号。
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
int i, j, row = 0, colum = 0, max;
int a[3][4] = { {1,2,3,4},{9,8,7,6},{-10,10,-5,2} };
max = a[0][0];
for(i=0;i<=2;i++) //for循环,a数组行
for(j=0;j<=3;j++) //for循环,a数组列
if (a[i][j] > max)
{
max = a[i][j]; //如果某元素大于max,就取代max的原值
row = i;
colum = j;
}
printf("max=%d\nrow=%d\ncolum=%d\n", max, row, colum);
return 0;
}
c语言中没有字符串类型,也没有字符串变量,字符串是存放在字符型数组中的。
char c[10];
c[0]=‘i’
char c[10]={‘i’,‘’,‘a’,‘m’,‘’,‘h’,‘a’,‘p’,‘p’,‘y’};
也可以定义和初始化二维字符数组。
(这两小节类比一维和二维数组,就不多赘述)
可以引用字符数组中的一个元素,得到一个字符。
【例6.6】输出一个已知的字符串
#include //编译预处理指令
int main() //定义主函数
{ //函数开始
char c[15] = { 'I',' ','a','m',' ','a',' ','s','t','u','d','e','n','t','.' }; //字符数组初始化
int i; //定义整型i
for (i = 0; i < 15; i++) //for循环挨个输出数组
printf("%c", c[i]);
printf("\n"); //输出换行符
return 0; //函数值返回0
} //函数结束
这个例子是用循环结构逐个输出字符数组。
【例6.7】同样也是循环结构输出,只不过用的二维数组,属于加深印象,就不在展示。
为了测定字符串的实际长度,c语言规定了一个“字符串结束标志”,以字符‘\0’作为结束标志。如果字符数组中存有若干字符,前面九个字符都不是空字符(‘\0’),而第十个字符是‘\0’,则认为数组中有一个字符串,其有效字符为9个。
注:c系统在用字符数组存储字符串常量时会自动加一个‘\0’作为结束符。
两种方式:
(1)逐个字符输入输出。用格式符“%c”输入或输出一个字符。
(2)将整个字符串一次输入或输出。用“%s”格式符,意思是对字符串(string)的输入输出。
例:
char c[ ]={“china”};
printf(“%s\n”,c);
注:
(1)输出的字符中不包括结束符’\0’。
(2)用“%s”格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素。
不能写成这种形式:printf(“%s”,c[0]);
(3)如果数组长度大于字符串的实际长度,也只输出到遇到‘\0’时输出就结束。
(4)如果一个字符数组中包括一个以上‘\0’,则遇到第一个‘\0’时输出就结束。
(5)可以用scanf函数输入一个字符串。&1:scanf函数中的输入项如果是字符数组名,不要再加地址符&,因为在c语言中数组名代表该数组第一个元素的地址。
1.puts函数——输出字符串函数
一般形式为 puts(字符数组)
2.gets函数——输入字符串的函数
一般形式为 gets(字符数组)
注:用puts和gets函数只能输出或输入一个字符串,不能写成puts(str1,str2)或gets(str1,str2)
3.strcat函数——字符串连接函数
一般形式为 stract(字符数组1,字符数组2)
说明:
(1)字符数组1必须足够大,以便容纳连接后的新字符串。
(2)连接前2个字符串的后面都有‘\0’,连接时将字符串1后面的‘\0’取消,只在新串最后保留‘\0’。
4.strcpy和strncpy函数——字符串复制函数
一般形式为 strcpy(字符数组1,字符数组2)
说明:
(1)字符数组1必须定义得足够大,以便容纳被复制的字符串2.
(2)“字符数组1”必须写成数组名形式(如str1),“字符串2”可以是字符数组名,也可以是一个字符串常量。
(3)如果在复制前未对str1数组初始化或赋值,则str1各字节中的内容是无法预知的,复制时将str2中的字符串和其后的‘\0’一起复制到字符数组1中,取代字符数组1中的前面6个字符,最后4个字符并不一定是‘\0’,而是str1中原有的最后四个字节的内容。
(4)不能用赋值语句将一个字符串常量或字符数组直接给一个字符数组。字符数组名是一个地址常量,他不能改变值,正如数值型数组名不能被赋值一样。只能用strcpy函数将一个字符串复制到另一个字符数组中去。用赋值语句只能将一个字符赋给一个字符型变量或字符数组元素。
(5)可以用strncpy函数将字符串2中前面n个字符复制到字符数组1中去。
5.strcmp函数——字符串比较函数
一般形式为 strcmp(字符串1,字符串2)
说明:
(1)如全部字符相同,则认为两个字符串相等。
(2)若出现不相同的字符,则以第一对不相同的字符的比较结果为准
结果说明:
(1)如果字符串1与字符串2相同,则函数值为0。
(2)如果字符串1>字符串2,则函数值为一个正整数。
(3)如果字符串1<字符串2,则函数值为一个负整数。
一般比较形式为:
if(strcmp(str1,str2)>0)
printf(“yes”);
6.strlen函数——测字符串长度的函数
一般形式为strlen(字符数组)
7.strlwr函数——转换为小写的函数
一般形式为strlwr(字符串)
8.strupr函数——转换为大写的函数
一般形式为strupr(字符串)
注:在使用字符串处理函数时,应当在程序文件的开头用
#include
【例6.8】输入一行字符,统计其中有多少个单词,单词之间用空格隔开。
#include //编译预处理指令
#include //调用字符串函数库
int main() //定义主函数
{ //函数开始
char string[81]; //定义字符数组
int i, num = 0, word = 0; //定义整型并赋值
char c; //定义字符
gets_s(string); //输入字符赋给string数组
for (i = 0; (c = string[i]) != '\0'; i++) //for循环,直到检测到‘\0’结束
if (c == ' ') //如果c等于空格,word等于0
word = 0;
else if (word == 0) //当word等于0时,word等于1.num加1
{
word = 1;
num++;
}
printf("there are %d words in this line.\n", num); //输出结果
return 0; //函数值返回0
} //函数结束
结果为:
I am a student.
there are 4 words in this line.
注:因为visual studio 2019认为gets()是不安全的,所以要用gets_s()。
【例6.9】有三个字符串,要求找出其中“最大”者。
#include //编译预处理指令
#include //调用字符串函数库
int main() //定义主函数
{ //函数开始
char str[3][20]; //定义二维字符数组
char string[20]; //定义一维字符数组
int i; //定义整型i
for (i = 0; i < 3; i++) //for循环,输入三个字符串赋给str数组
gets_s(str[i]);
if (strcmp(str[0], str[1]) > 0) //比较,将大的字符串赋给string,下面也是重复此过程
strcpy_s(string, str[0]);
else
strcpy_s(string, str[1]);
if (strcmp(str[2], string) > 0)
strcpy_s(string, str[2]);
printf("\nthe largest string is:\n%s\n", string); //输出结果
return 0; //函数值返回0
} //函数结束
结果为:
holland
china
america
the largest string is:
holland
终于把第六章啃完了,起笔时是三月,现在已经到了四月,一个月终于学完了数组,离指针又近了一步,加油啊。因为后面几章内容较多,篇幅较长,遍新开一篇专门写习题,这篇只总结知识点,并且只是大致总结,细节方面还是要看书学习,这只是作为一个辅佐。
聿辞
2021年4月3日