1.分支和循环
▶关于scanf是否读取空格与回车问题:
当使用scanf读取整数(或其他非字符类型)的数据时,整数前和整数中的空格与回车符会被“吃掉”,最后的空格与回车符不会被“吃掉”,会进入缓冲区。
int x,y,z;
char ch;
scanf("%d %d %d", &x, &y, &z);//第一次输入“ 回车1 2回车3 回车”,scanf读取其中“1 2回车3”,3后面的空格与回车符进入缓冲区
printf("%d %d %d", x, y, z);//输出“1 2 3”
//此时缓冲区内有 空格+回车
scanf("%c", &ch);//直接读取缓冲区中的空格
printf("%c", ch);//输出“ ”
scanf("%c", &ch);//直接读取缓冲区中的回车符
printf("%c", ch);//输出“\n”
当读取字符%c类型数据时(%c本质为ASCII码,数字也会转为ASCII码),空格与回车符会被读取处理或进入缓冲区等待下次取用。
当读取字符串%s类型数据时,%s会遇到空格会停止并且空格及之后内容进入缓冲区(等同于%d对空格回车的处理)。
char ch;
while (1)
{
scanf("%c", &ch);//输入“ABC回车”进入缓冲区,scanf每次读取一个字符(包括最后一个回车符)
printf("%c\n", ch);//所以循环输出4次:“A\n” “B\n” “C\n” “回车\n”
}
▶getchar()
int x=0; //getchar()返回值为int
//char x; //也可以,ASCII码也是整数
while ((x = getchar()) != EOF) //ctrl+z → END OF FILE
{
putchar(x);
}
用getchar()清空缓存区:
int tmp=0;
while ((tmp = getchar()) != '\n')
{
;
}
2.函数
▶函数如果未定义返回类型,默认为int型。
▶函数的声明和定义
函数的定义在主函数之后,需要在使用前进行声明int Add(int, int),函数的声明一般放在头文件。
若A创建了add.h的头文件(内含函数声明),B使用的话需要引用头文件#include "add.h"。
项目名称右键-配置属性-常规-配置类型-应用程序(.exe)-静态库(.lib),编译后在Debug文件夹中生成了.lib文件。.lib静态库和.h头文件可以打包给其他用户使用,以代替.c源码和.h头文件的打包方式。
导入静态库:#pragma comment(lib,"sub.lib")
▶头文件的内容通常是:
1、库函数等头文件的包含
2、符号的定义
3、函数的声明
▶函数形参-数组
数组名即首元素地址,等同于传址。
void test(int arr[]) //[]内无需定义个数,形参与实参可以同名,形参arr本质是指针
{
int n = 0;
sizeof(arr); //计算的是指针的大小,32位对应4字节
n = sizeof(arr) / sizeof(arr[0]); //1,在函数内,这种方法无法知道元素的个数
printf("函数内%d\n", n);
}
int main()
{
int arr[] = { 1,2,3,4,5 };
int n = 0;
n = sizeof(arr)/sizeof(arr[0]); //5,计算数组元素个数
printf("%d\n", n);
test(arr); //传首地址
return 0;
}
3.数组
▶数组如果未完全初识化,空位补0(char类型对应ASCII码'\0')。
▶二维数组的初始化
int arr[][4] = { {1,2}, {3,4}, {4,5} };
//二维数组如果有初始化,行可以省略,列不能省略
▶数组名即首元素地址,但有2个例外:
1、sizeof(arr),arr表示整个数组。
2、&arr,arr表示整个数组,取出的是整个数组的地址。
printf("%p\n", &arr[0]);
printf("%p\n", arr); //与上等效,首元素地址
printf("%p\n", &arr); //虽然值与上面两个一样,但是意义不一样,这里是整个数组
printf("%p\n", &arr+1); //证明