-1

I'm trying to read a file line by line and getting a total of 6 variables from it on each line starting with a string followed by 5 ints The problem is everytime I try this the initial string just keeps the whole line and the ints are left with random numbers. so is there a way to stop that initial string on the 1st ";". The variables on the file are writen as: string;V1;V2;V3;V4;V5

FILE *fp;
fp = fopen("MP.txt","r");
char tipo[20];
int V1,V2,V3,V4,V5;
while(!feof(fp)){
    fscanf(fp, "%s;%d;%d;%d;%d;%d", tipo,&V1,&V2,&V3,&V4,&V5);
    printf("\n%s\v1:%d\V2:%d\V3:%d\V4:%d\V5:%d\n",tipo,V1,V2,V3,V4,V5);
}

I've also tried to add %[^;] after the string which I saw on a comment but it didn't work.

Also the initial string on the file has a different size on each line.

Leftor
  • 3
  • 2
  • 3
    Re “but it didn't work”: Never describe a problem as “it didn‘t work”. Show example input, show the observed results, and described the desired results. Scanning with `%s` includes semicolons. `%[^;]` is a way to exclude semicolons, but you may need to exclude other things, like new-line. Also `%[^;]` will not scan empty strings; to satisfy it as a match, there must be at least one character. But we cannot diagnose why it did not work for you without more information. – Eric Postpischil Jan 29 '22 at 01:06
  • 4
    You should check the return value of `fscanf`, it tells you how many arguments it managed to parse. I also recommend not to use `fscanf` but to read the line with `fgets` instead and then parse it with `sscanf`. Last but not least, [see Why is while(feof) always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Pablo Jan 29 '22 at 01:12
  • 4
    You're better off reading a full line with `fgets`, then using `strtok` with `;` as the delimiter to capture each field. – dbush Jan 29 '22 at 01:42
  • @Leftor "I'm trying to read a file line by line " --> code is not doing that well with `fscanf()`. Use `fgets()`. Who/what text suggested using `fscanf()`? – chux - Reinstate Monica Jan 29 '22 at 06:27

1 Answers1

2

The %s format specifier causes fscanf to read as much string as it can. There are two things you can do to stop it:

  • specify a maximum number of characters to read!
  • specify a character range ([..] instead of s)

On string inputs you should always give a maximum number of characters to read, which is your buffer size minus one:

char s[100];
scanf("%99s",...);

You can use a character range to specify only those characters valid as input or, as you want, a delimiter:

char s[100];
scanf("%99[^;]",...);  // read all characters up to but not including a ';'

Also, do not loop on EOF. An input loop should be of the form:

while (1)
{
  attempt_to_read_stuff();
  if (attempt_failed()) break;
  do_stuff();
}

You can often make the attempt-to-read-and-fail bit a part of your loop condition. In your case that would be:

FILE *fp = fopen("MP.txt","r");
if (!fp) complain_and_quit();  // Don’t forget to check file opened OK

char tipo[20];
int V[5];
while (fscanf(fp,"%19[^;];%d ;%d ;%d ;%d ;%d\n",tipo,V+0,V+1,V+2,V+3,V+4) == 6)
{
  printf("%s:%d:%d:%d:%d:%d\n",tipo,V[0],V[1],V[2],V[3],V[4]);
}

fclose(fp);

This accepts a very rigid file format (the one indicated by your post, with the addition that numeric fields can have whitespace between the number and the semicolon, in addition to the already-possible whitespace before a number). If the file does not conform, processing stops.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39