C语言—scanf_s()

作者:追风剑情 发布于:2019-7-20 21:36 分类:C

示例

  1. //Visual Studio中加上这句才可以使用scanf()
  2. //否则只能使用scanf_s()
  3. #define _CRT_SECURE_NO_WARNINGS
  4.  
  5. //引入printf()、scanf_s()
  6. #include <stdio.h>
  7. #include <stdint.h>
  8. //引入bool类型,C99标准新增
  9. #include <stdbool.h>
  10. //引入Sleep()
  11. #include <windows.h>
  12. //ANSI C之前的编译器不支持string.h
  13. //一些ANSI之前的UNIX系统用strings.h代替string.h
  14. //引入strlen()
  15. #include <string.h>
  16.  
  17. int main(void)
  18. {
  19. char name[40];
  20. printf("please enter name:\n");
  21. //第三个参数代表最多读取多少个字符到name中
  22. //scanf_s是微软提供的,比scanf更安全
  23. //当读到第一个空格时即结束
  24. scanf_s("%s", name, 40);
  25. //sizeof()返回数组长度
  26. //strlen()返回数组中有效字符数
  27. printf("sizeof=%d, len=%d \n", sizeof(name), strlen(name));
  28. fflush(stdin);//刷新输入缓冲区
  29. fflush(stdout);//刷新输出缓冲区
  30.  
  31. int age=0;
  32. printf("please enter age:\n");
  33. scanf_s("%d", &age);
  34. printf("name=%s, age=%d\n", name, age);
  35.  
  36. int num1, num2, num3;
  37. scanf_s("%d %d %d", &num1, &num2, &num3);
  38. printf("num1=%d, num2=%d, num3=%d \n", num1, num2, num3);
  39.  
  40. char str1[40];
  41. char str2[40];
  42. //连续读取字符串,字符数组后面必须指明要读取的个数
  43. //输入多个字符串时用空格隔开.例如 abc def
  44. //多个%s可以连续写,也可以用空格隔开
  45. scanf_s("%s %s", str1, 40, str2, 40);
  46. printf("str1=%s, str2=%s\n", str1, str2);
  47.  
  48. int num4;
  49. char str3[40];
  50. scanf_s("%s %d", str3, 40, &num4);
  51. printf("str3=%s, num4=%d\n", str3, num4);
  52.  
  53. system("pause");
  54. return 0;
  55. }


运行测试

1111.png

ANSI C中scanf()的转换说明
scanf()函数所用的转换说明与printf()函数几乎相同。主要的区别是,对于float类型和double类型,printf()都使用%f、%e、%E、%g和%G转换说明。而scanf()只把它们用于float类型,对于double类型时要使用l修饰符。下表列出了C99标准中常用的转换说明。
转换说明 含义
%c 把输入解释成字符
%d 把输入解释成有符号十进制整数
%e、%f、%g、%a 把输入解释成浮点数(C99标准新增了%a)
%E、%F、%G、%A 把输入解释成浮点数(C99标准新增了%A)
%i 把输入解释成有符号十进制整数
%o 把输入解释成有符号八进制整数
%p 把输入解释成指针(地址)
%s 把输入解释成字符串。从第1个非空白字符开始,到下一个空白字符之前的所有字符都是输入
%u 把输入解释成无符号十进制整数
%x、%X 把输入解释成有符号十六进制整数


