-
2021-05-21 06:25:02
scanf_s()或scanf()函数从标准输入读取数据,并根据格式控制字符串中的格式说明符将它们转换为一个或多个值。
scanf_s()函数的原型如下:
int scanf_s(const char * restrict format, . . . );
scanf()函数也有一个类似的原型。
scanf()和scanf_s()之间的区别是:
后者需要两个参数,每个输入数据由c,s和[说明符,
前者只需要一个参数。
格式控制字符串基本上是scanf_s()应如何将传入字符流转换为所需值的描述。
在格式控制字符串之后,可以拥有一个或多个可选参数。
对于使用规范c,s或[说明符]读取的每个输入,第一个对应的参数是指向要存储输入的内存的指针,第二个参数对应于前一个参数指向的字节数。
scanf_s()从stdin读取,直到它到达格式控制字符串的末尾或者直到出现错误情况。
在控制台程序中需要输入时,将使用此函数。 这将接收行上的所有输入,直到按下回车键。 然后它会将值放入声明的变量中。它与scanf()函数相同,但它是安全的。 下面是一个例子:
#include
int main()
{
char c;
printf("Enter a letter");
scanf_s("%c", &c, 1);
printf("%s",&c);
return 0;
}
scanf()在vs2013里报错,编译器提示要用scanf_s代替;
scanf_s()参数与scanf()不同;例如scanf("%s",&name,n),整型n为name类型的大小,如果name是数组,那么n就是该数组的大小。
#include
#include
struct Student
{
char name[10];
char sex[10];
int age;
char city[10];
char grade[10];
};
int main()
{
struct Student stu1;
printf("请输入姓名:");
scanf_s("%s", &stu1.name,10);
printf("请输入性别:");
scanf_s("%s", &stu1.sex,10);
printf("请输入年龄:");
scanf_s("%d", &stu1.age,4);
printf("请输入城市:");
scanf_s("%s", &stu1.city,10);
printf("请输入年级:");
scanf_s("%s", &stu1.grade,10);
printf("姓名:%s\n", stu1.name);
printf("性别:%s\n", stu1.sex);
printf("年龄:%d\n", stu1.age);
printf("城市:%s\n", stu1.city);
printf("年级:%s\n", stu1.grade);
return 0;
}
更多相关内容 -
scanf与scanf_s函数的使用 详解
2021-10-17 15:31:041.scanf_s(是vs提供的函数) a.代码1 int main() { char a = 0; //scanf_s("%c", &a, 1); scanf_s("%c", &a, sizeof(a)); return 0; } scanf_s有三个参数,最后一个是变量a所占据空间的大小(单位...1.scanf_s(是vs提供的函数)
a.代码1
int main() { char a = 0; //scanf_s("%c", &a, 1); scanf_s("%c", &a, sizeof(a)); return 0; }
scanf_s有三个参数,最后一个是变量a所占据空间的大小(单位为字节),这里可以写1,也可以写sizeof(a)。如果a为整型的话,第三个参数就为4,或者sizeof(a)。
b.代码2
int main() { char a = 0, b = 0; scanf_s("%c %c", &a, sizeof(a), &b, sizeof(b)); printf("%c %c", a, b); return 0; }
可不要写成 scanf_s("%c%c",&a,&b,1,1); 这样会出错的
c.代码3
int main() { int a = 0; int b = 0; scanf_s("%d %d", &a, &b, sizeof(a),sizeof(b)); printf("%d %d", a, b); return 0; }
注意:如果输入整型数据,scanf函数的里面的sizeof()是在所有取地址的后面,而输入字符,每个取地址后面需要有一个sizeof()
d.代码3
int main() { char arr1[5] = { 0 }; scanf_s("%s", arr1, sizeof(arr1)); printf("%s", arr1); return 0; }
注意:输入字符的个数时,一定是比数组的空间个数小的,比如像上面的代码只能输入1-4个字符,而不是5个,不然会出错的。(arr[4]装的是一个'\0',字符串结束标志)
e.代码4
int main() { int a[5] = { 0 }; for (int i = 0; i < 5; i++) { scanf_s("%d", &a[i], sizeof(a[i])); } for (int i = 0; i < 5; i++) { printf(" %d", a[i]); } return 0; }
注意一点的是 那个取地址符(&)不要忘写了。
f.安全性检测
int main() { char arr1[5] = { 0 }; int c=scanf_s("%s", arr1, sizeof(arr1)); printf("%d\n", c); printf("%s", arr1); return 0; }
如果输入的字符个数>=数组空间 个数,scanf_s的返回值就为0,反之则为1。
int main() { char arr1[5] = { 0 }; scanf_s("%s", arr1, sizeof(arr1)); printf("%s", arr1); return 0; }
如果输入的字符个数>=数组空间 个数,是不会打印数组中的元素的。(而scanf函数就会打印出)
2.scanf(标准的库函数)
a.代码1
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { int a = 0; scanf("%d", &a); printf("%d", a); return 0; }
在VS13 17 19的版本下使用scanf函数一定在最开始(#define _CRT_SECURE_NO_WARNINGS
),不然会报错的。
b.返回值测试
代码1:
int main() { int a = 0; int ret=scanf("%d", &a); printf("%d\n", ret); return 0; }
代码2:
int main() { int a = 0; int b = 0; int ret = scanf("%d %d", &a,&b); printf("%d\n", ret); return 0; }
代码3:
int main() { char a = 0; int ret=scanf("%c", &a); printf("%d", ret); return 0; }
代码4:
int main() { char a = 0; char b = 0; int ret = scanf("%c%c", &a,&b); printf("%d", ret); return 0; } //int main()
代码5:
int main() { char str[5] = { 0 }; int ret=scanf("%s", str); printf("%s\n", str); printf("%d\n", ret); return 0; }
总结:scanf函数的返回值与函数里面格式符的个数有关 ,返回值即格式符的个数。
c.安全性测试
int main() { char arr1[5] = { 0 }; int c=scanf("%s", arr1); printf("%d\n", c); printf("%s", arr1); return 0; }
当我们输入abcdefg 7个字符时(已经超出了数组的空间个数了),虽然可以打印出来,但是arr1附近的栈空间已被破坏了,出现越界的情况了。scanf_s不会打印出来,也就不存在越界的行为了。
d.当在scanf函数里面输入格式符
如%d %d(%d%d之间有空格),那么通过标准输入设备(键盘)输入时两个整型之间也加一个空格。
如%d,%d(%d%d之间逗号),那么通过标准输入设备(键盘)输入时两个整型之间也加一个逗号。
3.总结
a.使用scanf_s函数虽然安全性比较高,但是可移植性差。比如含有scanf_s函数的代码不一定在其它的编译器上能够跑过。
b.scanf函数虽然没有scanf_s函数那么安全,但可移植性是比scanf_s强。
scanf_s函数与scanf函数的使用与比较今天就分享到这里了,如果对你有帮助的话吗,可以给个关注,顺便给个赞。
-
scanf与scanf_s区别
2021-12-11 14:52:42最近有这么一篇作业,输入十个等长字符串并为其排序,本来...但scanf_s则避免了这个问题。举个例子。 #define _CRT_SECURE_NO_WARNINGS 1; #include<stdio.h> int main() { char k[5][4] = { 0 }; printf(...最近有这么一篇作业,输入十个等长字符串并为其排序,本来是很简单的一道题,结果运行时却疯狂越界,百度了之后才知道是scanf的锅,于是决定查查其区别。
最大区别为scanf()在读取数据时不检查边界,所以可能会造成内存访问越界;但scanf_s则避免了这个问题。举个例子。
#define _CRT_SECURE_NO_WARNINGS 1; #include<stdio.h> int main() { char k[5][4] = { 0 }; printf("请输入5个字符串。\n"); for (int i = 0; i < 5; i++) scanf("%s", k[i]); printf("打印。\n"); for (int i = 0; i < 5; i++) printf("%s\n", k[i]); return 0; }
使用scanf函数当我输入字符串长度均小于4时运行正常,当我长度一旦到达4个,也就是没有给数组留下\0的位置就出问题了。
同样的,当输入字符串长度大于4时scanf函数仍然接收,无论字符串有多长,数组空间有多大,scanf函数都会接收并在最后置入\0表示字符串结束。当我最后输入sfervb时效果如下。
显而易见,这种情况让我们使用字符串时十分危险,一旦输入错误,就会使得后面数组使用时随时有越界的风险。如果换成scanf_s则需要换成scanf_s("%s",k,n)的格式,k为数组,n则为输入的最大长度,注意,这里的长度是计算上了\0的,即当n为4时,输入的字符串长度最大为3。
把scanf换成scnaf_s后
#define _CRT_SECURE_NO_WARNINGS 1; #include<stdio.h> int main() { char k[5][4] = { 0 }; printf("请输入5个等长字符串。\n"); for (int i = 0; i < 5; i++) scanf_s("%s", k[i],4); printf("打印。\n"); for (int i = 0; i < 5; i++) printf("%s\n", k[i]); return 0; }
当输入字符达到4个scanf_s就会将该数组置为空,效果如下图:
如果输入超过4个,scanf会视4个字符为一个字符串并将之置为空,余下的放入下一个数组视为新的字符串,不会像scanf那样一定要输入5次。效果如下:
综上,scanf_s在安全方面确实胜过scanf,可以有效避免字符串越界问题,但是scanf是C语言标准规定的函数,而scanf_s则是VS编译器替换的函数,所以在适用性方面,scanf_s就不能和scanf比了。
-
关于scanf与scanf_s
2021-10-21 23:40:42明明已创造了可放入char元素的数组,但是在如图所示的scanf_s一行中,使用%s却无法使程序跑动起来,达不到想要的预期效果。 但是最让人疑惑的是明明该放入%c或者是%s,在放入%d后,程序居然运转了....它居然运转...今日在输入一个程序时一直改不过来,发现有错误,就是现在下图的情况:
明明已创造了可放入char元素的数组,但是在如图所示的scanf_s一行中,使用%s却无法使程序跑动起来,达不到想要的预期效果。
但是最让人疑惑的是明明该放入%c或者是%s,在放入%d后,程序居然运转了....它居然运转起来了...然后放入%c也可以,为何%s就不可以呢?(学c,从入门到入土)
最后在和别人的讨论(主要是别人教我)后,从历史开始讲起...
scanf是在scanf_s之前出现的,从前用scanf输入函数,现在是用scanf_s来输入函数,以此来避免不检查边界从而导致内存泄露然后程序崩掉。而在scanf_s中,平时输入%d %f %lf都没有问题,但在用%s和%c输入字符串或者字符时会进入缓冲区一个一个读取,这时候在scanf_s中就要定义一个缓冲区的边界值,用来防止内存泄露,这个时候有scanf_s的程序才会运行,所以在scanf_s那一行里要用scanf_s("%20s",password,sizeof(password));来做到定义边界值,从而使得有scanf_s的程序运行起来。
"20s"——定义输入20个字符
sizeof(password)——定义一个缓冲边界值,防止内存泄露。
总结来说,要解决上面的问题,有以下两种方法:
一、将scanf_s改为scanf。
二、将scanf_s一行改为输入scanf_s("%20s",password,sizeof(password));
但仍存在两点疑惑未解决:
一、为何在使用%c时不需要定义边界值?
二、为何在scanf_s一行里使用%d时程序可正常运行?
在以后可以尝试用指针方法来求解,路漫漫~~
上文里还有很多不准确的地方,如果有什么错误或者有大佬能够解答我的疑惑,欢迎大家来讨论。
-
scanf_s与scanf
2022-04-05 17:13:48在VS中写c++不能直接使用scanf否则会出现 这种提示,所以按照提示将原本的 scanf("%d",&a); 改成 scanf_s("%d",&a);...scanf_s只能用于VS中,在其他编译器中会出现错误。 ... -
C语言scanf与scanf_s
2021-05-21 12:59:01C语言scanf与scanf_s0我打编译器是microsoft visual studio 2005,我的源程序如下,注意注释的地方,就是scan函数中的scanf_s函数,程序运行正常,但是当输入字符串大于或等于8个字符时,链表的输出就不正常了,7个... -
VS中的scanf和scanf_s
2022-04-02 21:02:14一:scanf() 和scanf_s()的区别 -
C语言中的scanf与scanf_s 以及循环使用scanf_s进行输入时的问题解决
2019-10-03 15:44:26Scanf 在标准C中,scanf提供了键盘输入功能。 scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。scanf函数的一般形式为: ... -
C语言中的scanf与scanf_s 以及循环输入的问题解决
2021-05-19 01:39:38Scanf在标准C中,scanf提供了键盘输入功能。scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。scanf函数的一般形式为:scanf... -
scanf与scanf_s的区别举例
2021-12-11 19:58:44不想用scanf_s硬用scanf -
C语言scanf_s错误
2022-02-19 18:11:54使用VS2019scanf_s输入字符串时,发生如下错误。是因为scanf_s在读取字符串时,需要提供一个参数表面读取多少个字符,防止溢出。修改如下: int main() { char arr[10]; scanf_s("%s", arr,5); printf("%s", ... -
scanf 和 scanf_s 函数在VS中的用法解释
2021-03-17 19:00:33由于微软工作人员从函数安全性的考虑,在VS中弃用了scanf函数,之后创建了scanf_s函数来代替使用,所以在VS中,大多数时候我们还是使用scanf_s函数 其实不是说不可以使用scanf函数,只不过是预处理器会发出错误警告... -
visual studio中scanf_s问题
2022-04-28 09:11:02这个scanf_s 是VS自己提供的函数,不是标准C提供的函数,也就说当你跨平台提交代码时,scanf_s可能会无法识别。那么这个问题怎么解决呢? 解决办法: 在源文件第一行加上 #define _CRT_SECURE_NO_WARNINGS ... -
用scanf_s输入字符串
2022-02-25 12:41:03vs2019。 为了安全,scanf_s输入字符串时需要加一个数字来限制最多读取的字符数。 -
【C语言:精准打击】scanf_s()函数与scanf()函数的相关解决方案
2022-03-19 10:03:42scanf_s()函数与scanf()函数的使用方法及两种函数出bug时相关解决方案 -
C语言scanf_s()函数的用法
2019-07-10 22:01:12C语言scanf_s()函数的用法 前言 今天开始学习C语言,看书学的挺快的,感觉也不能,就想着敲下代码,结果错误百出,差点不想学了,果然编程是敲会的。下面说说第一个程序遇到的问题与心得 scanf_s()前身——scanf() ... -
关于scanf_s老是报错的问题
2021-11-04 19:18:15scanf_s,你真是浪费了我好多时间 一开始我打算用scanf_s输入浮点型数据和字符型数据时,系统总是报错,就是那种生成解决方案没有错误,但是调试就是不行,诶它就是不行。 就是这种,一开始我不知道,还以为是... -
C语言学习>scanf和scanf_s的区别
2021-03-06 22:07:41scanf_s()更安全,其会检查输入的边界 如: char ch[6]; scanf("%s",ch); 若此时输入数据为abcdefghijk,则f以后的内容将溢出到别的空间,可能会导致程序运行错误 若使用 scanf_s("%s",ch); 则输入数据abcdefghijk... -
缺少scanf_s 的整型参数
2021-11-15 21:59:59int date1;... scanf_s("%d%c%d", &date1, &c, &date2); int date1; int date2; char c; scanf_s("%d%c%d", &date1, &c, 1,&date2); 这两串代码的区别 &c,1 &c -
scanf和scanf_s的区别
2020-03-29 08:33:18再写程序的时候一般都是用vs,调试的时候用dev-c++(写程序的时候用vs真的可以少打好多字),但是发现dev-C++中对scanf和scanf_s都可以进行编译,但是vs只能编译scanf_s,但是编译scanf的时候一直报错,那么scanf和... -
VS2019解决scanf_s等问题
2021-12-10 20:17:05vs2019解决scanf_s等问题 -
关于c语言的scanf\n的问题(scanf_s)
2021-05-21 05:30:36今天遇到一道题要求输入scanf("%c %c %c\n",&a,&b,&c),结果不停地出现问题,经过许久尝试,终于发现是\n出现了问题,scanf遇到\n看到另有玄机。这种情况下会要去多输入一行,才有用,但是实际读入的却... -
C6064:缺少“scanf_s”的整型参数(对应于转换说明符“2”
2022-04-05 10:38:58学习过程遇见的问题,出现两个警告,一个是关于C6054:可能没有为字符串“name”添加字符串零终警告,另一个是关于C6064:缺少“scanf_s”的整型参数(对应于转换说明符“2”,因为篇幅太长,本片只介绍C6064:缺少... -
C++——scanf_s与printf_s
2020-01-12 22:05:111.scanf是C语言的输入变量的方法,C++有类似的方法进行输入,采用sacnf_s的方法。 下面是一个输入样式: (代码中的%X表示格式化的类型,将在下文中讲到) int a, b; scanf_s("%d%d", &a, &b); 其实scanf_s... -
scanf_s输入字符/字符串vs抛异常
2021-11-28 18:52:59写C语言作业的时候,我使用visual studio2022的环境,在读取输入字符时总是抛出异常。... scanf_s("%d/%d%c%d/%d", &num1[0], &num1[1], &opt, &num2[0], &num2[1]); printf("%c", opt -
c语言scanf_s输入字符串报错
2021-09-16 21:08:42在visual studio上使用scanf_s输入字符串报错,如 scanf_s("%s", name); 这是因为scanf_s在读取字符串时,需要提供一个数字以表明读取多少个字符,以防止溢出。 scanf_s("%s", name, 20); -
C语言VS环境scanf()和scanf_s()函数
2019-09-28 14:04:28c语言,VS2013环境,scanf()安全性问题,_CRT_SECURE_NO_WARNINGS,scanf_s()函数, error C4996:‘scanf’:This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, ... -
C语言:VS中利用scanf_s函数输入字符串时出错
2022-01-18 19:21:11在vs中scanf函数中下图的代码正确,但是因为vs中scanf函数被认为不安全,现基本改用了scanf_s函数。 #include<stdio.h> int main() { char a[20]; printf("输入一个字符串="); scanf_s("%s",a); } ... -
scanf_s输入多个变量后,变量值发生变化
2020-02-06 14:59:17scanf_s("%d,%d,%d", &a, &b, & c); printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); } ``` ``` 1,2,3 1 -858993460 -858993460 C:\Users\jyz_1\source\repos\Project2\Debug\... -
C++之scanf_s
2019-12-07 17:58:10//而scanf_s对字符串的输入,需要边界参数,会检查有没有存储边界,则需要一般格式("%s",&numb,numb内存长度);非字符串输入不需要边界参数因此一般用scanf_s("%d",地址)就行了。 //scanf_s是有返回值的,返回...