首页 新闻 会员 周边

C语言在VS2019中输入和输出字符串遇到错误

0
悬赏园豆:200 [待解决问题]

源代码

include <stdio.h>

include <string.h> //提供strlen()的函数原型

int main(void)
{
char name[40];

printf("What's your name?");
scanf("%s", name);//错误
printf("Hello, %s\n", name);
printf("Your name of %zd letters occupies %zd memory cells.\n", strlen(name), sizeof(name));//错误

return 0;

}

问题补充:

希望讲清楚错误出现的原因,谢谢

心有明珠,山河明媚的主页 心有明珠,山河明媚 | 初学一级 | 园豆:2
提问于:2019-08-01 16:38
< >
分享
所有回答(3)
0

网上可以查到原因,讲解的很详细,最好养成自己查资料的好习惯,遇到问题先百度一下在网上找原因:
https://blog.csdn.net/dan15188387481/article/details/49622783/
另外英文不好可以把报错翻译一下也能很快找到原因

小光 | 园豆:1766 (小虾三级) | 2019-08-01 16:56

你还是没有回答正确的应该是什么样,那篇文章是VS2013,我这是VS2019界面已经完全不一样了。

@心有明珠,山河明媚: 改变函数不行么,用scanf_s代替scanf不行么

区别在于 用char*类型,比如%c %s格式时,后面要加一个最大程度
比如
scanf_s("%c%s", &a, 1, s, 20);
支持(0) 反对(0) 小光 | 园豆:1766 (小虾三级) | 2019-08-02 09:05

@心有明珠,山河明媚: 我用的2015,你看看网上vs2019的解决方案试试吧
https://blog.csdn.net/S1259364843/article/details/89225209

支持(0) 反对(0) 小光 | 园豆:1766 (小虾三级) | 2019-08-02 09:12

@小光: 那输入解决了,输出呢,为什么错误?

@心有明珠,山河明媚: 一样的,在函数后加上_s就行了,原因是:

scanf等类似的函数已经不太安全,要想保证程序的安全性,建议以后采用_s结尾的安全版本

其他解决方法:
1:右键项目,选择属性,把sdl检查去掉:

2:include的前面加上:#define _CRT_SECURE_NO_WARNINGS

3:include的前面加上:#pragma warning( disable : 4996)

支持(0) 反对(0) 小光 | 园豆:1766 (小虾三级) | 2019-08-02 14:15

@小光: 运行是可以运行,但还是警告,不想要那个波浪线出现

@心有明珠,山河明媚: 那个绿色波浪线是警告,你试试关闭警告:

支持(0) 反对(0) 小光 | 园豆:1766 (小虾三级) | 2019-08-02 15:06

@心有明珠,山河明媚: 不行你把鼠标移到波浪线上看看提示什么

支持(0) 反对(0) 小光 | 园豆:1766 (小虾三级) | 2019-08-02 15:07
0

这个是vs的问题
这个函数本身是没有问题的,但是开发vs的那帮人觉得这个函数容易出现溢出,所以就给vs添加上检查,禁止开发者使用scanf, 又写了个scanf_s函数来给开发者用。
也就是说scanf_s是vs特有的,你如果改用其他IDE是没有这个函数的,所以要兼容其他IDE最好还是使用scanf,所以你要把vs的“安全开发生命周期(SDL)检查“去掉,
2019版我没用过,你可以自己查一下怎么去除。

海之殇 | 园豆:500 (菜鸟二级) | 2019-08-02 11:38

查不到呀,怎么也查不到

@心有明珠,山河明媚:

1楼不是有链接吗,
项目->[项目名称] 属性->c++->预编译->取消预处理器定义->编辑
添加

_CRT_SECURE_NO_WARNINGS

还有一种方法就是在文件开头添加

#define _CRT_SECURE_NO_WARNINGS

这样的话需要每个cpp文件都要添加,有点麻烦

支持(0) 反对(0) 海之殇 | 园豆:500 (菜鸟二级) | 2019-08-02 12:41

@海之殇: 运行是可以运行,但还是警告,不想要那个波浪线出现

0

两个函数先加上_s变成
scanf_s()
printf_s()
很多带"_s"后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元素,有时黑客可以利用原版的不安全性黑掉系统。比如:char d[20];写成scanf_s("%s",d,20);才是正确的,有这个参数20使准确性提高。
然后第一个警告是因为:
scanf函数有返回值
scanf函数的返回值主要是用来判断输入数值的正确性的。正确的一个输入返回1,系统的提醒主要是为了加强对编程安全的理解。网上的资料:
1.scanf()函数有返回值且为int型。
2.scanf()函数返回的值为:正确按指定格式输入变量的个数;也即能正确接收到值的变量个数。

scanf("%d%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
ANSI C中没有scanf_s(),只有scanf(),scanf()在读取时不检查边界,所以可能会造成内存访问越界,例如分配了5字节的空间但是读入了10字节

char buf[5]={'\0'};
scanf("%s", buf);如果输入1234567890,后面的部分会被写到别的空间上去。以上代码如果用scanf_s,第二行应改为scanf_s("%s",buf,5),表示最多读取4个字符,因为buf[4]要放'\0'
scanf_s最后一个参数是缓冲区的大小,表示最多读取n-1个字符.

vc++2005/2008中提供了scanf_s(),在最新的VS2015中也提供了scanf_s()。在调用时,必须提供一个数字以表明最多读取多少位字符。

3.读取单个字符也需要限定长度:scanf_s("%c,%c",&c1,1,&c2,1);而不能写成scanf_s("%c,%c",&c1, &c2,1, 1);否则编译器会报错
你的libc的作者的决定scanf的返回值在大多数情况下不应该被忽略,所以他们给了一个属性告诉编译器给你一个警告。
如果返回值真的不需要,也行。但是,通常最好检查它,以确保你实际上成功地阅读你认为你做了。
在你的情况下,代码可以这样写,以避免警告:
(void)scanf_s("%s", name,40);
这样就不会有返回值
或者可以写t=scanf_s("%s", name,40);
if(scanf_s("%s", name,40)!=0);
表明你用到了他的返回值
第二个警告是因为:
你的strlen()函数认为你的name数组没有'\0'结束符(其实在执行scanf()函数之后会自动在后面添上'\0')
你可以在最开始的时候把char name[40]改为char name[40]="\0"先给name数组赋一个'\0'初值即可解决

然后我觉得你可以把%zd改成%d
%zd是格式符z和整数转换说明符一起使用,表示对应数字是一个size_t值。属于C99。一般很少使用,个人觉得意义不大。%d就行

因为用的不是VS2019,所以不敢肯定能解决,但理论上应该没有问题,希望能帮助到你

萌新弟弟就是我 | 园豆:202 (菜鸟二级) | 2019-08-09 12:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册