大家好,如果您还对深入解析C语言中的数组操作与技巧不太了解,没有关系,今天就由本站为大家分享深入解析C语言中的数组操作与技巧的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!
组、字符数组、指针数组、结构体数组等各种类别。
本章介绍了数值数组和字符数组,其余的将在后续章节中介绍。数组类型说明在C语言中使用数组之前,必须先进行类型说明。数组声明的一般形式
公式为:类型说明符数组名[常量表达式],其中,类型说明符是任意基本数据类型或构造数据类型。数组名称是用户定义的数组标识符。方括号中的常量表达式表示数据元素的数量,也称为数组的长度。
例如:
整数a[10];表示整数数组a,有10个元素。
浮点数b[10],c[20];这意味着真实数组b 有10 个元素,真实数组c 有20 个元素。
字符ch[20];表示字符数组ch,有20个元素。
描述数组类型时应注意以下几点:
1、数组的类型实际上是指数组元素的值类型。对于同一个数组,其所有元素的数据类型都是相同的。
2. 数组名的书写规则应符合标识符的书写规则。
3、数组名不能与其他变量名相同,例如:
无效主()
{
整数a;
浮动a[10];
……
}
是错误的。
4、方括号内的常量表达式表示数组元素的个数。例如,a[5]表示数组a有5个元素。但它的下标是从0开始的。因此,这五个元素分别是a[0]、a[1]、a[2]、a[3]、a[4]。
5、变量不能用在方括号中来表示元素的数量,但可以是符号常量或常量表达式。例如:
#定义FD 5
无效主()
{
int a[3+2],b[7+FD];
……
}
是合法的。但下面的解释是错误的。
无效主()
{
整数n=5;
整数a[n];
……
}
6. 允许在同一类型规范中指定多个数组和多个变量。
例如:int a,b,c,d,k1[10],k2[20];
数组元素的表示方法
数组元素是组成数组的基本单位。数组元素也是变量,由数组名称后跟下标来标识。下标表示数组中元素的序号。数组元素的一般形式为:数组名[下标] 其中下标只能是整型常量或整型表达式。如果是小数,C编译器会自动四舍五入。例如,a[5]、a[i+j]、a[i++]都是合法的数组元素。数组元素通常也称为下标变量。在使用下标变量之前必须先定义数组。在C语言中,下标变量只能一一使用,不能一次性引用整个数组。例如,要输出一个有10个元素的数组,必须使用循环语句将每个下标变量一一输出:
for(i=0; i10; i++)printf("%d",a[i]);下面的写法不是在一条语句中输出整个数组,而是错误的: printf("%d",a);
无效主()
{
整数i,a[10];
for(i=0;i10;)
a[i++]=2*i+1;
for(i=9;i=0;i--)
printf("%d",a[i]);
printf("/n%d %d/n",a[5.2],a[5.8]);} for(i=0;i10;)
a[i++]=2*i+1; for(i=9;i=0;i--)
printf("%d",a[i]); printf("/n%d %d/n",a[5.2],a[5.8]);
在这个例子中,使用一个循环语句将奇数发送到数组a的每个元素,然后使用第二个循环语句从大到小输出每个奇数。在第一个for 语句中,省略了表达式3。下标变量中使用表达式i++来修改循环变量。当然,第二个for语句也可以这样做。 C语言允许使用表达式来表达下标。程序中的最后一个printf 语句输出a[5] 的值两次。可见,当下标不是整数时,会自动四舍五入。给数组赋值除了使用赋值语句对数组元素一一赋值之外,还可以使用初始化赋值和动态赋值。数组初始化赋值数组初始化赋值是指在数组声明时给数组元素赋值初始值。数组初始化是在编译阶段执行的。这将减少运行时间并提高效率。
初始化赋值的一般形式为:静态类型说明符数组名[常量表达式]={value, value.value};其中static 表示静态存储类型,
C语言规定只能对静态存储数组和外部存储数组进行初始化和赋值(静态存储和外部存储的概念在第5章介绍)。 { } 中的每个数据值都是每个元素的初始值。
用逗号分隔值。例如: static int a[10]={ 0,1,2,3,4,5,6,7,8,9 };
相当于a[0]=0;a[1]=1.a[9]=9;
C语言对于数组的初始赋值也有如下规定:
1. 只能给某些元素赋初始值。当{ }中的值的个数小于元素的个数时,只对前部分元素赋值。例如:static int a[10]={0,1,2,3,4};表示只有a[0]~a[4]这5个元素被赋值,接下来的5个元素自动被赋值0。
2.只能对元素一一赋值,不能对数组整体赋值。例如,给所有十个元素赋值1只能写成: static int a[10]={1,1,1,1,1,1,1,1,1,1};但不能写成: static int a[10]=1;
3. 如果没有为可初始化数组分配初始值,则所有元素的值为0。
4. 如果所有元素都被赋值,则数组描述中不需要给出数组元素的个数。例如:static int a[5]={1,2,3,4,5};可以写成: static int a[]={1,2,3,4,5};动态赋值可以在程序执行过程中进行,动态地给数组赋值。这时可以用循环语句配合scanf函数对数组元素进行一一赋值。
无效主()
{
int i,max,a[10];
printf("输入10个数字:/n");
for(i=0;i10;i++)
scanf("%d",a[i]);
最大值=a[0];
for(i=1;i10;i++)
if(a[i]max) max=a[i];
printf("最大值=%d/n",max);
}
for(i=0;i10;i++)
scanf("%d",a[i]);
最大值=a[0];
for(i=1;i10;i++)
if(a[i]max) max=a[i];
printf("最大值=%d/n",max);
本示例程序中的第一个for 语句将10 个数字逐一输入到数组a 中。然后将a[0]发送到max。第二个for语句中,a[1]到a[9]与max的内容一一比较。如果大于max的值,则将下标变量发送到max,因此max始终是所比较的下标变量中最大的。比较结束,输出max的值。
无效主()
{
int i,j,p,q,s,a[10];
printf("/n 输入10 个数字:/n");
for(i=0;i10;i++)
scanf("%d",a[i]);
for(i=0;i10;i++){
p=i;q=a[i];
for(j=i+1;j10;j++)
如果(q
如果(i!=p)
{s=a[i];
a[i]=a[p];
a[p]=s; }
printf("%d",a[i]);
}
}
for(i=0;i10;i++)
scanf("%d",a[i]);
for(i=0;i10;i++){
p=i;q=a[i];
for(j=i+1;j10;j++)
如果(q
如果(i!=p)
{ s=a[i];
a[i]=a[p];
a[p]=s; }
printf("%d",a[i]);
}
该示例程序使用两个并行的for 循环语句,并且第二个for 语句中嵌套了一个循环语句。第一个for语句用于输入10个元素的初始值。第二个for语句用于排序。本程序的排序采用逐一比较的方法。在第i个循环中,将第一个元素的下标i赋给p,将下标变量值a[i]赋给q。然后进入一个小循环,将a[i+1]到最后一个元素的每个元素与a[i]进行比较。如果有比a[i]大的,则将其下标发送给p,并将元素值发送给q。循环结束后,p为最大元素的下标,q为元素值。如果此时ip,则说明p和q的值不再是进入小循环之前赋值的值,那么a[i]和a[p]的值被交换。此时a[i]就是排序后的元素。输出这个值后,进入下一个循环。对i+1 之后的元素进行排序。
二维数组
前面介绍的数组只有一个下标,称为一维数组,其数组元素也称为单下标变量。在实际问题中,很多量都是二维或多维的,因此C语言允许构造多维数组。多维数组元素有多个下标来标识其在数组中的位置,因此也称为多下标变量。本节只介绍二维数组。多维数组可以类推二维数组。二维数组类型规范二维数组类型规范的一般形式为:
类型说明符数组名[常量表达式1][常量表达式2]…;
常数表达式1表示第一维下标的长度,常数表达式2表示第二维下标的长度。例如:
int a[3][4];图示了一个三行四列的数组。数组名为a,下标变量类型为整型。该数组中有34个下标变量,分别是:a[0][0],a[0][1],a[0][2],a[0][3]
a[1][0],a[1][1],a[1][2],a[1][3]
a[2][0],a[2][1],a[2][2],a[2][3]
二维数组在概念上是二维的,也就是说它的下标在两个方向上变化,并且下标变量在数组中的位置也是在一个平面上,而不是像一维数组那样只是一个向量。然而,实际的硬件存储器是连续寻址的,即存储器单元在一维上线性排列。一维内存中存储二维数组有两种方式:一种是按行排列,即放置完一行后,依次放置第二行。另一种是按列排列,即放置一列后,依次放置第二列。在C语言中,二维数组按行排列。在图4.1中,它是按行顺序存储的,首先存储行a[0],然后存储行a[1],最后存储行a[2]。每行的四个元素也是按顺序存储的。由于数组a 被描述为
int类型,该类型占用两个字节的内存空间,因此每个元素占用两个字节(图中每个单元格为一个字节)。
二维数组元素的表示方法
二维数组的元素也称为双下标变量,其表达形式为:数组名[下标][下标]其中下标应为整型常量或整型表达式。例如:a[3][4]表示数组a的三行四列的元素。下标变量和数组声明在形式上有些相似,但两者的含义却完全不同。数组描述的方括号中给出的是某维的长度,即下标的最大值;数组元素中的下标是该元素在数组中的位置标识。前者只能是常量,后者可以是常量、变量或表达式。
一个学习小组有5人,每人有三门课程的考试成绩。求全组每个科目的平均分以及每个科目的总体平均分。
课程年级名称数学CDBASE
张8075 92
王6165 71
李5963 70
赵8587 90
周7677 85
可以设置一个二维数组a[5][3]来存储五个人三门课程的成绩。然后设置一个一维数组v[3]来存储每个科目的平均分,令变量l为全组每个科目的总平均分。编程如下:
无效主()
{
int i,j,s=0,l,v[3],a[5][3];
printf("输入分数/n");
for(i=0;i3;i++){
for(j=0;j5;j++)
{ scanf("%d",a[j][i]);
s=s+a[j][i];}
v[i]=s/5;
s=0;
}
l=(v[0]+v[1]+v[2])/3;
printf("math:%d/nc languag:%d/ndbase:%d/n",v[0],v[1],v[2]);
printf("总计:%d/n",l);
} for(i=0;j3;i++)
for(j=0;j5;j++)
{ scanf("%d",a[j][i]);
s=s+a[j][i];}
v[i]=s/5;
s=0;
}
l=(v[0]+v[1]+v[2])/3;
该程序首先使用双循环。在内循环中,依次读取每个学生在某门课程中的成绩,并将这些成绩累加起来。退出内循环后,将累计分数除以5并发送给v[i]。这就是课程。平均分。外循环一共循环3次,计算出三门课程每门课程的平均分,存入v数组中。退出外循环后,将v[0]、v[1]、v[2]相加并除以3,得到各科目的总体平均分。最后根据题意输出各个分数。
二维数组的初始化
二维数组的初始化还会在类型指定期间为每个下标变量分配一个初始值。二维数组可以按行分段赋值,也可以按行连续赋值。例如,对于数组a[5][3]:
1、按行分段赋值可以写成static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87 , 90},{76,77,85} };
2、按行连续赋值可以写为static int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85 };
这两个初始值赋值的结果是完全相同的。
无效主()
{
int i,j,s=0,l,v[3];
静态int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},
{85,87,90},{76,77,85} };
for(i=0;i3;i++)
{ for(j=0;j5;j++)
s=s+a[j][i];
v[i]=s/5;
s=0;
}
l=(v[0]+v[1]+v[2])/3;
printf("math:%d/nc languag:%d/ndbase:%d/n",v[0],v[1],v[2]);
printf("总计:%d/n",l);
}
二维数组的初始化赋值还有如下指令:
1.只能给部分元素赋初始值,未赋初始值的元素会自动取值0。
例如:static int a[3][3]={{1},{2},{3}};给每行第一列元素赋值,未赋值的元素取值为0。赋值后每个元素的值为:1 0 02 0 03 0 0
static int a [3][3]={{0,1},{0,0,2},{3}};赋值后元素值为0 1 00 0 23 0 0
2.如果给所有元素赋初始值,则不需要给出第一维的长度。
例如: static int a[3][3]={1,2,3,4,5,6,7,8,9};可以写成: static int a[][3]={1,2, 3,4,5,6,7,8,9};
数组是一种构造类型的数据。二维数组可以看作是一维数组的嵌套数组。假设一维数组的每个元素是另一个数组,形成一个二维数组。当然,前提是元素类型必须相同。根据这样的分析,一个二维数组也可以分解为多个一维数组。 C语言允许这样分解一个二维数组a[3][4],它可以分解为三个一维数组,数组名称分别为a[0]、a[1]、a[2]。这三个一维数组就可以使用,无需进一步解释。这三个一维数组有4 个元素。例如:一维数组a[0]的元素为a[0][0],a[0][1],a[0][2],a[0][3]。必须强调的是,a[0]、a[1]、a[2]不能用作下标变量。它们是数组名,而不是简单的下标变量。
字符数组
用于存储字符的数组称为字符数组。字符数组类型规范的格式与前面介绍的数值数组相同。例如:char c[10];由于字符和整数类型很常见,因此也可以定义为int c[10],但此时每个数组元素占用2 字节内存单元。字符数组也可以是二维或多维数组,例如:char c[5][10];是一个二维字符数组。字符数组还允许在类型指定期间进行初始分配。例如: static char c[10]={`c`,` `,`p`,`r`,o`,g`,r`,`a`,`m`};赋值后每个元素的值为: Array C c[0]c[1]c[2]c[3]c[4]c [5]c[6]c[7]c[8]c[9 ] 其中c[9]没有赋值,系统自动赋值为0。为所有元素分配初始值时也可以省略长度规范。例如: static char c[]={`c`,``,`p`,`r`,`o`,`g`,`r`,`a`,`m`};此时C数组的长度自动设置为9。
主要的()
{
整数i,j;
char a[][5]={{"B","A","S","I","C",},{"d","B","A","S"," E"}};
for(i=0;i=1;i++)
{
对于(j=0;j=4;j++)
printf("%c",a[i][j]);
printf("/n");
}
}
由于本例中的二维字符数组的所有元素在初始化时都被赋予了初始值,因此不需要指定一维下标的长度。 C语言中没有专门的字符串变量。字符数组通常用来存储字符串。在2.1.4节介绍字符串常量时,指出字符串总是以"/0"结尾。因此,当字符串存储在数组中时,终止符"/0"也存储在数组中,并用作字符串是否结束的标志。有了"/0"标志,就不需要使用字符数组的长度来确定字符串的长度。
C 语言允许使用字符串对数组进行初始化和赋值。例如:
static char c[]={"c", " ", "p", "r", "o", "g", "r", "a", "m"};可以写成:
static char c[]={"C程序"};或删除{} 并写为:
sratic char c[]="C程序";
字符串方式赋值比逐个字符赋值多占用一个字节,用于存储字符串结束标志"/0"。上述数组c在内存中的实际存储情况是:C程序/0`/0"是C编译系统自动添加的。由于使用了‘/0’标志,用字符串赋初值时一般不需要指定数组的长度,系统会自行处理。采用字符串方式后,字符数组的输入输出将变得简单方便。除了上面用字符串赋初始值的方法外,还可以使用printf函数和scanf函数一次性输出和输入字符数组中的字符串,而不是使用循环语句分别输入和输出人物一一。
无效主()
{
static char c[]="BASIC/ndBASE";
printf("%s/n",c);
printf("%s/n",c);
请注意,在本例中的printf 函数中,使用的格式字符串是“%s”,这意味着输出是字符串。可以在输出表列中给出数组名称。不能写成: printf("%s",c[]);
无效主()
{
字符st[15];
printf("输入字符串:/n");
scanf("%s",st);
printf("%s/n",st);
} 字符st[15];
在本例中,由于数组长度定义为15,因此输入字符串长度必须小于15,才能留下一个字节用于存储字符串结束标志“/0”。需要注意的是,对于字符数组,如果不进行初始化赋值,则必须指定数组长度。还需要注意的是,使用scanf函数输入字符串时,字符串中不能包含空格,否则会以空格作为字符串的终止符。例如,运行例4.8时,当输入字符串包含空格时,操作情况为:输入字符串:这是一本书this。从输出结果可以看出,空格后面的字符无法输出。为了避免这种情况,可以多设置几个字符数组来存储段中包含空格的字符串。该程序可以重写如下:
课
无效主()
{
字符st1[6],st2[6],st3[6],st4[6];
printf("输入字符串:/n");
scanf("%s%s%s%s",st1,st2,st3,st4);
printf("%s %s %s %s/n",st1,st2,st3,st4);
}
该程序分别建立了四个数组,将输入行字符的空格段分别装入四个数组中。然后分别输出这四个数组中的字符串。前面介绍过,scanf 的每个输入项必须以地址的形式出现,如a、b 等。但在例4.8 中,它以数组名的形式出现。这是为什么呢?这是因为C语言规定数组名代表数组的首地址。整个数组是一个从首地址开始的连续的内存单元。如果有一个字符数组char c[10],它在内存中可以表示如图4.2所示。假设数组c的首地址是2000,也就是说单元c[0]的地址是2000,那么数组名c就代表这个首地址。因此,c之前不能添加地址运算符。例如写scanf("%s",c);是错误的。执行函数printf("%s",c)时,根据数组名c找到首地址,然后逐个输出数组中的每个字符,直到遇到字符串终止标志"/0"。
常用字符串函数
C语言提供了丰富的字符串处理函数,大致可以分为几类:字符串输入、输出、合并、修改、比较、转换、复制和搜索。使用这些函数可以大大减轻编程的负担。用于输入和输出的字符串函数在使用前应包含头文件“stdio.h”;当使用其他字符串函数时,应包含头文件“string.h”。以下是一些最常用的字符串函数。
1、字符串输出函数puts 格式:puts(字符数组名) 功能:将字符数组中的字符串输出到显示器上。也就是将字符串显示在屏幕上
#include"stdio.h"
主要的()
{
static char c[]="BASIC/ndBASE";
看跌期权(c);
}
static char c[]="BASIC/ndBASE";
看跌期权(c);
从程序中可以看出,puts函数中可以使用转义字符,因此输出结果变成两行。 puts函数可以完全被printf函数替代。当需要以某种格式输出时,通常使用printf函数。
2、字符串输入函数gets 格式: gets(字符数组名) 功能: 从标准输入设备键盘输入一个字符串。该函数获取一个函数值,该值是字符数组的首地址。
#include"stdio.h"
主要的()
{
字符st[15];
printf("输入字符串:/n");
获取(st);
看跌期权(st);
}
可以看到,当输入字符串包含空格时,输出仍然是整个字符串。说明一下,gets函数不使用空格作为字符串输入结束的标志,而只使用回车作为输入结束。这与scanf 函数不同。
3、字符串连接函数strcat 格式:strcat(字符数组名1,字符数组名2) 功能:将字符数组2中的字符串连接到字符数组1中的字符串末尾,并删除字符串1后面的字符串字符串标志“ /0”。该函数的返回值为字符数组1的首地址。
#include"字符串.h"
主要的()
{
static char st1[30]="我的名字是";
int st2[10];
printf("请输入你的名字:/n");
获取(st2);
strcat(st1,st2);
投入(st1);
}
static char st1[30]="我的名字是";
int st2[10];
printf("请输入你的名字:/n");
获取(st2);
strcat(st1,st2);
该程序连接初始化的字符数组和动态分配的字符串。需要注意的是,字符数组1要定义足够的长度,否则连接的字符串无法完全加载。
4、字符串复制函数strcpy 格式:strcpy(字符数组名1,字符数组名2) 功能
:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“/0”也一同拷贝。字符数名2, 也可以是一个字符串常量。这时相当于把一个字符串赋予一个字符数组。 #include"string.h" main() { static char st1[15],st2[]="C Language"; strcpy(st1,st2); puts(st1);printf("/n");好了,关于深入解析C语言中的数组操作与技巧和的问题到这里结束啦,希望可以解决您的问题哈!
【深入解析C语言中的数组操作与技巧】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
C语言数组真是基础中的基础啊!
有19位网友表示赞同!
终于有机会学习一下数组详解了!
有14位网友表示赞同!
想深入了解下数组在C语言中的运作机制。
有18位网友表示赞同!
这篇文章能帮我把数组的用法搞清楚吗?
有8位网友表示赞同!
以前只会简单使用数组,现在要好好学学它的细节。
有6位网友表示赞同!
看看这篇详解能不能让我写出更高效的程序代码。
有19位网友表示赞同!
学习C语言やっぱり离不开数组这一关口。
有12位网友表示赞同!
感觉数组操作还是蛮有技巧的,希望能有所收获。
有11位网友表示赞同!
期待这篇文章能把数组的概念讲解得透彻明白!
有5位网友表示赞同!
准备好好跟着文章一步步啃下数组的知识点。
有6位网友表示赞同!
对C语言数组的多种使用方式一直不太懂,希望能解决我的疑惑。
有11位网友表示赞同!
学习好C语言中的数组是入门到精通的必经之路。
有6位网友表示赞同!
这篇文章能让我更好地理解数组的底层实现吗?
有16位网友表示赞同!
平时写代码总觉得数组的使用不够灵活,希望这篇详解能给我启发。
有13位网友表示赞同!
想要学好C语言,掌握数组的原理是关键。
有18位网友表示赞同!
我对指针的理解还不太完善,希望能通过文章学习到相关知识。
有17位网友表示赞同!
终于找到一篇讲解C语言数组的详细的文章了!
有15位网友表示赞同!
这篇文章能帮我提高程序设计的效率吗?
有6位网友表示赞同!
感觉学习C语言数组要从基础概念开始着手才能系统理解。
有14位网友表示赞同!