| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4777 人关注过本帖
标题:字符串结束符的疑惑???
只看楼主 加入收藏
lklqlk1991
Rank: 2
等 级:论坛游民
帖 子:32
专家分:16
注 册:2009-10-15
结帖率:75%
收藏
已结贴  问题点数:20 回复次数:8 
字符串结束符的疑惑???
请问一下如果我输入5个字符,那岂不是没地方存结束符了,如果硬要存下数组是不是己经溢出??如果小于5是不是自动加'\0'???
// Note:Your choice is C++ IDE
#include <iostream>
using namespace std;
int main()
{
char a[5];
cout<<"请输入一组字符串.小于5"<<endl;
cin>>a;
while(strlen(a)>5)
{
cout<<"error"<<endl;
cin>>a;
}
cout<<a<<endl;
char *b=a;
while(*b!='\0')
{
cout<<*b<<endl;
b++;
system("pause");
}
    return 0;
}
还问一下strlen是在输入给数组后判断的吧,输入时按下回车键的那一刻,数据己经存入数组,如果输多了,数组己经溢出,会不会带来错误??那strlen在后来判断还有什么用啊????!!!
最好给小弟详解下,谢谢!
搜索更多相关主题的帖子: 结束 字符 
2009-12-19 10:14
debroa723
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:23
帖 子:862
专家分:1954
注 册:2008-10-12
收藏
得分:10 
"请问一下如果我输入5个字符,那岂不是没地方存结束符了,如果硬要存下数组是不是己经溢出??如果小于5是不是自动加'\0'???"
cin并不知道你提供的数组大小,所以,不管输入多少,它都注入到这个内存起的一段内存里,并在结束的地方加结束符。所以超过数组下标的,肯定是溢出了。

“还问一下strlen是在输入给数组后判断的吧,输入时按下回车键的那一刻,数据己经存入数组,如果输多了,数组己经溢出,会不会带来错误??那strlen在后来判断还有什么用啊????!!!”
strlen返回的是到第一个结束符的地方的长度,的确,数组已经溢出,但会不会造成错误,这就很难说。
例一:Debug下,内存中的两个变量之间会加一点长度,如本题中,变量a的数组理论长度为5,实际占内存长度为8,这一点是为了补满四字节(注:这是在XP操作系统上,编译器为VS2008的情况下描述,具体情况有各异,不过原则是一样的)。
每两个变量之间还会再补四个字节,这样算下来,变量a的容量在12,也就是说,输入字符在12以内是安全的。
例二:如果输入字符超过安全容量,会怎么样,这要看跟在变量a前面的是什么了(代码中,声明在a前面的变量,在内存上看,存在于a 的后面),那么a的溢出就会修改到这些东西,如果是基础类型的变量,还好,只是会造成计算上的错误,如果是指针,函数入口什么的,就等着准备哭吧.
2009-12-19 14:24
lklqlk1991
Rank: 2
等 级:论坛游民
帖 子:32
专家分:16
注 册:2009-10-15
收藏
得分:0 
多谢楼上的大哥.哪位进来的大侠再帮下忙,多多交流,给小弟仔细讲讲.先谢过!请问下有没有一种安全的机制,在strlen检查之前可以让数组不溢出??

[ 本帖最后由 lklqlk1991 于 2009-12-19 20:28 编辑 ]
2009-12-19 18:50
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:0 
在 C++ 里可以用 string 类,它可以动态分配内存。理论上,C++鼓励用 string 代替 C 风格的字符串。
在 C 里编程,就必须自己小心的使用内存。比如用传统的 scanf 函数族,可以用域宽限定读入字符的个数,然后自己检查是不是读全了。
内存管理方面,C 语言的确相对弱一些。要自己努力~
2009-12-20 09:35
ruinw
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2009-12-20
收藏
得分:0 
溢出自然就报错了。不会在第5个上加结束符的...

strlen 不是用来判断是不是溢出的  是返回长度的 呵呵~~~
2009-12-20 11:12
lklqlk1991
Rank: 2
等 级:论坛游民
帖 子:32
专家分:16
注 册:2009-10-15
收藏
得分:0 
c++很好很强大啊,学习也并非一朝一夕,只有一点又一点的努力......
多多交流,共同进步
2009-12-20 15:08
debroa723
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:23
帖 子:862
专家分:1954
注 册:2008-10-12
收藏
得分:5 
五楼的兄弟应该调试一下再说,当然可能其它编译器会是你说的那样报错,但至于在VS2008上是没有在输入时报错,只到程序结束时报错,因为它破坏了堆。这个原因就是因为cin的>>重载函数并不知道数组的长度,它只管在给定的内存地址上注入输入的字符。
使用scanf准确的说也不安全,应该使用scanf_s,关于这里的问题,有兴趣的话可搜索“CRT安全函数”的相关,会发现许多已经禁止使用或是准备抛弃使用的C函数,依然地在被各大教程使用。
学C不是在学历史。
cin是C++的,它的用法可以是这样
char str[20];
cout<<"Input :";
cin.getline(str,20);//这样就安全保证不会溢出了。当然,多输入的字符就不会存在于str 中。
cout<<str<<endl;
cin其实是一个模板类,它有许多方法,有兴趣的话可以打开它的声明的地方看一看,会学到一些东西。


[ 本帖最后由 debroa723 于 2009-12-20 23:45 编辑 ]
2009-12-20 23:20
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:5 
网上查了 CRT 的函数是微软特有的。
而且所谓的安全,其实就是用 %s 之类的东西时,要强制多传一个参数指定缓冲区长度。
当然这种东西用在工程里能避免错误也可以鼓励使用,就像鼓励使用 fgets 而不是 gets 一样,不过其实都是避免因程序员编程错误而引发的 bug。
不过我感觉也不是很方便,如果将来出于优化或之类什么的原因,把缓冲区扩大了,还要想着把所有用 %s 的地方,之后追加的参数改过来。也许可以考虑用宏,但也不一定很方便。我觉得既然 scanf 有域宽的限制,那么可以用 %5s 之类的方法避免溢出。如果觉得这些传统的 C 语言函数有缺陷,其实就用 C++ 中的 cin 配合 string类 来代替就好了。
C 语言 一切相信程序员 也可以作为它的精神之一,用简单的假设换取执行的效率,把一切错误的责任“推卸”给程序员。
缓冲区这种东西,有时候就是容易招致 bug。所以 Knuth 才有 过早优化是万恶之源 的说法。但人们并没有放弃使用这种优化方法,而是小心的去使用。据说软件工程在理论上提出了好多有效的原则(其中很多都是实践证明确实有效的),可以使得大型的项目成为可能,使很多工程避免过多的 bug。不过大多数这些原则,都不能,或很少能贯彻到实际的编程中去。所以真正有用的也许不是这些原则,而是如何贯彻这些原则的方法,或理念。
 
以上一堆费话而已,最近看了一本讲设计哲学的书,感触比较多罢了。
debroa 是个高手,他往往有真知灼见。我从他那里也学到了很多东西。
2009-12-22 12:02
ruinw
Rank: 1
等 级:新手上路
帖 子:4
专家分:0
注 册:2009-12-20
收藏
得分:0 
恩~ 谢7楼的提醒,我开始直观的以为溢出会报错... 大家抱歉了

cin多余的输入应该放在缓冲区里吧~
2010-08-25 08:40
快速回复:字符串结束符的疑惑???
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018994 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved