简体   繁体   中英

Reading in C using fscanf

I've did my research and did several attempts but none came to work and I don't know why because I'm almost the same as a begginer.

From a text file:

Hello;20

Wait;10

Please;5

I want to save the first word "Hello" into a variable and the number 20 in another one. The same goes for the rest of the lines.

I have this:

int main()
{

FILE* file;
char fileName[50];
int seconds;

file = fopen("order.txt","r");

while(fscanf(file,"%s;%d",&fileName,&seconds) != EOF)
{

printf("%s",fileName);
printf("\n");
sleep(seconds);

}

fclose(file);
}

I've tried to change things inside fscanf but nothing came to work, the output is the following:

Hello;20

Wait;10

Please;5

----------------------

I've tried something new (seems like I should edit this instead of creating an answer) which was getting the content from a file like this:

order.txt

hello.txt;20

wait.txt;10

please.txt;5

I want to get the file name one by one, open it, show the content for X time, all for the 3, which lead to me:

orderFile = fopen("order.txt","r");

        while(fscanf(orderFile,"%49[^;];%d",fileName,&seconds) == 2)
        {
            contentFile = fopen(fileName,"r");

            while(fscanf(contentFile,"%[^\t]",textContent) == 1)
            {
                printf("%s\n", textContent);
            }

            sleep(seconds);

            fclose(contentFile);
        }

        fclose(orderFile);

Yet, it only shows the first file content, wait 20 seconds, and then it ends the program. I want it to show the content for the whole files. How can I do it?

After accept answer

The following format "%49[^;];%d" reads in the previous line's '\\n' as part of the filename. Better to first consume leading whitespace

while(fscanf(file,"%s;%d",&fileName,&seconds) != EOF)       // OP original
while (2 == fscanf(file,"%49[^;];%d", fileName, &seconds))  // problem
while (2 == fscanf(file," %49[^;];%d", fileName, &seconds)) // better-space added

Even better: As data is per line , read the line and then parse the string . Suggest by @ jamesdlin

#define INT_STRING_SIZE_MAX  22
char buf[(sizeof fileName + INT_STRING_SIZE_MAX) * 2];  // I like 2x buffers

while(fgets(buf, sizeof buf, file) != NULL) {
  if (2 != sscanf(buf,"%49[^;];%d", fileName, &seconds)) {
    break;  // Maybe add format error message.
  }
  ...
}

In sscanf(buf,"%49[^;];%d"... , a " " is not needed as code is reading line-by-line and no "previous line's '\\n' " exist.

Normally, fscanf() with %s stops reading strings at whitespace, but in this case you want to stop at ; so you need to use a bracket expression (scan set) to exclude ; instead of %s .

Also I added 49 after the % to protect against buffer overruns, and also test that the two variables have been updated, and pass a char * rather than a char (*)[50] to for the %[^;] conversion specification.

 while (2 == fscanf(file,"%49[^;];%d", fileName, &seconds))

So I've used a little of Jasen code, and bluepixy, which was:

Instead of having:

while(fscanf(file,"%s;%d",&fileName,&seconds) != EOF)

I now have:

while(fscanf(file,"%[^;];%d",&fileName,&seconds) != EOF)

And it works. Yet, I don't know why?

As it is .txt it already reads the first one as a string? Why if I put %[^;]s it doesn't work? I did not understand it very well..

fscanf returns the number of successfully scanned items (see fscanf(3) man page). You should use:

while(fscanf(file,"%s;%d",&fileName,&seconds) == 2) 

Butt even that is dangerous. Better give the maximal width of your fileName , accept only 49 chars in [A-Za-z0-9_] (or whatever set is appropriate for you) (and keep a space for the ending 0 byte), so

  while(fscanf(file,"%49[A-Za-z0-9_];%d",&fileName,&seconds) == 2) 

Actually, I would loop on reading every line with getline(3) (or otherwise fgets ) and parse it separately (either using some sscanf , or perhaps parsing manually).

You need to define more what is the acceptable input. What characters can appear before the semicolon? Are you sure to want to accept all of them? Are you using UTF-8 ? CAn your input file contain naughty bytes? (eg non UTF-8 encoding, or control characters)? Does é (French accentuated e), (cherokee hv), Ы (cyrillic yeru), א (hebrew aleph), Ω (greek uppercase omega) count as a letter? Are spaces acceptable around the semi-colon? Maybe you want some UTF-8 library like libunistring ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM