I'm using a fprintf function to print to a new file
I'm using the following command to write multiple times:
fprintf(fp, "%-25s %d %.2f %d",temp->data.name, temp->data.day, temp->data.temp, temp->data.speed);
The problem is that sometimes the file gets an extra new line as the first character.
Could this be lelftovers from some buffer, I don't really know...
typedef struct Data {
char name[26];
int day;
int speed;
float temp;
} Data ;
#spatz you were right, I'm kind of new to the string format thing and I was told to make one for a fscanf where I was to expect an undetermined amount of space between the bits of data, here is what I came up with, I'm pretty sure its the source of the problem:
check=fscanf(fp1, "%20c%*[^0-9]%d%*[^0-9]%f%*[^0-9]%d%*[^\n]%*c", name, &day, &temp, &speed);
only the first line get read normally and everything afterwards reads the new line of the previous line.
Can someone please show me the proper way to write this thing?
Rather than calling fscanf() over and over, and hoping that the newlines match up how you want, use fgets() to get one line at a time, parse it using fscanf(), and do error handling on a line-by-line basis. This will be less error-prone, and it sounds like it will clear up your problem with no extra effort.
Your problem is that name starts with a newline, and that newline ends up in the file.
In order to properly parse the file I would have to know its format, but for now I assume it's <string> <int> <int> <float> where the number of spaces between each element may vary.
The format string I would start with is simply "%s%d%d%f", and let fscanf() deal with the whitespace. With this format string I was able to properly parse lines like
foo 3 4 7
If this does not satisfy you feel free to elaborate on the format of the file you are parsing and I'll try to come up with solutions.
Related
I'm trying to implement a cycle which will read lines off a file until it finds a line with a specific format. Namely, until it finds a line with:
number number character number
and nothing (but spaces or tabs) until the newline. Specifically, the stuff I have to go through until I find such a line will always be the contents of a 'lines.rows' matrix, but its data points are not necessarily neatly ordered in 'lines' lines of 'rows' elements. They can have any amount of spaces, tabs or newlines between each element.
However, after lines.rows elements there will always be a line in the format I'm scanning for, after an arbitrary number of spaces, tabs or newlines following the last element of the matrix.
I've been trying for several hours to use fgets and fscanf in different ways to achieve this, but the output is simply not correct. Right now I have this:
for (i=0;i<lines;i++)
{
for(j=0;j<rows;j++)
{
fscanf(in_fp, "%d", &temp);
}
}
, which is working but takes way too long in large matrices. Aside from this I've tried, for example,
for (i=0;i<lines;i++)
{
fscanf(in_fp, "%*[^\n]\n", NULL);
}
, which did not work. The idea was to skip to the end of each line and then also read the new line so as to start at the beginning of the following line. However, by the end of this cycle my file was not pointing to the correct line (which would be one with the format specific above - %d %d %c %d). Instead, it was pointing to a 'random' line in the middle of the matrix at hand.
I also tried the same code as above but with an fgets. When I ran an fscanf following a cycle of fgets for all the lines of the matrix, I still did not read the line that should be coming next (with the format specified above).
If you have any input on how to achieve this, or how to make this question more understandable, I would be very thankful.
I have a text file full of points of the following format on different lines
LONG,LONG
i can successfully read each line and print it out, but I how can I parse the string in C such that I get each long of each point on its own?
Thanks!
if you have the line already, it's easiest to use sscanf() to do this:
long a, b;
if(sscanf(line, "%ld,%ld", &a, &b) == 2)
{
/* Successfully parsed two long integers, now store them somewhere I guess. */
}
Note that it's a good idea to check the return value of sscanf(), this protects you from wrongly accepting illegal data and getting undefined results.
You can do it in multiple steps too if you need more control, as #dasblinkenlights suggested. You can use strtol() to parse the first number from the start of the line, then if that succeeds look for the comma, and then parse the second number. It can be faster than sscanf(), but I wouldn't expect too much for something this simple.
There are many solutions to this.
One is to read the line, read the first long with strtol find the position of the comma that follows with strchr, and read the second number from there.
Another solution would be to read the line, and pass it to sscanf function with the format that accepts two comma-separated LONGs.
Use the string variant of scanf() if you say you've already got the line:
char* line;
long long1;
long long2;
sscanf(line, "%ld,%ld", &long1, &long2);
Indeed as #unwind suggests in his +1 answer, it's a very good idea to check the return value of scant(), which is the number of successfully read values.
Making a program that adds user records to text file; so far so good! Yet I ran into a problem that I can not figure out on my own.
int main()
{
FILE *fp;
struct info
{
char name[15];
char surename[15];
char gender[15];
char education[15];
} info;
char c;
int i,j,a;
struct info sem;
beginning:
scanf("%d",&a);
if (a==1)
and at this part if user chooses option one 1, program needs to check all the records per person in txt file and printf me every single person information who has bachelors education.
{
FILE *fp=fopen("info.txt", "r");
char tmp[256]={0x0};
while(fp!=NULL && fgets(tmp, sizeof(tmp),fp)!=NULL)
{
if(strstr(tmp,"bachelors"))
printf("test test");
fprintf(fp, "\n%s %s %s %s %s %s",
sem.name,
sem.surname,
sem.gender,
sem.education,);
}
if(fp!=NULL) fclose(fp);
goto beginning;
}
This code so far detects the word "bachelor" but doesn't want to print out the line where it detected it; any ideas how to solve it? Plus, any suggestions how to make sure program only checks education field and doesn't give me false positive if some one would be named Bachelors?
printf/fprintf procedures use internal buffers to avoid calling the syscall "write" everytime.
I would say that you should add a '\n' character at the end of your string to actually force flushing the buffers writing the test. Moreover your token "bachelors" has to be in the 256 first characters of your file.
Second question depends on how your file is formatted, and you are the only one who knows that.
What output do you actually get? You say it doesn't want to print out the correct lines, but does that mean it prints all lines, no lines, some but not others?
Looking at your program, I would hazard a guess that every line is being printed out. You need braces around if(strstr(tmp,"bachelors")) if you want more than one statement in the body of the if.
EDIT:
In addition to your braces problem, you are attempting to use fprintf to print back to fp, which was opened in read mode (using the r flag). You need to use read/update mode (r+) if you want to modify info.txt. However, this is probably not the way you want to do this.
Firstly, you stated you wanted to "printf" the data, which means printing to standard out. If so then you should use printf instead of fprintf. On the other hand it would seem likely that what you want to do is to read lines from one text file and print data out to another file. In that case you probably want two files.
Even with the above modifications, you will be printing the same data to file each time, since the sem struct is not being updated at all.
Finally, your fprintf format string expects six inputs and you only have four (and an erroneous trailing ,). Why?
I'm in my first year of Computer Sciences and I have to design a procedure that writes to a file with format (fprintf) and displays it with format (fscanf). But I can't get it to run properly; it compiles but when it gets to the fscanf part, it crashes. I've been looking around reference sites, YouTube videos and stuff but I can't get it to work without any success.
Except for the last 2 lines of codes, it does everything great. Its capable of writing the records I enter, in the .txt file. The problem is with the use of fscanf itself.
void write_with_format()
{
char name_of_file[100] = "grades.txt";
FILE *arch;
arch = fopen (name_of_file, "a");
char name[50];
char career[50];
char grades[100];
char total;
printf("Give me the name");
gets(name);
printf("Give me the career");
gets(career);
printf("Give me the grade");
gets(grades);
getchar();
fprintf (arch, "%s,%s,%s\n",name,career,grades);
fscanf(arch,"%s %s %f",&name,&career,&grades);
printf("%s %s %f",name,career,grades);
}
I'd appreciate any help regarding my code or the proper use of fscanf, thank you all.
This line is all wrong:
fscanf(arch,"%s %s %f",&name,&career,&grades);
grades is declared as char grades[100];, ie. a string, however you're trying to read a float into it. Same goes for the printf line below it, you're using %f and telling printf that you're passing a float, however you're passing an array. You also don't need to use the address-of operator (&) when passing arrays to functions, as you have with fscanf.
You should use fclose to flush the buffer and close the file stream once you're done with reading/writing a file.
Back to the fscanf line, what exactly do you expect it to do? The file position inidcator is at the end of the file, just after where you've appended the line produced by fprintf. Check the return value of fscanf and you'll see that it's returning EOF to report an error. The specific error value is stored in errno.
You can use rewind or fseek to set the position to the start of the file or back a certain amount, or you could always reopen the file. I know that I at least wouldn't have my read code in a write_with_format function.
gets is unsafe and should not be used as it has the potential to cause buffer overflows, use fgets(stdin, SIZE...) instead.
Turn up your compiler warnings. If by chance you're using gcc, the flag is -Wall. Just because your code compiles, doesn't mean that it's going to work properly (or at all).
You declare grades as an array of char's but are trying to read into it a float.
I am new to C programming, so I am having difficulties with the problem below.
I have a text file inp.txt which contains information like the following:
400;499;FIRST;
500;599;SECOND;
670;679;THIRD;
I need to type a number and my program needs to compare it with numbers from the inp.txt file.
For example, if I type 450, it's between 400 and 499, so I need write to the word FIRST to the file out.txt
I have no idea how to convert a character array to an int.
I think you'll want these general steps in your program (but I'll leave it to you to figure out how you want to do it exactly)
Load each of the ranges and the text "FIRST", "SECOND", etc. from the file inp.txt, into an array, or several arrays, or similar. As I said in the comment above, fscanf might be handy. This page describes how to use it - the page is about C++, but using it in C should be the same http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/. Roughly speaking, the idea is that you give fscanf a format specifier for what you want to extract from a line in a file, and it puts the bits it finds into the variables you specify)
Prompt the user to enter a number.
Look through the array(s) to work out which range the number fits into, and therefore which text to output
Edit: I'll put some more detail in, as asker requested. This is still a kind of skeleton to give you some ideas.
Use the fopen function, something like this (declare a pointer FILE* input_file):
input_file = fopen("c:\\test\\inp.txt", "r") /* "r" opens inp.txt for reading */
Then, it's good to check that the file was successfully opened, by checking if input_file == NULL.
Then use fscanf to read details from one line of the file. Loop through the lines of the file until you've read the whole thing. You give fscanf pointers to the variables you want it to put the information from each line of the file into. (It's a bit like a printf formatting specifier in reverse).
So, you could declare int range_start, range_end, and char range_name[20]. (To make things simple, let's assume that all the words are at most 20 characters long. This might not be a good plan in the long-run though).
while (!feof(input_file)) { /* check for end-of-file */
if(fscanf(input_file, "%d;%d;%s", &range_start, &range_end, range_name) != 3) {
break; /* Something weird happened on this line, so let's give up */
else {
printf("I got the following numbers: %d, %d, %s\n", range_start, range_end, range_name);
}
}
Hopefully that gives you a few ideas. I've tried running this code and it did seem to work. However, worth saying that fscanf has some drawbacks (see e.g. http://mrx.net/c/readfunctions.html), so another approach is to use fgets to get each line (the advantage of fgets is that you get to specify a maximum number of characters to read, so there's no danger of overrunning a string buffer length) and then sscanf to read from the string into your integer variables. I haven't tried this way though.