简体   繁体   中英

c strings, char pointers: need help printing the string and some advice

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.

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

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).

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");

You've declared str as 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 malloc or calloc .

Secondly, the %s conversion specifier expects the corresponding argument to have type char * ; since str has that type, you don't need to use the & operator.

So, you'll need to do something like

char str[SOME_SIZE]; 

or

char *str = malloc( SOME_SIZE );

where SOME_SIZE is large enough to hold the string you enter plus one extra character for the 0 terminator.

You'd read and write the input as follows:

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

You don't need the & for either call. The %s conversion specifier expects the corresponding argument to have type char * . Under most circumstances 1 , an expression of 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 str as an array, then in the scanf and printf calls the expression str 2 will be converted to a char * . If you declared str as a char * , it's already the expected type.

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 fflush on the standard output stream:

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.

"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:

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" )

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 ncurses and the getch() function on *nix or _kbhit() and _getch(); in windoze.

Printf takes a pointer, not an address to a pointer. You should be using it like this:

 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

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.

Here is the solution: This is subjected to realloc fail when it can't acquire sufficient contigous memory

 #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");    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM