一、学习概览
2.5.1一维数组
- 数组:长度为n,下标为0~(n-1)。
- 只要赋初值,没被赋值的默认初值为0;若未初始化,每个元素会是一个随机数。
- 给整个数组赋初值0:
int a[10]={0};
int a[10]={};
//或者memset函数
- 递推:根据一些条件,不断让后一位的结果由前一位或前若干位计算得来。
2.5.2冒泡排序
- 冒泡排序的比较次数:(假设排序的数字数为n)1+2+…+(n-1)
- 特别提醒:如果数组大小较大(大概10^6级别),则需要将其定义在主函数外面,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外部申请的全局变量来自静态存储区,允许申请的空间较大。
2.5.4memset
- memset函数:初学者只建议赋0或-1。其他用fill。
2.5.5字符char数组
- 字符数组就是char数组。
- 对于scanf输入-printf输出,只有%c格式能够识别空格+换行并将其输入,%s格式以及其他(如%d)通过空格/换行来识别一个字符串的结束。
- 对于getchar输入-putchar输出,不需要格式控制符(都是char类型元素)。遇到换行/空格也会输出。
getchar();
putchar('\n');
-
gets识别换行符\n作为输入结束——scanf完一个整数后,如果要使用gets,需要先用getchar接收整数后的换行符。puts输出字符串后,会紧跟一个换行。
-
输入输出的真正含义是:输入输出并存起。
-
空字符\0——表示存放的字符串的结尾。在使用gets或scanf时自动添加至末尾,并占用一个字符位,puts和printf通过识别\0来输出。
特别提醒1:①字符数组的长度>=实际存储字符串的长度+1;②只有char型数组末尾需要加\0,int型不需要;③\0和空格不同,\0的ASCII码是0(空字符NULL),空格的ASCII码是32。
特别提醒2:如果不是使用scanf的%s格式或gets函数输入字符串(例如使用getchar),一定要在输入的每个字符串后加“\0”,否则printf和puts会因无法识别字符串末尾而输出一大堆乱码。见代码2.27。 -
ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符 [1] 。
2.5.6string.h头文件
- string.h包含的用于字符数组的函数:(使用时要在程序开头加上string.h)
①strlen()
②strcmp()
按字典序(a<b<c<…<z)。若str1<str2,返回负整数;str1==str2,返回0;str1>str2,返回正整数。
③strcpy()
把str2复制给str1,“复制”包括结束符\0。
④strcat()
str2接到str1后面。
#include <string.h>
int len=strlen(str); //得到字符数组中第一个\0前的字符的个数
int cmp=strcmp(str1,str2);//返回两个字符串大小的比较结果
if(cmp<0) printf("str1<str2\n");
else if(cmp>0) printf("str1>str2\n");
else printf("str1==str2\n");
strcpy(str1,str2);//把一个字符串复制给另一个字符串
strcat(str1,str2);//把一个字符串接到另一个字符串后面
2.5.7sscanf与sprintf
- scanf与printf的另一种写法:(scanf从左至右,printf从右至左)
scanf("%d",&n);
scanf(screen,"%d",&n);
printf("%d",n);
printf(screen,"%d",n); //screen是屏幕
- sscanf与sprintf:(sscanf从左至右,sprintf从右至左。注意代码行2与行4的区别。)
sscanf(str,"%d",&n);
printf("%d",n); //初始化str,写到n里
sprintf(str,"%d",n); //字符数组str
printf("%d",str); //初始化n,写到str里
- sscanf还支持正则表达式。
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。许多程序设计语言都支持利用正则表达式进行字符串操作。
二、代码分析
2.23 冒泡排序
#include <stdio.h>
int main(){
int a[10]={3,1,4,5,2};
for(int i=1;i<=4;i++){ //进行n-1趟
//第i趟从a[0]到a[n-i-1]都与它们下一个数比较
for(int j=0;j<5-i;j++){
if(a[j]>a[j+1]){ //如果左边的数更大,则交换a[j]和a[j+1]
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<5;i++){
printf("%d",a[i]);
}
return 0;
}
思考:
把i打成了1。
2.24 三维数组自增1
#include <stdio.h>
int main(){
int a[3][3][3];
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int k=0; k< 3; k++){
scanf("%d",&a[i][j][k]); //输入三维数组a的元素
a[i][j][k]++; //自增
}
}
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int k=0; k< 3; k++){
printf("%d\n",&a[i][j][k]); //输出三维数组a的元素
}
}
}
return 0;
}
这…什么鬼
2.25 memset函数
#include <stdio.h>
#include <string.h>
int main(){
int a[5]={1,2,3,4,5};
//赋初值0
memset(a, 0, sizeof(a));
for(int i=0;i<5;i++){
printf("%d", a[i]);
}
printf("\n");
//赋初值-1
memset(a,-1, sizeof(a));
for(int i=0;i<5;i++){
printf("%d", a[i]);
}
printf("\n");
return 0;
}
把-1改成1后:
#include <stdio.h>
#include <string.h>
int main(){
int a[5]={1,2,3,4,5};
//赋初值1
memset(a,1, sizeof(a));
for(int i=0;i<5;i++){
printf("%d", a[i]);
}
printf("\n");
return 0;
}
2.26 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(); //这句是为了把输入中每行末尾的换行符吸收掉
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
putchar(str[i][j]);
}
putchar('\n');
}
return 0;
}
不加行8:
不加行14:
完整结论:
2.27 使用getchar,每个字符串后要加“\0”
#include <stdio.h>
int main(){
char str[15];
for(int i=0;i<5;i++){
str[i]=getchar();
}
puts(str);
return 0;
}
不加也没有乱码呢。