1

到目前为止我有这个代码:

char *str;
scanf ("%s", &str);
printf("%s",&str);
system("pause");

它可以工作,但问题是在我按下一个键继续程序(或结束它)后,我收到以下错误:

运行时检查失败 #2 - 变量“str”周围的堆栈已损坏。

我以前从来没有玩过 char 指针,我想解释一下为什么我会收到这个错误,以及如何改进我从用户那里收到字符串输入的格式。我知道有更简单的方法,但我的最终目标是获得最简单的代码来确定输入的大小,而不是限制用户。

提前致谢

4

5 回答 5

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");
于 2013-06-04T17:05:25.580 回答
2

您已声明str为指针,但尚未为其提供指向的有效位置;它最初包含一些随机值,可能是也可能不是可写内存地址。您仍然需要分配一块足够大的内存来保存您的输入,方法是声明一个数组或使用mallocor分配内存calloc

其次,%s转换说明符期望相应的参数具有 type char *;由于str具有该类型,因此您无需使用&运算符。

所以,你需要做类似的事情

char str[SOME_SIZE]; 

或者

char *str = malloc( SOME_SIZE );

whereSOME_SIZE大到足以容纳您输入的字符串加上0 终止符的一个额外字符。

您将按如下方式读取和写入输入:

scanf( "%s", str ); 
printf( "%s", str ); 

你不需要&for 任何一个电话。%s转换说明符期望相应的参数具有type char *。在大多数情况下1,将数组类型的表达式转换为指针类型的表达式,表达式的值是数组中第一个元素的地址。如果您声明str为数组,则在scanfandprintf调用中,表达式 str2将转换为 a char *。如果您声明str为 a char *,则它已经是预期的类型。

现在,输出(通常)是行缓冲的,这意味着它不会显示在您的控制台上,除非有换行符或字符串的长度超过缓冲区长度。您将要在打印语句中添加换行符:

printf( "%s\n", str );

或调用fflush标准输出流:

printf( "%s", str );
fflush( stdout );

以确保您的输出得到显示。


1 - 当数组表达式是sizeof. _Alignof,或一元运算&符,或者是用于在声明中初始化另一个数组的字符串文字。

2 - 请记住,此转换操作适用于表达式,而不是对象。您偶尔会听到有人声称“数组是指针”,但这不是真的;数组和指针完全是不同的动物。

于 2013-06-04T17:24:17.763 回答
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 个字符的输入并将其附加到您自己增长的字符串中,但这是一个特定于操作系统的解决方案,因为您需要使用*nix 或windows中ncurses的函数。getch()_kbhit()_getch();

于 2013-06-04T17:18:18.397 回答
0

您正在扫描 str 而没有首先为其分配内存。但是,幸运的是,它从一个随机地址开始存储,因此打印效果很好,但是您的运行时系统识别出您遇到了一个您没有权限的内存区域。

这是解决方案: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");    
}
于 2013-06-04T17:01:51.967 回答
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

//也许添加空终止 //你必须确保他们不尝试

于 2013-06-04T16:56:49.547 回答