I need to be able to get data from a text file, which is presented in the following format:
Starting Cash: 1500
Turn Limit (-1 for no turn limit): 10
Number of Players Left To End Game: 1
Property Set Multiplier: 2
Number of Houses Before Hotels: 4
Must Build Houses Evenly: Yes
Put Money In Free Parking: No
Auction Properties: No
Salary Multiplier For Landing On Go: 1
To clarify, I need the data presented after the colon. I'm not really sure how to approach this. I was reading other questions and they all said to use fgets, but I don't know how long each line will be and we can't statically allocate C strings, so where would I store the line pointed to by fgets? Also, is it possible to do this using fscanf (we have learned how to do fscanf but not learned fgets)? My idea when approaching this was to get each line, and then scan each line with sscanf (I think that would work) using the string literals that I don't need:
sscanf(str, "Starting Cash: %d", &startingCash);
Would this work?
After opening the file with fopen(), you could do
float cash;
int turnlimit, plyrno, mult, house;
fscanf(fin, "%*[^:]: %f", &cash);
fscanf(fin, "%*[^:]: %d", &turnlimit);
fscanf(fin, "%*[^:]: %d", &plyrno);
where fin is the FILE pointer.
%[^:] would scan till, but not including, a : is encountered and the * is for assignment suppression; meaning the value for it would be read but not assigned anywhere.
After reading till the point before the :, the : itself followed by a space must be read. So a : must be there in the format string followed by a space.
See What is the purpose of using the [^ notation in scanf? .
Related
I have an input file where I have 2 very long numbers (somewhere at 10^8 digits) separated by a space. What I have to do is to read them , both of them from the last digit to first and put them in separate strings. Here is an example for 2 short numbers:
1234 5678
My program needs the numbers like a[ ]={4,3,2,1} and n[ ]={8,7,6,5} to work.
FILE *f;
char str[100000000],*ptr,avect[100000000],nvect[100000000];
f = fopen ("input.txt", "r");
fgets(str, MAX_NR_DIGITS, f); //read the whole line into a string
strrev (str); //inverse the string and I am gonna read n firstly and a secondly
nvect=strtok(str," ");
Here I stopped, because I don't know how strtok works. After mirroring, I have to give nvect number n in a string and give avect number a in a string. I think is a good solving method, BUT if you know a better one by elapsed time point of view, I am open. Thank you for help!
Basically how Strtok works is in the string provided it reads until it reaches a certain character or "delimiter" , in your case space, or " " is what you're using since the numbers are separated by a space, and then returns the string up until it the delimiter, here's a helpful link that might help
https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
1 42.4 73.45 Albany, N.Y.
2 35.05 106.39 Albuquerque, N.M.
3 35.11 101.5 Amarillo, Tex.
4 61.13 149.54 Anchorage, Alaska
5 33.45 84.23 Atlanta, Ga.
6 30.16 97.44 Austin, Tex.
Given a table like this in a .txt file in the format of int float float string, i have to read the file and put the data into correspoding arrays.
The data must be entered into parallel arrays where
column 1 is the cityid
column 2 is the x poistion
column 3 is the y position
column 4 is the city name
I can read the array but I don't know how i would put the data into the corresponding array.
i have tried using
while ((fscanf(filePtr, "%d %f %f %[^'\n']", cityid, x_location, y_location, city_name)) == 4)
but the loop goes through the entire file and only puts the very last entry into the array.
so i tried this loop
while (fscanf(filePtr, "%d %f %f %[^'\n']", tcityid, tx_location, ty_location, cityname) == 4)
{
cityid[i] = tcityid;
x_location[i] = tx_location;
y_location[i] = ty_location;
*city_name[i] = cityname;
}
so my thinking is that the fscanf will read one line and put into the each of the values into the corresponding variable then copy it to the array. My code will build and run but when it reaches the while loop it throws an error that says
An invalid parameter was passed to a function that considers invalid parameters fatal.
I think the issue is with the city_name, I'm not really sure how to deal it. Any help would be greatly appreciated.
Thank you
The problem is that scanf does not accept regular expressions in the format specification. Also, you cannot just simply use %s, because that stops at the first whitespace, so the state name would be cut off. The best I can suggest is that you read in a line using fgets() into a string named, say, 'line'. Then use sscanf to extract the first three numbers. Afterwards use strchr 3 times to find the 3rd space, that's where the city name starts. Finally use strdup() to make a copy of the city name that you can store in your array. You can't simply save the pointer into 'line' as line will be overwritten each time you read in a new line.
Wrong parameters passed to fscanf().
I am surprised your compiler did not warn of this. Check compiler settings or consider a new compiler.
Pass the address of int, float values.
Also amend [] specifier.
// while (fscanf(filePtr, "%d %f %f %[^'\n']",
// tcityid, tx_location, ty_location, cityname) == 4)
while (fscanf(filePtr, "%d %f %f %[^\n]",
&tcityid, &tx_location, &ty_location, cityname) == 4)
BTW #LaszloLadanyi idea is good to use fgets() to read the line and then use sscanf().
I am not new to programming, but I encountered this small problem and I can't seem to get it.
I want to read a file with dates and put them in another file with another format
Input example: 18.08.2015
Output example: 18-08-2015
Here is the code (dat1 has "r" permission and dat2 "w"):
char d[3];
char m[3];
char g[5];
while(fscanf(dat1,"%s.%s.%s\n",&d,&m,&g)==3)
{
fprintf(dat2,"%s-%s-%s\n",d,m,g);
}
On the other hand, this works fine if I use [space] instead of a [dot] in the input file.
(18 08 2015)
What am I missing? The solution has to be as simple as possible and with using fscanf, not fgetc or fgets, to be explained to students that are just beginning to learn C. Thanks.
The %s pattern matches a sequence of non-white-space characters, so the first %s will gobble up the entire string.
Why use char arrays at all, why not int?
int d;
int m;
int g;
while(fscanf(dat1,"%d.%d.%d\n",&d,&m,&g)==3)
{
fprintf(dat2,"%d-%d-%d\n",d,m,g);
}
The %d in fprintf will not output leading zeros though. You'll have to teach your students a little bit extra or leave it for extra credit.
Since the scanf format %s reads up to the next whitespace character, it cannot be used for a string ending with a .. Instead use a character class: %2[0-9] or %2[^.]. (Change the 2 to the maximum number of characters you can handle, and don't forget that the [ format code does not skip whitespace, so if you want to do that, put a space before the format code.)
Change
fscanf(dat1,"%s.%s.%s\n",&d,&m,&g)
to
fscanf(dat1,"%[^.].%[^.].%[^.]\n",d,m,g);
I've got a file that is formatted like this
A New Day Has Come (Radio Remix); 239
Ten Days; 227
Goodbye's (The Saddest Word); 198
Prayer; 313
I Surrender; 271
At Last; 209
Sorry For Love; 301
How would I use fscanf to grab the string, and also the number following the semicolon? I tried this
for(track = 0; track < albums[size].num_tracks; ++track){
fscanf(fileptr,"%s;%i",albums[size].tracks[track].name,albums[size].tracks[track].length);
//print out the tracks
printf("Track number %i : %s", track, &albums[size].tracks[track].name);
}
However, when the printf happens, the whole string isn't printed, rather something like
Track number 0 : A
Track number 1 : New
Track number 2 : Day
etc...
So as you can see, the code is capturing the individual words for some reason, rather than the entire string before the semi colon. Which expression would I use to grab the entire string? Edited for spelling
While fscanf might not be the best function to use in this case, formally one can still be use it to grab the string that ends with ; by using the following format specifier
fscanf(fileptr, "%[^;];%i",
albums[size].tracks[track].name,
&albums[size].tracks[track].length);
This will require the input file to adhere to very strict format requirements though. Note also that if your albums[size].tracks[track].length is an int object, then & operator is required before albums[size].tracks[track].length. When %i format specifier is used in fscanf it requies a pointer to int as argument.
Also, your printf does not look right. It should be
printf("Track number %i : %s", track, albums[size].tracks[track].name);
That & before albums[size].tracks[track].name is not supposed to be there.
You shouldn't fscanf is for formatted data. Your data isn't really formatted in a way friendly to fscanf. You'd be better off reading the whole line and then just searching for the semicolon.
I have a file that contains 80 characters per line. I want to go to a particular line that starts with "ATOM".
I tried with fscanf(f1," %s%*[^\n]", rec) and compare rec with strcmp(rec,"ATOM"), but it reads the next line from the match.
I also tried with fscanf("line_format", variables), but this reads somewhere else from the file.
The line is
ATOM 1 N MET A 1 36.643 -24.862 8.890 1.00 24.11 N
From this I want to read character by character and assign it to variables. I have a problem with the float values and spaces. If I find a space in a place of particular variable how do I read it? How do I read the float values if there is no space between them?
You can read each line from the input file using fgets(), tokenise it using strtok() or strtok_r(), compare the first token to "ATOM", and then parse the rest of the tokens using atof() or atoi() to convert them to floating point or integer numbers if necessary.
Although this is a bit of an overkill since the ATOM record in the PDB file has a well defined structure with fixed sized fields and any conformant pdb file would be much easier to parse. You just pick the relevant substrings and pass them to atof() or atoi().
I believe you had an error in your (not shown) line_format. You really should be able to just do:
if( fscanf(f1, "ATOM %d %s %s %s %d %f %f %f %f %f %s", /* ... */) == 11 )
{
/* store/analyze/print the parsed values */
}
Note of course that this runs the risk of overwriting the string arguments. You could use a more specific format string to limit the lengths.