Home > Software engineering >  string gets filled with garbage
string gets filled with garbage

Time:11-10

i got a string and a scanf that reads from input until it finds a *, which is the character i picked for the end of the text. After the * all the remaining cells get filled with random characters. I know that a string after the \0 character if not filled completly until the last cell will fill all the remaining empty ones with \0, why is this not the case and how can i make it so that after the last letter given in input all the remaining cells are the same value?

    char string1 [100];

    scanf("%[^*]s", string1);
    for (int i = 0; i < 100;   i) {
        printf("\n %d=%d",i,string1[i]);
}

if i try to input something like hello*, here's the output:

 0=104   
 1=101   
 2=108   
 3=108   
 4=111   
 5=0
 6=0
 7=0
 8=92
 9=0
 10=68

CodePudding user response:

You have an uninitialized array:

char string1 [100];

that has indeterminate values. You could initialize the array like

char string1 [100] = { 0 };

or

char string1 [100] = "";

In this call

scanf("%[^*]s", string1);

you need to remove the trailing character s, because %[] and %s are distinct format specifiers. There is no %[]s format specifier. It should look like this:

scanf("%[^*]", string1);

The array contains a string terminated by the zero character '\0'.

So to output the string you should write for example

for ( int i = 0; string1[i] != '\0';   i) {
    printf( "%c", string1[i] ); // or putchar( string1[i] );
putchar( '\n' );

or like

for ( int i = 0; string1[i] != '\0';   i) {
    printf("\n %d=%c",i,string1[i]);
putchar( '\n' );

or just

puts( string1 );

As for your statement

printf("\n %d=%d",i,string1[i]);

then it outputs each character (including non-initialized characters) as integers due to using the conversion specifier d instead of c. That is the function outputs internal ASCII representations of characters.

CodePudding user response:

I know that a string after the \0 character if not filled completly until the last cell will fill all the remaining empty ones with \0

No, that's not true. It couldn't be true: there is no length to a string. No where neither the compiler nor any function can even know what is the size of the string. Only you do. So, no, string don't autofill with '\0'

Keep in minds that there aren't any string types in C. Just pointer to chars (sometimes those pointers are constant pointers to an array, but still, they are just pointers. We know where they start, but there is no way (other than deciding it and being consistent while coding) to know where they stop.

Sure, most of the time, there is an obvious answer, that make obvious for any reader of the code what is the size of the allocated memory.

For example, when you code

char string1[20];
sprintf(string1, "hello");

it is quite obvious for a reader of that code that the allocated memory is 20 bytes. So you may think that the compiler should know, when sprinting in it of sscaning to it, that it should fill the unused part of the 20 bytes with 0. But, first of all, the compiler is not there anymore when you will sscanf or sprintf. That occurs at runtime, and compiler is at compilation time. At run time, there is not trace of that 20.

Plus, it can be more complicated than that

void fillString(char *p){
    sprintf(p, "hello");
}

int main(){
    char string1[20];
    string1[0]='O';
    string1[1]='t';
    fillString(&(string1[2]));
}

How in this case does sprintf is supposed to know that it must fill 18 bytes with the string then '\0'?

And that is for normal usage. I haven't started yet with convoluted but legal usages. Such as using char buffer[1000]; as an array of 50 length-20 strings (buffer, buffer 20, buffer 40, ...) or things like

union {
    char str[40];
    struct {
        char substr1[20];
        char substr2[20];
    } s;
}

So, no, strings are not filled up with '\0'. That is not the case. It is not the habit in C to have implicit thing happening under the hood. And that could not be the case, even if we wanted to.

Your "star-terminated string" behaves exactly as a "null-terminated string" does. Sometimes the rest of the allocated memory is full of 0, sometimes it is not. The scanf won't touch anything else that what is strictly needed. The rest of the allocated memory remains untouched. If that memory happened to be full of '\0' before the call to scanf, then it remains so. Otherwise not. Which leads me to my last remark: you seem to believe that it is scanf that fills the memory with non-null chars. It is not. Those chars were already there before. If you had the feeling that some other methods fill the rest of memory with '\0', that was just an impression (a natural one, since most of the time, newly allocated memory are 0. Not because a rule says so. But because that is the most frequent byte to be found in random area of memory. That is why uninitialized variables bugs are so painful: they occur only from times to times, because very often uninitialized variables are 0, just by chance, but still they are)

CodePudding user response:

The easiest way to create a zeroed array is to use calloc. Try replacing char string1 [100]; with char *string1=calloc(1,100);

  • Related