C语言 c 字符串,字符指针:需要帮助打印字符串和一些建议
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16923405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c strings, char pointers: need help printing the string and some advice
提问by ziggyyoyo
so far i have this code:
到目前为止,我有这个代码:
char *str;
scanf ("%s", &str);
printf("%s",&str);
system("pause");
it works, but the problem is after i press a key to continue the program (or end it), i get the following error:
它有效,但问题是在我按下一个键继续程序(或结束它)后,我收到以下错误:
Run-Time Check Failure #2 - Stack around the variable 'str' was corrupted.
运行时检查失败 #2 - 变量“str”周围的堆栈已损坏。
i have never played around with char pointers before and i would like to get an explanation to why i am getting this error and how to improve the format of which i receive a string input from the user. i know there are easier ways to this, but my ultimate goal is to get the simplest code to determine the size of the input, and not limit the user.
我以前从未玩过字符指针,我想解释一下为什么我会收到这个错误,以及如何改进我从用户那里收到的字符串输入的格式。我知道有更简单的方法,但我的最终目标是获得最简单的代码来确定输入的大小,而不是限制用户。
thanks in advance
提前致谢
回答by Nicholaz
Your 2nd part of the question (determining length of input beforehand) isn't possible with a simple scanf (except going more complex and reading/appending chunk by chunk).
您的问题的第二部分(事先确定输入的长度)不可能使用简单的 scanf (除了变得更复杂和逐块读取/附加)。
But at least the code below fixes your overwrite of random memory.
但至少下面的代码修复了你对随机内存的覆盖。
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");
You could use a very large buffer beforehand, and then trim the result back to given length, but you need max. length to start with.
您可以事先使用一个非常大的缓冲区,然后将结果修剪回给定的长度,但您需要最大。长度开始。
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");
回答by John Bode
You've declared stras a pointer, but you haven't given it a valid location to point to; it initially contains some random value that may or may not be a writable memory address. You still need to allocate a block of memory large enough to hold your input, either by declaring an array or by allocating memory with mallocor calloc.
你已经声明str为指针,但你有没有给它一个有效的位置,以点到; 它最初包含一些随机值,可能是也可能不是可写的内存地址。您仍然需要分配一个足够大的内存块来保存您的输入,方法是声明一个数组或使用malloc或分配内存calloc。
Secondly, the %sconversion specifier expects the corresponding argument to have type char *; since strhas that type, you don't need to use the &operator.
其次,%s转换说明符期望相应的参数具有类型char *;由于str具有该类型,因此您无需使用&运算符。
So, you'll need to do something like
所以,你需要做类似的事情
char str[SOME_SIZE];
or
或者
char *str = malloc( SOME_SIZE );
where SOME_SIZEis large enough to hold the string you enter plusone extra character for the 0 terminator.
whereSOME_SIZE足够大,可以容纳您输入的字符串以及0 终止符的一个额外字符。
You'd read and write the input as follows:
您可以按如下方式读取和写入输入:
scanf( "%s", str );
printf( "%s", str );
You don't need the &for either call. The %sconversion specifier expects the corresponding argument to have type char *. Under most circumstances1, an expressionof array type is converted to an expression of pointer type, and the value of the expression is the address of the first element in the array. If you declared stras an array, then in the scanfand printfcalls the expressionstr2will be converted to a char *. If you declared stras a char *, it's already the expected type.
&两个调用都不需要。的%s转换指定期望对应参数具有类型char *。在大多数情况下1,一个表达阵列类型的被转换为指针类型的表达式,表达式的值是数组中的第一元素的地址。如果您声明str为数组,则在scanf和printf调用中,表达式str2将转换为 a char *。如果您声明str为 a char *,则它已经是预期的类型。
Now, output is (typically) line-buffered, meaning it won't show up on your console unless there's a newline or the length of the string exceeds the buffer length. You will either want to add a newline to your print statement:
现在,输出(通常)是行缓冲的,这意味着它不会显示在您的控制台上,除非有换行符或字符串的长度超过缓冲区长度。您要么想在打印语句中添加换行符:
printf( "%s\n", str );
or call fflushon the standard output stream:
或调用fflush标准输出流:
printf( "%s", str );
fflush( stdout );
to make sure your output gets displayed.
以确保您的输出得到显示。
1 - The exceptions to this rule occur when the array expression is the operand of the
sizeof. _Alignof, or unary &operators, or is a string literal being used to initialize another array in a declaration.2 - Remember, this conversion operation applies to expressions, not objects. You'll occasionally hear someone claim that "arrays are pointers", but this isn't true; arrays and pointers are different animals completely.
1 - 当数组表达式是
sizeof. _Alignof,或一元运算&符,或者是用于在声明中初始化另一个数组的字符串文字。2 - 请记住,此转换操作适用于表达式,而不是对象。您偶尔会听到有人声称“数组是指针”,但事实并非如此;数组和指针是完全不同的动物。
回答by Mike
"my ultimate goal is to get the simplest code to determine the size of the input, and not limit the user."
"my ultimate goal is to get the simplest code to determine the size of the input, and not limit the user."
Yeah, therein lies the problem, once you do that things start to get tricky. You can't simply use an uninitialized pointer like that to get “as many” characters as you want. The simplest options are:
是的,这就是问题所在,一旦你这样做,事情就会开始变得棘手。您不能简单地使用像这样的未初始化指针来获取“尽可能多”的字符。最简单的选项是:
char *str = malloc(1000);
scanf ("%999s", str);
or
或者
char str[1000];
scanf ("%999s", &str);
of course this puts a constraint on the amount of input. (btw: You should really evaluate if there is a number which will satisfy this condition.)
当然,这会限制输入量。(顺便说一句:您应该真正评估是否存在满足此条件的数字。)
Now there are other options, but they start to move away from being portable. If you're using GCC there's a "dynamic" specificer that can be used:
现在还有其他选择,但它们开始远离便携性。如果您使用 GCC,则可以使用“动态”特定器:
char *str;
scanf("%ms", str); // dynamically allocate space for the size of input from the user
But using this now ties your hands to the compiler being used (also the version, this works for c99, earlier needs "%as")
但是现在使用它会将您的手与正在使用的编译器联系起来(还有版本,这适用于 c99,早期需要"%as")
Other than that, you can read the input in 1 character at a time and append it to a string you grow yourself, but that's an OS specific solution as you'll need to use ncursesand the getch()function on *nix or _kbhit()and _getch();in windoze.
除此之外,你可以同时读取1个字符输入并追加到你长大自己的字符串,但那是因为您需要使用操作系统特定的解决方案ncurses和getch()在* nix功能或_kbhit()与_getch();在windoze。
回答by Magn3s1um
Printf takes a pointer, not an address to a pointer. You should be using it like this:
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
//Maybe add null termination //You will have to make sure they don't try
//也许添加空终止 //你必须确保他们不尝试
回答by pinkpanther
You are scanning the str with out first allocating memory to it. But, by your luck it starts storing from a random address and hence printed well but your runtime system recognized that you ran into a memory area which you do not have priveleges.
您正在扫描 str 而不先为其分配内存。但是,幸运的是,它从一个随机地址开始存储,因此打印得很好,但是您的运行时系统识别出您遇到了一个您没有特权的内存区域。
Here is the solution: This is subjected to reallocfail when it can't acquire sufficient contigous memory
这是解决方案: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]='##代码##';
printf("%s",str);
system("pause");
}

