【C语言】一些常见概念
目录
一、32个关键字
二、ASCII码
三、字符串和结束标志\0
四、变量存储和sizeof计算变量所用空间
五、循环输入
六、printf
七、scanf
一、32个关键字
auto break case char const continue default do double else enum extern
float for goto if int long register return short signed sizeof static
struct switch typedef union unsigned void volatile while
- 数据类型有关:void int char float double long short unsigned signed extern(外部变量) static(静态) const(修饰常量) 12个
- 分支循环有关:do while for if else switch case break default continue goto return 12个
- 其他:8个
二、ASCII码
- 字符A~Z的ASCII码值从65~90
- 字符a~z的ASCII码值从97~122
- 对应的大小写字符(a和A)的ASCII码值的差值是32
- 数字字符0~9的ASCII码值从48~57
- 回车\r 的ASCII值是:13
- 换行\n 的ASCII值是:10
- 在这些字符中ASCII码值从0~31,这32个字符是不可打印字符,无法打印在屏幕上观察
三、字符串和结束标志\0
字符串是一组字符,即char arr[]=”abc”
""引字符串,用%s
''引字符,用%c
对于字符串"abcdef",我们实际上看到了6个字符:a,b,c,d,e,f,但是实际上在末尾还隐藏一个 \0 的 转义字符, \0 是字符串的结束标志。所以我们在使用库函数 printf() 打印字符串或者 strlen() 计算字符串长度的时候,只统计\0之前的字符个数,遇到\0 的时候就自动停止了。
数组使用""和使用{}存储字符串有区别,使用{}存储字符串末尾默认不会加上\0(想要正常使用需要自行在最后补上'\0'),在实际打印中会一直往后寻找到\0为止,即越界访问问题
四、变量存储和sizeof计算变量所用空间
- 局部变量和函数参数保存在栈区
- 程序开辟的空间存储在堆区
- 全局变量和静态变量存储在静态区
对于不同的数据类型在内存中到底占多少byte(字节)可以使用“sizeof”操作符得到结果,sizeof返回类型是size_t,即无符号整型,sizeof中表达式不会进行计算
8bit=1byte
char 占1byte
short 占2byte
int 占4byte
uint16_t 16指16bit,即2byte,即无符号short,取值范围0~2^16, 即0~65535
int16_t 也是short,不过有符号,取值范围2^-8~2^8, 即-32768~32767
对于大部分数据类型,不写signed也可以,默认是signed类型
对于char类型,默认是有符号还是无符号取决于编译器
五、循环输入
while( scanf() != EOF )
scanf有返回类型,返回的是成功读取的变量个数,当读取失败或者读取结束时会返回-1,即EOF,使用时可以按ctrl+z或ctrl+c中断执行,实现提前结束
六、printf
printf的一些占位符可表示的变量类型
- %c 字符
- %s 字符串
- %d 十进制整数
- %f 十进制浮点数
- %x 十六进制整数
- %a 十六进制浮点数
- %p 指针
限定宽度打印
右对齐
printf("%5d",123);
输出的最小宽度是5,即打印出来的123不足5个,会在前面补上两个空格
如果数据超过5,依旧能正常打印超过长度的数字
浮点类型与之类似,不过在限定宽度打印时会把小数点也算上
左对齐
printf("%-5d",123);
输出的最小宽度是5,即打印出来的123后面会补两个空格
想让输出结果无论正负都有自己的符号
在%后加上+号
printf("%+d",a);
限定小数位数
在%后,在f前,加上.和想要保留的位数
printf("%.2f",a);
既要限定宽度又要限定保留位数
printf("%6.2f",a);
6表示最小宽度是6
.2表示保留两位小数
可以使用*作为占位符来控制宽度和位数
printf("%*.*f",6,2,a);
输出部分字符
printf("%.5s","hello world!");
只会打印前5个字符,后面的不会打印出来
七、scanf
- scanf() 处理用户输入的原理是,用户的输⼊先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。 解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
- scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。 所以,用户输入的数据之间,有⼀个或多个空格不影响 scanf() 解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。但是不建议一个空格也不加,这样会导致识别不了输入的数据
- scanf() 的返回值是一个整数,表示成功读取的变量个数。 如果没有读取任何项,或者匹配失败,则返回 0 。如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF。
- 在VS环境中按3次 ctrl+z ,才结束了输入。 如果一个数字都不输入,直接按3次 ctrl+z ,输出是-1,也就是EOF
-
变量前面必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址, 即将变量的地址指向用户输入的值。 如果这里的变量是指针变量(比如字符串变量),那就不用加 & 运算符。
-
在scanf的所有占位符之中,除了 %c 以外,都会自动忽略起首的空白字符。 %c 不忽略空白字符,总是返回当前第⼀个字符,无论该字符是否为空格(因为空格也是字符)。即对于字符的输入,""内是什么样的格式,用户就需要输入一模一样的格式
如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上一个空格,表示跳过零个或多个空白字符。
特别说明占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。 因为 %s 不会包含空白字符,所以无法用来读取多个单词,除非多个 %s ⼀起使用。这也意味着, scanf() 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外, scanf() 遇到 %s 占位符,会在字符串变量末尾存储⼀个空字符 \0 。
-
scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成 %[m]s ,其中的 [m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。针对上述情况,VS2022专门提供了一个自己软件的函数scanf_s(),但是不建议使用,因为这个函数不是C语言官方提供的函数声明,只能在VS的环境下使用才不会报错,降低了代码的可移植性
-
赋值忽略符*
有时,用户的输入可能不符合预定的格式。
scanf("%d-%d-%d",&year,&mouth,&day);
用户输入需要严格按照上述格式用-分开,否则不能正确读取
为防止上述情况,使用赋值忽略符*,只要将其加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃
scanf("%d%*c%d%*c%d",&year,&mouth,&day);
被赋值忽略符*修饰的字符%*c不论是什么在解析后都会被丢弃,所以不需要用变量接收