到目前为止,我有这段代码:
char *str;
scanf ("%s", &str);
printf("%s",&str);
system("pause");
它有效,但问题是我按一个键继续程序(或结束它)后,我收到以下错误:
运行时检查失败#2 - 变量'str'周围的堆栈已损坏。
我之前从未使用过char指针,我想得到一个解释,为什么我收到此错误以及如何改进我从用户收到字符串输入的格式。我知道有更简单的方法,但我的最终目标是获得最简单的代码来确定输入的大小,而不是限制用户。
提前致谢
答案 0 :(得分:6)
问题的第二部分(预先确定输入的长度)不可能通过简单的scanf(除了更复杂和按块读取/附加块)。
但至少下面的代码修复了你对随机内存的覆盖。
char buffer[256];
char *str= buffer;
scanf ("%s", str); // or scanf ("%s", buffer); or scanf("%s", &buffer[0]);
printf("%s", str); // or printf("%s", buffer); or printf("%s", &buffer[0]);
system("pause");
您可以事先使用非常大的缓冲区,然后将结果修剪回给定长度,但您需要最大值。从头开始。
char *str= (char *)calloc(1,10000);
scanf ("%.9999s", str);
str= (char *)realloc(str, strlen(str)+1); // release excess memory
printf("%s", str);
free(str);
system("pause");
答案 1 :(得分:2)
您已将str
声明为指针,但您尚未将其指定为指向的有效位置;它最初包含一些随机值,可能是也可能不是可写存储器地址。您仍然需要通过声明数组或使用malloc
或calloc
分配内存来分配足够大的内存块来保存输入。
其次,%s
转换说明符期望相应的参数具有类型char *
;由于str
具有该类型,因此您无需使用&
运算符。
所以,你需要做一些像
这样的事情char str[SOME_SIZE];
或
char *str = malloc( SOME_SIZE );
其中SOME_SIZE
足以容纳您为<0>终结符输入加上一个额外字符的字符串。
您可以按如下方式阅读和编写输入:
scanf( "%s", str );
printf( "%s", str );
任何一个电话都不需要&
。 %s
转换说明符期望相应的参数具有类型char *
。在大多数情况下 1 ,数组类型的表达式将转换为指针类型的表达式,表达式的值是数组中第一个元素的地址。如果您将str
声明为数组,那么在scanf
和printf
调用表达式 str
2 将转换为char *
。如果您将str
声明为char *
,则它已经是预期的类型。
现在,输出(通常)是行缓冲的,这意味着它不会显示在控制台上,除非有换行符或字符串的长度超过缓冲区长度。您可能要在print语句中添加换行符:
printf( "%s\n", str );
或在标准输出流上调用fflush
:
printf( "%s", str );
fflush( stdout );
确保显示输出。
<小时/> 1 - 当数组表达式是
sizeof
的操作数时,会出现此规则的例外情况。 _Alignof
或一元&
运算符,或者是用于在声明中初始化另一个数组的字符串文字。
答案 2 :(得分:1)
"my ultimate goal is to get the simplest code to determine the size of the input, and not limit the user."
是的,其中存在问题,一旦你这样做,事情开始变得棘手。你不能简单地使用像这样的未初始化的指针来获得你想要的“尽可能多”的字符。最简单的选择是:
char *str = malloc(1000);
scanf ("%999s", str);
或
char str[1000];
scanf ("%999s", &str);
当然这会对输入量产生约束。 (顺便说一下:你应该真的评估是否有一个能满足这个条件的数字。)
现在还有其他选择,但他们开始摆脱可移植性。如果您正在使用GCC,那么可以使用“动态”特异性:
char *str;
scanf("%ms", str); // dynamically allocate space for the size of input from the user
但是现在使用它会将你的手绑在正在使用的编译器上(也就是版本,这适用于c99,之前需要"%as"
)
除此之外,您可以一次读取1个字符的输入并将其附加到您自己成长的字符串中,但这是特定于操作系统的解决方案,因为您需要使用ncurses
和{{ 1}}函数在* nix或windoze中的getch()
和_kbhit()
。
答案 3 :(得分:0)
Printf接受指针,而不是指针的地址。你应该像这样使用它:
scanf("%s", str)
printf("%s", str);
char * str = malloc(100); //allocates 100 bytes
scanf("%###c", str) //Gets line from STDIN. ### indicates how many to read MAXIMUM, so scanf("%2c", str) will read maximum 2 characters into str. Don't use s, since then you read until every whiteline.
int i = 0;
while(str[i] != NULL){
i++;
}
realloc(buf, i+1); //make the string fit tightly. I'm unsure if it will be null terminated
//也许添加空终止 //你必须确保他们不要尝试
答案 4 :(得分:0)
您正在扫描str而不首先为其分配内存。但是,幸运的是,它开始从一个随机地址开始存储,因此打印得很好但是你的运行时系统认识到你遇到了一个没有priveleges的内存区域。
以下是解决方案:当realloc
无法获得足够的连续记忆时,会遇到 #include<stdio.h>
#include<malloc.h>
#define MAX 100
int main(){
char *str=malloc(sizeof(char)*MAX);
int size=0;
int capacity=MAX;
char c;
int i=0;
while((c=getchar())!='\n'){
if(size==MAX-1){
capacity=2*MAX;
realloc(str,capacity);
}
str[i]=c;
i++;
}
str[i]='\0';
printf("%s",str);
system("pause");
}
失败
{{1}}