2.4 循环结构
2.4.3 for
在C语言中不允许在for语句的表达式A里面定义变量(例如int i
的写法不被允许),但是在C++之中可以,因此这种写法需要被保存为.cpp
文件才能通过编译
2.5 数组
2.5.1 一维数组
一维数组的初始化,需要给出用逗号隔开的从第一个元素开始的若干个元素,并用大括号括住。后面未被赋值的元素将会由不同的编译器内部实现的不同而被赋予不同的初值(可能是很大的随机数),而一般情况默认初值为0
如果想要将整个数组都赋值为0,只需要把第一个元素赋值为0,或者只用一个大括号来表示。
int a[10] = {0}
int a[10] = { }
2.5.2 冒泡排序
#include<stdio.h>
int main()
{
int a[10] = {3,1,4,5,2};
for(int i=1;i<=4;i++)
{
for(int j=0;j<5-i;j++)
{
int temp = a[j];
a[j]= a[j+1];
a[j+1]=temp;
}
}
for(int i=0;i<5;i++)
{
printf("%d ",a[i]);
}
}
2.5.2 二维数组
和一维数组一样,二维数组在定义的时候也可以进行初始化。二维数组在初始化时候要按照第一维的顺序依次用大括号给出第二维初始化情况,然后将他们用逗号分隔,并用大括号全部括住,而这些被赋初值的元素之外德 部分将被默认赋值为0.
int a[5][6] = {{3,1,2},{8,4},{},{1,2,3,4,5}};
输出结果:
3 1 2 0 0 0
8 4 0 0 0 0
0 0 0 0 0 0
1 2 3 4 5 0
0 0 0 0 0 0
可以看到,第1,2,4行都赋予了初值,第三行使用{}跳过了(注意:如果没有大括号是无法通过编译的)。剩下的部分均被默认为0
如果数组大小较大(大概10^6级别),则需要将其定义在主函数外面,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外部申请的全局变量来自静态存储区,允许申请的空间较大。
2.5.4 memset——对数组中每一个元素赋相同的值
一般来说,给数组中的元素赋相同的值得方法有两种:memset函数
和fill函数
memset
函数的格式为:
memset (数组名 ,值 , sizeof(数组名));
不过要记住,使用memset
需要在程序的开头添加string.h
头文件,且只建议初学者使用memset
赋0
或者-1
。这是因为memset使用的是按字节赋值,即对每个字节赋相同的值,这样组成int
型的4个字节就被赋值了,而且由于0的二进制补码为0,-1的二进制补码为1,这样不同意弄错。但如果要对数组赋予其他的数字,那么请使用fill
函数
memset(a,0,sizeof(a));
memset(a,-1.sizeof(a));
2.5.5 字符数组
1.字符数组的初始化
和普通数组一样,字符数组也可以初始化,初始化如下:
char str[15]={'g','o','o','d',' ','s','t','o','r','y'};
输出结果如下:
good story
除此之外,字符数组还能够通过直接赋予初值来初始化,仅限于初始化,程序的其他位置不允许这样直接赋值整个字符串,示例如下:
char str[15]="good story!"
2.字符数组的输入和输出
字符数组就是char
的数组,当维度为1时可以作为字符串,当维度为2时可以作为字符串数组
字符数组除了可以使用scanf
来输入还能使用getchar
或者gets
字符数组除了可以使用printf
来输出还能使用putchat
或者puts
(1) scanf输入,printf输出
scanf
对字符类型有%c
和%s
两种类型(printf
同理,下同)
%c
用来输入单个字符,可以识别空格和换行
%s
用来输入字符串,将空格和换行作为输入结束的识别标志
#include<stdio.h>
int main()
{
char str[20];
scanf("%s",str);
printf("%s",str);
return 0;
}
输入数据:QAQ QAQ QAQ
输出数据:QAQ
(2)getchar和putchar
使用getchar
输入字符,使用putchar
输出字符
#include<stdio.h>
int main()
{
char str[5][5];
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
str[i][j]=getchar();
}
getchar();//这是为了将输入中每行末尾的换行符吸收掉
}
return 0;
}
(3)gets输入,puts输出
gets
用来输入一行字符串(注意:gets
识别换行符\n
作为输入结束,因此scanf
完一个整数后,如果要使用gets
,需要先用getchar
接收整数后的换行符),并将其放于一维数组(或者二维数组的一维)中;puts
用来输出一行字符串,即将一维数组(或者二维数组的一维)在界面上输出,并紧跟一个换行。示例如下:
#include<stdio.h>
int main()
{
char str1[20];
char str2[5][10];
gets(str1);
for(int i=0;i<3;i++)
{
gets(str2[i]);
}
puts(str1);
for(int i=0;i<3;i++)
{
puts(str2[i]);
}
return 0;
}
3.字符数组的存放方式
除此之外,在一维字符数组(或是二维字符数组的第二维)的末尾都有一个空字符\0
,用来表示存放的字符串的末尾。空字符\0
在使用gets
或scanf
输入字符串时会自动添加在输入字符串后面,并且占用一个字符位,而puts
与printf
就是通过识别\0
作为字符串的结尾来输出的。
特别提醒1: 结束符\0
的ASCII码为0,即空字符NULL,占用一个字符位,因此开字符数组的时候千万要记得字符数组的长度一定要比实际存储字符串的长度至少多1。注意,int型数组的末尾不需要加\0
,只有char
型数组需要。还需要注意,\0
和空格
不是一个东西,空格的ASCII码为32
特别提醒2: 如果不是使用scanf
函数的%s
格式或者gets
函数输入字符串(例如使用getchar
),请一定要在输入的每个字符串后加入\0
,否则printf
和puts
输出字符串会因为无法识别字符串末尾而输出一大堆乱码
2.5.6 string.h头文件
1.strlen()
strlen
函数可以得到字符数组中第一个\0
前的字符的个数,其格式如下:
strlen(字符数组);
2.strcmp()
strcmp
函数返回两个字符串大小的比较结果,比较原则是按字典序,其格式如下:
strcmp(字符数组1,字符数组2)
①如果字符数组1<字符数组2,则返回一个负整数
②如果字符数组1==字符数组2,则返回0
③如果字符数组1>字符数组2,则返回一个正整数
3.strcpy()
strcpy
函数是将一个字符串复制给另一个字符串,其格式如下:
strcpy(字符数组1,字符数组2);
注意:是把字符数组2复制给字符数组1,这里的“复制”包括了结束符\0
4.strcat()
strcat()
可以将一个字符串接到另一个字符串的后面,其格式如下:
strcat(字符数组1,字符数组2)
注意是将字符数组2接到字符数组1的后面
2.5.7 sscanf与sprintf
sscanf
与sprintf
与上面的格式是相同的,只不过把screen
换成了字符数组(假设定义了一个char
数组str[100]
),如下所示:
sscanf(str,"%d",&n);//将字符数组str中的内容以"%d"的格式写到n中
sprintf(str,"%d",n);//将n以"%d"的格式写到str字符数组中(还是从右至左)
来一个复杂一点的应用:
#include<stdio.h>
int main()
{
int n;
double db;
char str[100]="2048:3.14,hello",str2[100];
sscanf(str,"%d:%lf,%s",&n,&db,str2);
printf("n=%d,db=%.2f,str2=%s\n",n,db,str2);
n=12;
db=3.1415;
char str3[100],str4[100]="good";
sprintf(str3,"%d:%.2f,%s",n,db,str4);
printf("str=%s\n",str3);
return 0;
}
运行结果:
n=2048,db=3.14,str2=hello
str=12:3.14,good