你该逆袭了
第4章:重点摘录
五、scanf( )
1、使用 scanf( )
#include <stdio.h> int main() { int age = 0; float assets = 0; char pet[30] = { 0 }; printf("Enter your age,assets,and favourite pet.\n"); scanf("%d %f", &age, &assets); scanf("%s", pet); printf("%d $%.2f %s\n", age, assets, pet); return 0; } // scanf()函数使用 空白(换行符、制表符、空格)把输入分成多个字段。 // 在 依次把转换说明和字段匹配 时跳过空白。 // 注意:只要在每个输入项之间输入 至少一个 换行符、空格、制表符 即可,可以在一行或多行输入。 // 唯一例外的是 %c 转换说明。 // 根据 %c ,scanf() 会读取每个字符,包括 空白。 // scanf() 函数所用的转换说明与 printf() 函数 几乎相同。 // 主要区别: // 对于 float类型 和 double类型 , // printf() 都使用 %f、%e、%E、%g 和 %G 转换说明。 // 而 scanf() 函数 只把它们用于 float 类型, // 对于 double 类型 时,要使用 l 修饰符。
scanf()函数使用 空白(换行符、制表符、空格)把输入分成多个字段。
在 依次把转换说明和字段匹配 时跳过空白。
注意:只要在每个输入项之间输入 至少一个 换行符、空格、制表符 即可,可以在一行或多行输入。
唯一例外的是 %c 转换说明。
根据 %c ,scanf() 会读取每个字符,包括 空白。
scanf() 函数所用的转换说明与 printf() 函数 几乎相同。
主要区别:
对于 float类型 和 double类型 ,
printf() 都使用 %f、%e、%E、%g 和 %G 转换说明。
而 scanf() 函数 只把它们用于 float 类型,
对于 double 类型 时,要使用 l 修饰符。
(1)转换说明 *
转化说明 *
含义:抑制赋值
示例:“%*d”
scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n
在程序需要读取文件中特定列的内容时,这项跳过功能很有用。
//转化说明 * //含义:抑制赋值 //示例:"%*d" //P96 程序清单 4.17 //跳过输入中的前两个整数 #include <stdio.h> int main() { int n; printf("Please enter three integers:\n"); scanf("%*d %*d %d", &n); //2014 2014 2015 printf("The last integer was %d\n", n); //2015 return 0; } //scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n //在程序需要读取文件中特定列的内容时,这项跳过功能很有用。
(2)转换说明 数字
转换说明 数字
最大字段宽度。输入达到最大字段宽度处,或第 1 次遇到 空白字符 时停止。
通过尝试:这里的 空白字符 不包括 回车,只包括 空格 和 制表符。
示例:“%10s”
//转换说明 数字 //最大字段宽度。输入达到最大字段宽度处,或第 1 次遇到 空白字符 时停止。 //通过尝试:这里的 空白字符 不包括 回车,只包括 空格 和 制表符。 //示例:"%10s" #include <stdio.h> int main() { char input[30] = { 0 }; int ch = 0; //第一次遇到 空白字符 时停止 scanf("%s", input); //11 25 printf("%s\n", input); //11 while ((ch = getchar()) != '\n') //清空缓存区中的,上一次输入多余的东西 { ; } //输入达到最大字段宽度处 scanf("%10s", input); //1234567890987654321 printf("%s\n", input); //1234567890 return 0; }
(3)转换说明 hh
转换说明 hh
把整数作为 signed char 或 unsigned char 类型读取
示例:“%hhd” “%hhu”
//转换说明 hh //把整数作为 signed char 或 unsigned char 类型读取 //示例:"%hhd" "%hhu" #include <stdio.h> int main() { //有符号 char 的取值范围:127~-128 //无符号 char 的取值范围:0~255 signed char signedCharVar; unsigned char unsignedCharVar; scanf("%hhd", &signedCharVar); // 读取一个signed char类型的值 scanf("%hhu", &unsignedCharVar); // 读取一个unsigned char类型的值 //在上述代码中,%hhd 用于读取一个 signed char 类型的值, //而 %hhu 用于读取一个 unsigned char 类型的值。 //这两个转换说明符,确保了即使在较大的环境中,也可以安全地读取一个字节的数据。 printf("%c\n", signedCharVar); printf("%c\n", unsignedCharVar); return 0; }
(4)scanf 中其他的转换说明,不作详细解释,用到的时候再去学习即可
2、从 scanf( ) 角度 看 输入
假设 scanf() 根据一个 %d 转换说明读取一个整数。
scanf() 函数每次读取一个字符,跳过所有的空白字符,直至遇到 第一个非空白字符 才开始读取。
因为要读取整数,所以 scanf() 希望发现 一个数字字符 或者 一个符号(+、-)。
如果找到一个 数字 或 符号,它便保存该字符,并读取下一个字符。
如果下一个字符是数字,它便保存该数字并读取下一个字符。
scanf() 不断地读取和保存字符,直至遇到非数字字符。
如果遇到一个非数字字符,它便认为读到了 整数的末尾。
然后,scanf() 把非数字字符放回输入。
这意味着程序在下一次读取输入时,首先读到的是上一次读取丢弃的非数字字符。 (我的理解就是:输入的数据保存在了 缓冲区 中)
最后,scanf() 计算已读取数字(可能还有符号)相应的数值,并将计算后的值放入指定的变量中。
如果使用字段宽度,scanf() 会在 字段末尾 或者 第一个空白字符处 停止读取(满足两个条件之一便停止)。
如果 第一个非空白字符 是 A 而不是 数字,会发生什么情况呢?
scanf() 将停在那里,并把 A 放回输入中,不会把值赋给变量。
程序在下一次读取输入时,首先读到的字符是 A 。
如果程序只使用 %d 转换说明,scanf() 就一直无法越过 A 读下一个字符。
另外,如果使用带多个转换说明的 scanf() ,C 规定在 第一个出错处停止读取输入。
用其他数值匹配的转换说明读取输入和用 %d 的情况相同。
区别在于 scanf() 会把更多字符识别成数字的一部分。
例如:%X 转换说明要求 scanf() 识别十六进制数 a~f 和 A~F.
浮点转换说明要求scanf() 识别小数点、e 计数法(指数计数法)和新增的 p 计数法(十六进制指数计数法)。
如果使用 %s 转换说明,scanf() 会读取 除空白以外的所有字符。
scanf() 跳过空白开始读取第一个非空白字符,并保存非空白字符直到再次遇到空白。
这意味着 scanf() 根据 %s 转换说明读取下一个单词,即不包含空白字符的字符串。
如果使用字段宽度,scanf()在字段末尾 或者 第一个空白字符 处停止读取。
无法利用字段宽度让只有一个 %s 的scanf() 读取多个单词。
最后要注意一点:
当 scanf() 把字符串放进指定数组中时间,它会在字符序列的末尾加上 ‘\0’ ,让数组中的内容成为一个 C 字符串。
3、格式字符串中的普通字符
#include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); printf("%d %d\n", a, b); scanf("%d%d", &a, &b); printf("%d %d\n", a, b); return 0; }
4、scanf()的返回值
六、printf( ) 和 scanf( ) 的 * 修饰符
printf ( ) 和 scanf( ) 都可以使用 * 修饰符 来修改转换说明 的含义。
但是,他们的用法不太一样。
1、printf( ) 中 * 的用法
如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用 * 修饰符 代替 字段宽度。
但还是要用一个参数告诉函数,字段宽度应该是多少。
也就是说,如果转换说明是 %d ,那么参数列表中应包含 * 和 d 对应的值。
这个技巧也可以用于浮点值指定精度和字段宽度。
//P94 程序清单 4.16 //如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用 * 修饰符 代替 字段宽度。 //但还是要用一个参数告诉函数,字段宽度应该是多少。 //也就是说,如果转换说明是 %d ,那么参数列表中应包含 * 和 d 对应的值。 //这个技巧也可以用于浮点值指定精度和字段宽度。 #include <stdio.h> int main() { unsigned width, precision; int number = 256; double weight = 242.5; printf("Enter a field width:\n"); scanf("%d", &width); //6 printf("The number is:##%*d##:\n", width, number); //:## 256##: printf("Now enter a width and a precision:\n"); //8 3 scanf("%d %d", &width, &precision); printf("Weight = ##%*.*f##\n", width, precision, weight); //## 242.500## printf("Done!\n"); return 0; } //变量 width 提供字段宽度,number 是待打印的数字。 //因为转换说明中 * 在 d 的前面,所以在 printf( ) 的参数列表中,width 在 number 的前面。
变量 width 提供字段宽度,number 是待打印的数字。
因为转换说明中 * 在 d 的前面,所以在 printf( ) 的参数列表中,width 在 number 的前面。
2、scanf( ) 中 * 的用法
scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n
在程序需要读取文件中特定列的内容时,这项跳过功能很有用。
//P96 程序清单 4.17 //跳过输入中的前两个整数 #include <stdio.h> int main() { int n; printf("Please enter three integers:\n"); scanf("%*d %*d %d", &n); //2014 2014 2015 printf("The last integer was %d\n", n); //2015 return 0; } //scanf( ) 指示:跳过两个整数,把第三个整数拷贝给 n //在程序需要读取文件中特定列的内容时,这项跳过功能很有用。
七、本地化设置
八、第四章的 关键概念
九、本章小结
微软雅黑字体
黑体
3号字
4号字
红色
绿色
蓝色