C 语言里如何给从键盘输出获得字符串动态分配内存

2018-12-07 00:53:24 +08:00
 xjr1022

关于动态分配内存,我看到的一个回答感觉太麻烦,该回答传送门

https://segmentfault.com/a/1190000007675747

于是我尝试用 realloc 函数分配内存, 结果只要输出 6 个以上字符,程序就终止,原因搜了半天没找到,难道只能一开始就给字符串分配足够大的空间吗 (菜鸟一枚,才学 C 没几天,求大神轻喷)

#include <stdlib.h>
#include<string.h>
void main() {
	char str[6];  
	char *new_str = str;
	//输入 6 个以上的字符
	scanf("%s", str);
	
	if (strlen(str)>sizeof str)
	{
		new_str = (char*)realloc(str, 100*sizeof(char));
	}
	prin
	return 0;
	
}

2785 次点击
所在节点    C
19 条回复
msg7086
2018-12-07 01:04:21 +08:00
> 难道只能一开始就给字符串分配足够大的空间吗

当然了。

类比一下。旅行团定酒店,起手先定 3 间双人房,然后来了个 20 个人的团,你说会发生什么事呢。
xjr1022
2018-12-07 01:05:24 +08:00
更正一下,prin 是 printf("%s",new_str);
xjr1022
2018-12-07 01:07:28 +08:00
@msg7086 就是为了避免这种越界溢出情况,我想着用 realloc 来改增大空间,然后就程序异常。。。
nccer
2018-12-07 01:11:06 +08:00
@xjr1022 你应该在 6 个字符的时候增大空间,大于 6 的判断条件已经越界了。
msg7086
2018-12-07 01:11:58 +08:00
@xjr1022 越界发生在增大空间之前。程序都炸穿了你稍后再增大空间还有什么用呢。
就像这 20 个人的团在酒店大堂睡了一晚以后,第二天你再去定其他 7 个房间……
kokutou
2018-12-07 01:20:11 +08:00
起手一个 char *str = malloc(1000 * sizeof(char));
输入超过 1000 就再改大点。
tomychen
2018-12-07 01:21:31 +08:00
你已经越界在先了
anonymous256
2018-12-07 01:26:10 +08:00
char str[6]; //你声明它的上限是 6
scanf 在读取时会检查是否溢出。

你可以用 gets 或 fgets(更安全)
int main()
{
char string [256];
fgets (string, 256, stdin);
printf ("%s\n",string);
return 0;
}
参考:http://c.biancheng.net/cpp/html/260.html
xjr1022
2018-12-07 01:27:12 +08:00
@msg7086 忘记说了,因为异常是发生在 main 函数结尾出,所以才想出这种方法能不能事后补救,不过看来是没救了,
tomychen
2018-12-07 01:47:55 +08:00
如果是真的有需要遇到不定长度,就得需要对每次输入处理了,如果只是学习的话,也就是楼上说的定个 256 或者 1024, 用 fgets 或者其他安全函数,也只是把超出的给截掉,而不是动态扩充。

还有 char *argv[]是个好东西
xjr1022
2018-12-07 01:54:01 +08:00
@tomychen 我也就是学习下,突发奇想,看来也只能这样了,谢谢啦
msg7086
2018-12-07 01:55:54 +08:00
@xjr1022 异常发生在结尾是因为,不是不报,时候未到。
还是拿旅行团做例子。那 20 个人的团有可能当场就来揍你了(比如复写了保护内存,直接 SEGFAULT ),也有可能等回家了以后把你告上法庭(比如复写得不多,直到程序退出清算内存空间的时候才发现内存乱套了)。
xjr1022
2018-12-07 01:59:55 +08:00
@msg7086 嗯嗯,是的,也是突发奇想,看来还是骗不了编译器~,果然还是得老老实实得按照传送门里得那种方法才行,谢谢辛苦回复啦 (●'◡'●)
xjr1022
2018-12-07 02:01:12 +08:00
@nccer 这就又回到了我传送门里得那种方法了,还是得老老实实得写,骗不了编译器~
tomychen
2018-12-07 02:20:26 +08:00
你可以放弃 scanf,当然 很多 C 语言的书里一直在强调这个函数,其实这是个很鸡肋的函数

真要可变简单点就是
int main(int argc, char *argv[]){
//process argv
}
然后 就是 getopt()

至于 scanf(),你可以用了 argv 和 getopt 忘了那个它
maokabc
2018-12-07 02:40:12 +08:00
char str[6];分配在栈上,哪能用 realloc 扩容?
geelaw
2018-12-07 02:42:59 +08:00
@xjr1022 #13 你这个想法是不对的。编译器可以完全不 care 你“骗没骗”它,在你违反标准里的一些规定的时候,受苦的是你自己的程序,而不是编译器——因为你的程序有了未定义行为,它的功能不再有保障。
kljsandjb
2018-12-07 08:21:14 +08:00
man realloc 先
rochek
2018-12-07 17:12:23 +08:00
其实,这个地方如果一定要用动态申请内存,是可以做到的
挂钩一下输入函数,重写将输入放进内存的代码

每次放进内存,都 malloc 空间
或者,每次都 realloc 内存

在这段内存用完之后,手动释放下

但是会很麻烦,不如不做
简单的做法就是一开始就申请足够的内存空间

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/515183

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX