This is the code, it reads from a file and then it prints what is written in that file.
I don't know why but the last string of the file is readed twice.
Code
FILE* src = fopen(name_email_src, "r");
if (src == NULL)
{
printf("ERROR source file not found");
}
while(fgets(buff_src, sizeof(buff_src), src) != NULL)
{
fputs(buff_src, stdout);
}
fclose(src);
printf("%s", buff_src);
This is the output:
Date: Tue, 07 Feb 2017 21:32:46 +0100 (CET)
From: Rental <rental#house-rental.com>
To: me <me#upf.edu>
Message-ID: message2
Subject: Paga el alquiler ya.
Dear customer,
you are late in your payment, please pay or LEAVE!
Sincerely yours,
House rental
House rental
What can I do to solve this problem? Thank you.
printf("%s", buff_src); is printing the last line.
You have an extra call to printf() after your while loop:
while(fgets(buff_src, sizeof(buff_src), src) != NULL)
{
fputs(buff_src, stdout); // prints each line
}
fclose(src);
printf("%s", buff_src); // prints buff_src which still holds the last line
Just remove this unnecessary call to printf() and it will work as you expect.
fgets() reads line by line from the file. From the man page of fgets()
If a newline is read, it is stored into the buffer.
fgets(buff_src, sizeof(buff_src), src) /* read upto New line or EOF from src and store into buff_src */
when loop fails whatever buff_src contains that's been printed using last printf statement.
Related
I have a configuration file that I need to alter.
The structure of the file is:
resolution 12x34
interval 1234
So two strings with a whitespace delimiter. The code I use to alter it is this:
FILE *fp = fopen(configuration_file, "a+");
char str[100], key[100], value[100];
if(fp) {
while(fgets(str, 100, fp) != NULL) {
if(2 == sscanf(str, "%s %s", &key, &value)) {
if(strcmp(key, "resolution") == 0){
if(msg->resolution){
fprintf(fp, "%s %s\r\n", key, msg->resolution);
}
} else if(strcmp(key, "interval") == 0) {
if(msg->interval) {
fprintf(fp, "%s %d\r\n", key, msg->interval);
}
} else {
fputs(str, fp);
}
} else {
fputs(str, fp);
}
}
} else {
(void)printf("-- Configuration file not found (%s)\r\n --", configuration_file);
}
fclose(fp);
The idea was to read it line by line. According to the documentation for fgets says that it stops at newlines. String-scan each line and parse them into a key and value. So far so good, acting as expected. And then print the new line to the file, overwriting the line it had just scanned. This is where the problem comes in. If I use fprintf, only the first value, resolution, is processed. The result of it is:
resolution oldxres
resolution newxres
It overwrites the wrong line and skips the second entirely.
If I remove the fprintf and instead simply print the values it has found, it prints both as it is supposed to.
What am I missing here? Does fprintf push the file pointer?
And then print the new line to the file, overwriting the line it had just scanned.
Files don't work this way. Write to a new file. When finished, rename the new file to the old name. Alternatively, read the entire file into memory, change the contents in memory, then write it back.
You can rewrite individual lines is if the modified line never becomes longer than the original one. Otherwise the modified line will spill over the next line you have not read yet, and destroy it. In order to prevent this you would need some kind of look-ahead buffer, which is just too cumbersome and error-prone. In the worst case you'd need to read the entire file anyway.
I am trying to read lines from a list to my structs, and it is almost working. I am not really sure what the problem is, but the last line of the text file wont show up when I call for the structs and I do not think the words are placed right...
void loadFile(char fileName[], Song *arr, int nrOf) {
FILE *input = fopen(fileName, "r");
if (input == NULL) {
printf("Error, the file could not load!");
} else {
fscanf(input, "%d", &nrOf);
fscanf(input, "%*[^\n]\n", NULL);
for (int i = 0; i < nrOf; i++) {
fgets(arr[i].song, sizeof(arr[i].song), input);
fgets(arr[i].artist, sizeof(arr[i].artist), input);
fgets(arr[i].year, sizeof(arr[i].year), input);
}
for (int i = 0; i < nrOf; i++) {
printf("%s", arr[i].song);
printf("%s", arr[i].artist);
printf("%s", arr[i].year);
}
rewind(input);
printf("The file is now ready.\n");
}
fclose(input);
}
The text file starts with a number on the first line to keep track of how many songs there are in the list. I therefore tried with this:
fscanf(input, "%d", &nrOf);
fscanf(input, "%*[^\n]\n", NULL);
to be able to skip the first line after nrOf got the number.
EDIT:
Here is the struct:
typedef struct Song {
char song[20];
char artist[20];
char year[5];
} Song;
Here is the text file:
4
Mr Tambourine Man
Bob Dylan
1965
Dead Ringer for Love
Meat Loaf
1981
Euphoria
Loreen
2012
Love Me Now
John Legend
2016
And the struct is dynamic allocated:
Song *arr;
arr = malloc(sizeof(Song));
there are a combination of reasons why the last line(s) do not print
The main reason is the last line(s) were never read
Should not call fclose() in any execution path where the file failed to open
there is no need to call rewind() when the next statement is fclose()
Since the calls to printf() for the fields in the Song array are output, one right after another, this will result in a long long single line output to the terminal, Hopefully the terminal is set to automatically scroll after so many columns of output, but that cannot be depended upon.
When outputting an error message, it is best to output it to stderr, not stdout. The function: perror() does that AND also outputs the reason the OS thinks the error occurred. (it does this by referencing errno to select which error message to output.)
the following is the key problem:
if the input file contains one song info per line then the field year will either contain a trailing newline or the newline will not have been read. If the newline was not read, then the next call to fgets() which was trying to input the song title will only receive a newline then all following fields (of all songs) will be progressively further off.
Suggest after reading a song fields, use a loop to clear out any remaining characters in the input line, similar to:
int ch;
while( (ch = getchar( input )) && EOF != ch && '\n' != ch );
I have a file that's storing strings from the user's input (stdin)
However there are 2 situations
If I read it normally, my file will have an empty line at its end due to the newline from the last string the user introduced.
If I remove the \n from the input string, the file stores all strings in the same line, which is not wanted.
How can I simply remove that newline from the end of the file?
I can edit and provide some of my code if required.
EDIT: Let's say the last line of a file I already have is "cards"
when the cursor is in front of "cards", if I press the down arrow it doesn't go on to the next line, while in this case it can happen once.
For my code to function perfectly I can't let that happen,
Here's an example of what I have:
f=fopen(somefile, "w");
do
{
fgets(hobby, 50, stdin);
fprintf(f, "%s", hobby)
} while(strcmp(hobby,"\n") != 0);
The newline character1 at the end of the file is part of the last line. Removing it is possible but makes the last line incomplete, which will break many programs. For example, concatenating another file at the end of this file will cause the last line to be merged with the first line of the concatenated file.
A Yuri Laguardia commented, if you later reopen this file in append mode to write more lines, the first one added would be concatenated at the end of this last incomplete line. Probably not the intended behavior.
If you do not want the file to contain empty lines, check user input before writing the line into the file:
void input_file_contents(FILE *fp) {
char userinput[80];
printf("enter file contents:\n");
while (fgets(userinput, sizeof userinput, stdin)) {
if (*userinput != '\n') {
fputs(userinput, fp);
}
}
}
EDIT:
Your code does not test for termination at the right place: you write the empty line before the test. Do not use a do / while loop:
f = fopen(somefile, "w");
if (f != NULL) {
/* read lines until end of file or empty line */
while (fgets(hobby, 50, stdin) != NULL && *hobby != '\n') {
fputs(hobby, f);
}
}
1 The newline character is actually a pair of bytes <CR><LF> on legacy systems.
I'm having some trouble with my code. I'm trying to read in some previous commands saved to a file, and place them in my array to use for later.
Here is my relevant piece of code:
if( (pastHist = fopen("history.txt", "r+")) == NULL)
{
pastHist = fopen("history.txt", "w+");
}
else
{
printf("%s", "INSIDE the else!");
pastHist = fopen("history.txt", "r+");
fscanf(pastHist, "%s", fstring);
while (fstring != NULL)
{
printf("%s %s", "the read in string is: ", fstring);
strcpy(cmndLine[cmndIndex], fstring);
strcpy(cmndLinecpy[cmndIndex], fstring);
cmndIndex++;
cmndNum++;
fscanf(pastHist, "%s", fstring);
}
}
Now the code writes to the file fine. (the writing part is held elsewhere). If I read from a file I wrote to before and the file said:
ls
rmdir angel
history
then i use this print statement to double check what i'm reading... it prints out
"INSIDE the else! the read in string is: lsthe read in string is: rmdirthe read in string is: angelthe read in string is: historythe read in string is: historythe read in string is: history
... and it repeats that the last thing read in was history a million times. Why is this the case? I also tried with the while condition
while(getchar() != EOF)
but that gave me the same thing.
please help.
Thanks.
fstring can never be set to NULL by that call to fscanf. What you want to check is the return value of fscanf.
Your getchar() loop likewise does nothing useful - it's reading from the standard input, not from your file.
I know this is a dumb question, but how would I load data from a multiline text file?
while (!feof(in)) {
fscanf(in,"%s %s %s \n",string1,string2,string3);
}
^^This is how I load data from a single line, and it works fine. I just have no clue how to load the same data from the second and third lines.
Again, I realize this is probably a dumb question.
Edit: Problem not solved. I have no idea how to read text from a file that's not on the first line. How would I do this? Sorry for the stupid question.
Try something like:
/edited/
char line[512]; // or however large you think these lines will be
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
/* "rt" means open the file for reading text */
int cur_line = 0;
while(fgets(line, 512, in) != NULL) {
if (cur_line == 2) { // 3rd line
/* get a line, up to 512 chars from in. done if NULL */
sscanf (line, "%s %s %s \n",string1,string2,string3);
// now you should store or manipulate those strings
break;
}
cur_line++;
}
fclose(in); /* close the file */
or maybe even...
char line[512];
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
fgets(line, 512, in); // throw out line one
fgets(line, 512, in); // on line 2
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 2 is loaded into 'line'
// do stuff with line 2
fgets(line, 512, in); // on line 3
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 3 is loaded into 'line'
// do stuff with line 3
fclose(in); // close file
Putting \n in a scanf format string has no different effect from a space. You should use fgets to get the line, then sscanf on the string itself.
This also allows for easier error recovery. If it were just a matter of matching the newline, you could use "%*[ \t]%*1[\n]" instead of " \n" at the end of the string. You should probably use %*[ \t] in place of all your spaces in that case, and check the return value from fscanf. Using fscanf directly on input is very difficult to get right (what happens if there are four words on a line? what happens if there are only two?) and I would recommend the fgets/sscanf solution.
Also, as Delan Azabani mentioned... it's not clear from this fragment whether you're not already doing so, but you have to either define space [e.g. in a large array or some dynamic structure with malloc] to store the entire dataset, or do all your processing inside the loop.
You should also be specifying how much space is available for each string in the format specifier. %s by itself in scanf is always a bug and may be a security vulnerability.
First off, you don't use feof() like that...it shows a probable Pascal background, either in your past or in your teacher's past.
For reading lines, you are best off using either POSIX 2008 (Linux) getline() or standard C fgets(). Either way, you try reading the line with the function, and stop when it indicates EOF:
while (fgets(buffer, sizeof(buffer), fp) != 0)
{
...use the line of data in buffer...
}
char *bufptr = 0;
size_t buflen = 0;
while (getline(&bufptr, &buflen, fp) != -1)
{
...use the line of data in bufptr...
}
free(bufptr);
To read multiple lines, you need to decide whether you need previous lines available as well. If not, a single string (character array) will do. If you need the previous lines, then you need to read into an array, possibly an array of dynamically allocated pointers.
Every time you call fscanf, it reads more values. The problem you have right now is that you're re-reading each line into the same variables, so in the end, the three variables have the last line's values. Try creating an array or other structure that can hold all the values you need.
The best way to do this is to use a two dimensional array and and just write each line into each element of the array. Here is an example reading from a .txt file of the poem Ozymandias:
int main() {
char line[15][255];
FILE * fpointer = fopen("ozymandias.txt", "rt");
for (int a = 0; a < 15; a++) {
fgets(line[a], 255, fpointer);
}
for (int b = 0; b < 15; b++) {
printf("%s", line[b]);
}
return 0;
This produces the poem output. Notice that the poem is 14 lines long, it is more difficult to print out a file whose length you do not know because reading a blank line will produce the output "x�oA". Another issue is if you check if the next line is null by writing
while (fgets(....) != NULL)) {
each line will be skipped. You could try going back a line each time to solve this but i think this solution is fine for all intents.
I have an even EASIER solution with no confusing snippets of puzzling methods (no offense to the above stated) here it is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string line;//read the line
ifstream myfile ("MainMenu.txt"); // make sure to put this inside the project folder with all your .h and .cpp files
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Happy coding