C Primer Plus 第4章——第二篇

avatar
作者
猴君
阅读量:0

你该逆袭了

第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号字
红色
绿色
蓝色

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!