Reputation: 163
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?
Upvotes: 0
Views: 2629
Reputation: 153338
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.
Upvotes: 2
Reputation: 12392
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))
Upvotes: 1
Reputation: 1
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? (e.g. 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?
Upvotes: 0
Reputation: 163
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..
Upvotes: 1