0

i'm currently doing an uni project which has to read a multiple lines sequence of inputs given in a .txt format. This is my first experience with C, so i don't know much about reading files with fscanf and then processing them. The code i wrote goes like this:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char tipo [1];
    float n1, n2, n3, n4;
    int i;
    FILE *stream;
    stream=fopen("init.txt", "r");
    if ((stream=fopen("init.txt", "r"))==NULL) {
        printf("Error");
    } else {
        i=0;
        while (i<4) {
            i++;
//i know i could use a for instead of a while
            fscanf(stream, "%s %f %f %f %f%", &tipo, &n1, &n2, &n3, &n4);
            printf("%s %f %f %f %f", tipo, n1, n2, n3, n4);
        }
    }
    return 0;
}

My "init" file is formatted like this:

L 150.50 165.18 182.16 200.50
G 768.12 876.27 976.56 958.12
A 1250.15 1252.55 1260.60 1265.15
L 200.50 245.30 260.10 275.00
A 1450.15 1523.54 1245.17 1278.23
G 958.12 1000.65 1040.78 1068.12

I don't know how to tell the program to skip a line after the first one is read.

Thanks for the help in advance!

Augusto Colongo
  • 3
  • 1
  • 1
  • 4
  • 1
    Passing the value of `&tipo` as the first argument is bad in 2 ways: you're passing a pointer to array of 1 char, but `%s` expects a pointer to char pointing to 1st char of a buffer with enough space to read a string of non-whitespace characters. A string in C is null-terminated, so in your case 2 characters are written, but your array has space for 1. – Ilja Everilä Oct 26 '17 at 10:25
  • I assume your code does not work. Explain how. – klutt Oct 26 '17 at 10:25
  • 3
    In general, avoid using `scanf` or `fscanf`. They're notoriously hard to use. Read each line one at a time with `fgets` and then you can use `sscanf` on each resulting string. – jamesdlin Oct 26 '17 at 10:26
  • Correct me if i am wrong. Is this your desired output?L 150.50 165.18 182.16 200.50 A 1250.15 1252.55 1260.60 1265.15 A 1450.15 1523.54 1245.17 1278.23 – Aditi Rawat Oct 26 '17 at 10:29
  • I'd argue that `fscanf` is *notoriously hard to use*. It's easy as hell. [Don't use it](https://stackoverflow.com/questions/2430303/disadvantages-of-scanf). – Andrejs Cainikovs Oct 26 '17 at 11:12

3 Answers3

1

Use fscanf(stream, "%*[^\n]\n") to skip line. Just add one if statement to check line number to skip. if (i == 2) to skip second line. Also change char tipo[1] to char tipo and change "%s" to "%c" in printf and fscanf

while (i++ < 4) 
{
    if (i == 2) // checks line number. Skip 2-nd line
    {
        fscanf(stream, "%*[^\n]\n");
    }
    fscanf(stream, "%c %f %f %f %f\n", &tipo, &n1, &n2, &n3, &n4);
    printf("%c %f %f %f %f\n", tipo, n1, n2, n3, n4);
}

Also you are opening file twice. if(streem = fopen("init.txt", "r") == NULL) will be true because you have already opened file.

Gor Asatryan
  • 904
  • 7
  • 24
  • Thanks a lot for the help, particularly with the fopen == null one. Since i'm a newbie, i didn't know that – Augusto Colongo Oct 26 '17 at 17:05
  • Just remove stream=fopen(“init.txt”,”r”) because you are opening file twice. You don’t need it. – Gor Asatryan Oct 26 '17 at 20:53
  • Note [the effect of trailing white space in a `scanf()` format string](https://stackoverflow.com/q/19499060/15168). It is mostly OK if the input will always be a disk file, but it is diabolically awful if a human might ever do the typing. – Jonathan Leffler Apr 26 '22 at 23:33
1

In response to "I don't know how to tell the program to skip a line after the first one is read."Just do this!

while (i<4) 
{
    i++;
    //i know i could use a for instead of a while
    fscanf(stream, "%s %f %f %f %f%", &tipo, &n1, &n2, &n3, &n4);
    if(i != 2) //skipping second line
        printf("%s %f %f %f %f", tipo, n1, n2, n3, n4);

}

Also there is no point in using an 1-element array. If you wish to just use a char element change it from char tipo [1]; to char tipo; and your respective "%s" to "%c". But if you wish it to be a string element : change it from char tipo [1]; to char *tipo; or char tipo [n]; and keep your "%s".

Aditi Rawat
  • 784
  • 1
  • 12
  • 15
0

There's no reason to use a char array (string) when you're only going to read one character.

Do this:

char tipo;

and

fscanf(stream, " %c %f %f %f %f%", &tipo, &n1, &n2, &n3, &n4);

and your code should work. Note the c instead of s.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • Note that this will read the newline into `tipo` after the first use (unless you take steps to read up to and including the newline). You might be better off using `" %c …"` where the space before the `%c` skips zero or more white space characters — such as blank, tab, and newline. However, you don't have control over `fscanf()` skipping blank lines this way. If you care about that, don't use `fscanf()` at all — read the lines with `fgets()` or POSIX `getline()` and then use `sscanf()` to parse the lines. – Jonathan Leffler Apr 26 '22 at 23:31