scanf()转换说明中的修饰符
使用转换说明比较复杂,而且这些表中还省略了一些特性。省略的主要特性是,从高度格式化源中读取选定数据,如穿孔卡或其他数据记录。
转换说明 含义
* 抑制赋值
示例:“%*d”
数字 最大字段宽度。输入达到最大字段宽度处,或第1次遇到空白字符时停止
示例:“%10s”
hh 把整数作为signed char或unsigned char类型读取
示例:“%hhd”、"%hhu"
ll 把整数作为long long或unsigned long long类型读取(C99)
示例:“%lld”、"%llu"
h、l或L “%hd”和"%hi"表明把对应的值储存为short int类型
"%ho"、"%hx"和"%hu"表明把对应的值储存为unsigned short int类型
“%ld”和"%li"表明把对应的值储存为long类型
"%lo"、"%lx"和"%lu"表明把对应的值储存为unsigned long类型
"%le"、"%lf"和"%lg"表明把对应的值储存为double类型
在e、f和g前面使用L而不是l,表明把对应的值被储存为long double类型。如果没有修饰符,d、i、o和x表明对应的值被储存为int类型,f和g表明把对应的值储存为float类型
j 在整型转换说明后面时,表明使用intmax_t或uintmax_t类型(C99)
示例:"%zd"、"%zo"
z 在整型转换说明后面时,表明使用sizeof的返回类型(C99)
t 在整型转换说明后面时,表明使用表示两个指针差值的类型(C99)
示例:“%td”、"%tx"


示例:读取字符串输入

  1. //Visual Studio中加上这句才可以使用scanf()
  2. //否则只能使用scanf_s()
  3. #define _CRT_SECURE_NO_WARNINGS
  4. #include <stdio.h>
  5. //argc: 参数个数 argv[]: 参数数组
  6. int main(int argc, char *argv[])
  7. {
  8. int age;
  9. float assets;
  10. char pet[30];//字符数组,用于储存字符串
  11. pet[2] = '\0';
  12.  
  13. printf("Enter your age, assets, and favorite pet.\n");
  14. //用户可以在一行或多行输入参数
  15. //参数间需要用空白(换行符、制表符和空格)把输入分成多个字段
  16. scanf_s("%d %f", &age, &assets);//这里要使用&
  17. //scanf_s("%s", pet);//会输出乱码
  18. scanf("%s", pet);//字符数组不使用&
  19. printf("%d $%.2f %s\n", age, assets, pet);
  20.  
  21. //唯一例外的是%c转换说明,根据%c,scanf()会读取每个字符,包括空白。
  22.  
  23. system("pause");
  24. return 0;
  25. }
运行测试
111.png


从scanf()角度看输入

      假设scanf()根据一个%d转换说明读取一个整数。scanf()函数每次读取一个字符,路过所有空白字符,直至遇到第1个非空白字符才开始读取。因为要读取整数,所以scanf()希望发现一个数字字符或者一个符号(+或-)。如果找到一个数字或符号,它便保存该字符,并读取下一个字符。如果下一个字符是数字,它便保存该数字并读取下一个字符。scanf()不断地读取和保存字符,直到遇到非数字字符。如果遇到一个非数字字符,它便认为读到了整数的末尾。然后,scanf()把非数字字符放回输入。这意味着程序在下一次读取输入时,首先读到的是上一次读取丢弃的非数字字符。最后,scanf()计算已读取数字(可能还有符号)相应的数值,并将计算后的值放入指定的变量中。

       如果使用字段宽度,scanf()会在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。

       如果第1个非空白字符是A而不是数字,会发生什么情况呢?scanf()将停在那里,并把A放回输入中,不会把值赋给指定变量。程序在下一次读取输入时,首先读到的字符是A。如果程序只使用%d转换说明,scanf()就一直无法越过A读下一个字符。另外,如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。

       用其他数值匹配的转换说明读取输入和用%d的情况相同,区别在于scanf()会把更多字符识别成数字的一部分。例如,%x转换说明要求scanf()识别十六进制数a~f和A~F。浮点转换说明要求scanf()识别小数点、e记数法(指数记数法)和新增的p记数法(十六进制指数记数法)。

       如果使用%s转换说明,scanf()会读取除空白以外的所有字符。scanf()路过空白开始读取第1个非空白字符,并保存非空白字符直到再次遇到空白。这意味着scanf()根据%s转换说明读取一个单词,即不包含空白字符的字符串。如果使用字段宽度,scanf()在字段末尾或第1个空白字符处停止读取。无法利用字段宽度让只有一个%s的scanf()读取多个单词。最后注意一点:当scanf()把字符串放进指定数组中时,它会在字符序列末尾加上'\0',让数组中的内容成为一个C字符串。

       实际上,在C语言中scanf()并不是最常用的输入函数,这里重点介绍它是因为它能读取不同类型的数据。C语言还有其他的输入函数,如getchar()和fgets()。这两个函数更适合处理一些特殊情况,如读取单个字符或包含空格的字符串。无论程序中需要读取整数、小数、字符还是字符串,都可以使用scanf()函数


