1

I'm new to C programming. So I have maybe a simple question. So why fscanf with fopen(read mode) can't be used? I mean, from what I learned I must use fopen(write mode) first so then fopen(read mode) will work. If i use fopen(read mode) first before fopen(write mode) it wouldn't work like in this code. Another thing is, why fscanf can't read space in this code? I already tried %*s while fopen(read mode) first and it didn't work.

Here is my simple code:

int main() {
    FILE *fp;
    fp = fopen("Test.txt", "r+");
    char name[100], hobby[100];
    int age;
    fscanf(fp, "Name:%*s\nAge:%d\nHobby:%*s", &name, &age, &hobby);
    printf("\nScan Result\n%s\n%d\n%s", name, age, hobby);
    fclose(fp);
    return 0;
}

Test.txt file:

Name:This is a test
Age:21
Hobby:Play games

When I run it:


Scan Result
`░
0
 >m
Process returned 0 (0x0)   execution time : 0.016 s
Press any key to continue.

So did I miss something? or it isn't possible? Answer with the code given would be very helpful for me to learn better, thank you.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
LearnerC
  • 51
  • 6
  • 2
    Check the return value of the `fscanf` function. Always do that. But to be fair, the `scanf` functions are kinda limited and poor. You should avoid them and learn to write parsers yourself. – Cheatah Jun 15 '22 at 19:02
  • 2
    You shouldn't pass `&name` and `&hobby` but instead pass `name` and `hobby`. – Cheatah Jun 15 '22 at 19:03
  • The `*` in `%*s` means to read a string but not store it. Why do you have variables in for the two `%*s` fields? – Barmar Jun 15 '22 at 19:06
  • `%s` extract just a single word from the input. You can't use it for a multi-word input like `This is a test`. – Barmar Jun 15 '22 at 19:07
  • 1
    Use `fgets()` to read lines, not `fscanf()`. – Barmar Jun 15 '22 at 19:07
  • I use %*s for read word after space. So if I don't use that it just read "This" not full word like "This is a test" @Barmar – LearnerC Jun 15 '22 at 19:11
  • 2
    You need to read the scanf documentation, that's not what `*` means in `scanf`. If you want to read everything until a newline, use `%[^\n]` not `%*s`. – Barmar Jun 15 '22 at 19:12
  • I have some trouble if i use fgets, i can't figure out how to put a different word/line into each different data variables. For example, the name and hobby section will store into string variables which is the correct use for fgets, but how to put the age section into integer variables? @Barmar – LearnerC Jun 15 '22 at 19:14
  • 1
    After you use `fgets()` you can use `sscanf()` to parse it into a variable. – Barmar Jun 15 '22 at 19:16
  • Try just `%s` If that doesn't work split into two `fscanf` one for each line – Craig Estey Jun 15 '22 at 19:20
  • Don't put whitespace in the scanf format string without a good reason, every character is significant and has a purpose. With format types `%c` and `%[]` it can be necessary, but it is essential to understand how whitespace is handled both in the format string and in the input. Please see [What is the effect of trailing white space in a scanf() format string?](https://stackoverflow.com/questions/19499060/what-is-the-effect-of-trailing-white-space-in-a-scanf-format-string) – Weather Vane Jun 15 '22 at 19:27
  • 1
    Your compiler should be complaining loudly about `fscanf("Name:%*s\nAge:%d\nHobby:%*s", &name, &age, &hobby);`. If you are not getting warnings there, turn up your compiler diagnostics. – William Pursell Jun 15 '22 at 19:46

1 Answers1

2

%s reads a single word, use %[^\n] to read everything until a newline.

Don't put & before array names when scanning into a string. Arrays automatically decay to a pointer when passed as a function argument.

    fscanf(fp,"Name: %[^\n] Age: %d Hobby: %[^\n]",name,&age,hobby);

Or use fgets() to read one line at a time, then you can use sscanf() to extract from it.

char line[100];
fgets(line, sizeof line, fp);
sscanf(line, "Name: %[^\n]", name);
fgets(line, sizeof line, fp);
sscanf(line, "Age: %d", &age);
fgets(line, sizeof line), fp;
sscanf(line, "Hobby: %[^\n]", hobby);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 3
    Albeit somewhat beyond the OP's current skill level, the conversion string should be `"Name: %99[^\n] Age: %d Hobby: %99[^\n]"`. The line oriented alternative is good advice, but testing the return value or initializing the destination arrays is recommended. – chqrlie Jun 15 '22 at 19:26