1

So after scanf, the printf(); skips the first line
I have read some questions that tells that , "%[^\n]" must be " %[^\n]" to skip the newline.
I have tried it both, but it still print the same result and now I don't know why it doesn't work.

Example input
Enter number of Materi: 4
Materia 1 name : a
Materia 2 name : b
materia 3 name : c
materia 4 name : d

Output:
Materia - 1 : R╒fu
Materia - 2 : a
Materia - 3 : b
Materia - 4 : c
#include<stdio.h>
#include<windows.h>

int main(int argc, const char *argv[]){

    int i;
    int V;

    printf("Enter number of Materi: ");
    scanf("%d", &V); fflush(stdin);

    //Insert materia
    char materia[V][50];
    for(i = 0; i < V; i++){
        printf("Materia %d name : ", i+1);scanf("%[^\n]", &materia[i][50]);fflush(stdin);
    }

    for(i = 0; i < V; i++){
        printf("Materia - %d: %s\n", i+1, materia[i]);
    }
    system("pause");

    return 0;
}


  • 2
    `fflush(stdin)` is undefined behavior in c, and useless where defined by POSIX or Windows. `scanf("%[^\n]", &materia[i][50])` doesn't do what you think it does. – EOF May 09 '20 at 15:37
  • @EOF It actually ask to scan after i use fflush(stdin); , when i don't use it, it won't even scan at all – Christian Halim May 09 '20 at 15:38
  • 1
    You don't (reasonably) control your input. You *can* control your output. – EOF May 09 '20 at 15:39
  • Add a space to `"%[^\n]"` making it `" %[^\n]"` and this will filter leading whitespace. It is not automatic with this format (or with `%c`). – Weather Vane May 09 '20 at 15:40
  • @WeatherVane Do you mean, it is not possible to use within the ```for``` format ? – Christian Halim May 09 '20 at 15:41
  • I mean add the space as recommended. Format specs `%d` and `%s` and `%f` automatically filter out leading whitespace, but `%c` and `%[]` and `%n` do not. The `scanf` functions stop at the first character they cannot convert, which is left in the input buffer. You told `%[]` to stop at the first newline. There is one already there, from the first `%d` `scanf` and it needs to be removed, also in subsequent iterations and adding the space does that job. Trying to remove it *afterward* is clumsy and not guranteed to work. – Weather Vane May 09 '20 at 15:42
  • @WeatherVane i have tried adding space ``` %[^\n]```, but it still prints the same output edited: oops i mean [^\n] – Christian Halim May 09 '20 at 15:48
  • That does not look like `" %[^\n]"`. The `^` is missing. Also, remove the `fflush(stdin)`. – Weather Vane May 09 '20 at 15:49
  • 1
    There is another mistake: `&materia[i][50]` should be `materia[i]` – Weather Vane May 09 '20 at 15:51
  • @WeatherVane oh wait, what it works after i change ```&materia[i][50]``` to ```materia[i]``` – Christian Halim May 09 '20 at 15:53

3 Answers3

3

There are several mistakes in the program

  • The array passed to scanf is wrong.

  • fflush(stdin) is non-standard, although Windows does support it it's not portable. But you aren't using Windows because it does not support the VLA char materia[V][50];

  • The newlines which the scanf format "%[^\n]" will stop at, are already the next character in the input buffer.

  • The return value from scanf was not checked. It is the number of items successfully scanned.

  • You can have buffer overflow because the input string length is not restricted.

Here is the adjusted code:

#include<stdio.h>

int main(int argc, const char *argv[]){

    int i;
    int V;

    printf("Enter number of Materi: ");
    if(scanf("%d", &V) != 1) {
        /* add some error message */
        return 1;
    }
    // fflush(stdin);               // removed

    //Insert materia
    char materia[V][50];
    for(i = 0; i < V; i++){
        printf("Materia %d name : ", i+1);
        // add a space to filter the newline
        // correct the array passed
        // and restrict the length to prevent buffer overflow
        if(scanf(" %49[^\n]", materia[i]) != 1) {
            /* add some error message */
            return 1;
        }
        // fflush(stdin);           // removed
    }

    for(i = 0; i < V; i++){
        printf("Materia - %d: %s\n", i+1, materia[i]);
    }

    return 0;
}

About the newlines. Format specs %d and %s and %f automatically filter out leading whitespace, but %c and %[] and %n do not. The scanf functions stop at the first character they cannot convert, which is left in the input buffer. The %[^\n] tell it to stop at the first newline. But there is one already there, from the first %d scanf and it needs to be removed, also in subsequent iterations and adding the space does that job. Trying to remove it afterward is clumsy and not guranteed to work.

You must check the return value from scanf every time it is used. It is the number of items successfully scanned. Here, it should be 1 in both uses. So if you have two items in one statement, its return value must be 2.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
1

In the line:

scanf("%[^\n]", &materia[i][50]); 

You are storing the inputed string in the address of materia[i][50], effectively storing it outside the bounds of the array.

Something interesting happens here, 2D array storage is contiguous as if it was a one dimensional vector, what happens is you are storing the first string in the beginning of the second line of the array, the second on the third and so on, leaving the first empty. That's the rational for the output the program produces.

Correct you code with:

#include<stdlib.h>

//...

if(scanf(" %49[^\n]", materia[i] != 1) {
   puts("Read error");
   return EXIT_FAILURE;       
}

49 character + the nul terminator to avoid overflow, a space in the beginning of the specifier avoids the consuption of blank characters left in the stdin buffer. Always verify scanf return to avoid reading errors.

Some other issues:

anastaciu
  • 23,467
  • 7
  • 28
  • 53
0

Use fgets instead of scanf. The newline character is consumed as a character by your subsequent scanf. That's why you are facing this problem.

VHS
  • 9,534
  • 3
  • 19
  • 43