示例:格式字符串中的普通字符

  1. //Visual Studio中加上这句才可以使用scanf()
  2. //否则只能使用scanf_s()
  3. #define _CRT_SECURE_NO_WARNINGS
  4. #include <stdio.h>
  5. //argc: 参数个数 argv[]: 参数数组
  6. int main(int argc, char *argv[])
  7. {
  8. int n, m;
  9. // 用户必须输入两个整数且用逗号隔开
  10. // scanf()会跳过整数前面的空白
  11. scanf("%d,%d", &n, &m);
  12. printf("Enter: %d, %d\n", n, m);
  13.  
  14. scanf("%d ,%d", &n, &m);
  15. printf("Enter: %d, %d\n", n, m);
  16.  
  17. // 除了%c,其他转换说明都会自动跳过待输入值前面所有的空白。
  18. // scanf("%d%d", &n, &m)
  19. // scanf("%d %d", &n, &m)
  20. // 上面两句行为相同
  21.  
  22. // 对于%c,在格式字符串中添加一个空格字符会有所不同。
  23. // 例如,如果把%c放在格式字符串中的空格前面,scanf()便会跳过空格,
  24. // 从第1个非空白字符开始读取。也就是说,scanf("%c", &ch)从输入中的
  25. // 第1个字符开始读取,而scanf(" %c", &ch)则从第1个非空白字符开始读取。
  26.  
  27. char ch;
  28. // scanf返回成功读取的项数,检测到文件结尾,则返回EOF
  29. // EOF是stdio.h中定义的特殊值,通常用#define指令把EOF定义为-1
  30. // 可利用返回值来检测和处理不匹配的输入
  31. int result = scanf(" %c", &ch);
  32. printf("scanf return: %d\n", result);
  33.  
  34.  
  35. system("pause");
  36. return 0;
  37. }
运行测试
1111.png


示例:printf()和scanf()的*修饰符

  1. //Visual Studio中加上这句才可以使用scanf()
  2. //否则只能使用scanf_s()
  3. #define _CRT_SECURE_NO_WARNINGS
  4. #include <stdio.h>
  5. //argc: 参数个数 argv[]: 参数数组
  6. int main(int argc, char *argv[])
  7. {
  8. /*
  9. printf()和scanf()都可以使用*修饰符来修改转换说明的含义。但是,
  10. 它们的用法不太一样。
  11. 如果你不想预先指定字段宽度,希望通过程序来指定,
  12. 那么可以用*修饰符代替字段宽度。但还是要用一个参数告诉函数,
  13. 字段宽度应该是多少。也就是说,如果转换说明是%*d,那么参数
  14. 列表中应包含*和d对应的值。这个技巧也可用于浮点值指定精度和字段宽度。
  15. */
  16.  
  17. unsigned width, precision;
  18. int number = 256;
  19. double weight = 242.5;
  20.  
  21. /** 在printf()中使用* **/
  22. printf("Enter a field width: \n");
  23. scanf("%d", &width);
  24. printf("The number is :%*d:\n", width, number);
  25. printf("Now enter a width and a precision: \n");
  26. scanf("%d %d", &width, &precision);
  27. printf("Weight = %*.*f\n", width, precision, weight);
  28. printf("Done!\n");
  29.  
  30. /** 在scanf()中使用* **/
  31. /*
  32. scanf()中把*放在%和转换字符之间时,会使得scanf()跳过相应的输入项。
  33. 在程序需要读取文件中特定列的内容时,这项跳过功能很有用。
  34. */
  35. int n;
  36. printf("Please enter three integers:\n");
  37. scanf("%*d %*d %d", &n);
  38. printf("The last integer was %d\n", n);
  39.  
  40. system("pause");
  41. return 0;
  42. }
运行测试
1111.png


标签: C语言

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号