c字符串,char指针:需要帮助打印字符串和一些建议

时间:2013-06-04 16:55:01

标签: c string pointers char scanf

到目前为止,我有这段代码:

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

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

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

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

提前致谢

5 个答案:

答案 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声明为指针,但您尚未将其指定为指向的有效位置;它最初包含一些随机值,可能是也可能不是可写存储器地址。您仍然需要通过声明数组或使用malloccalloc分配内存来分配足够大的内存块来保存输入。

其次,%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声明为数组,那么在scanfprintf调用表达式 str 2 将转换为char *。如果您将str声明为char *,则它已经是预期的类型。

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

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

或在标准输出流上调用fflush

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

确保显示输出。

<小时/> 1 - 当数组表达式是sizeof的操作数时,会出现此规则的例外情况。 _Alignof或一元&运算符,或者是用于在声明中初始化另一个数组的字符串文字。

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

答案 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}}