I am after a simple task: reading one line at a time from a file, printing the line and appending all the content in a char array. It all started with a Segmentation fault (core dumped) from my project, I then kept on isolating my code until I reached this:
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp;
fp = fopen("read.txt","r");
char buffer[255];
char longBuff[1024] = "";
while(fgets(buffer, 255, fp)) {
printf("%s\n",buffer);
strcat(longBuff, buffer);
}
fclose(fp);
printf("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWTF%s\n", longBuff);
}
The read.txt file:
short
this is Longer
+++++
sad
And the Output:
sad++is Longer
sad++is LongerWWWWWWWWWWWWWWWWWWWTFshort
When I was confidently expecting:
short
this is Longer
+++++
sad
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWTFshortthis is Longer+++++sad
I have been over multiple similar questions and most answers refer to carriage return but I still don't understand this behavior and what is the cause for it.
The text file likely originated on a platform with "\r\n" line endings #M.M.
A simple solution takes advantage the should "\r" occur, it is overwhelming part of the line ending and can easily be lopped off. strcspn()
I now see #David C. Rankin suggested this.
while(fgets(buffer, sizeof buffer, fp)) {
// Find length of string not made up of '\n', '\r', '\0'
// This nicely lops off the line ending, be it "\n", "\r\n" or missing.
buffer[strcspn(buffer, "\n\r")] = '\0';
printf("<%s>\n",buffer);
}
Unfortunately when a text file line-endings employ "\r" only, fgets() (on a system expecting "\n") will not see any line ending. There a new approach is needed.
As I am using Linux, the problem was with the input file. After running file read I got read: ASCII text, with CR line terminators and the CR LT were causing that stage overwriting behavior. Created a new input file newFile: ASCII text with the same text and the output was as expected.
Related
Here's the file I want to read.
single
splash
single
V-Line
h-line
Macro for checking if string is equal.
#define STR_MATCH(a,b) (strncmp((a),(b),strlen(b)+1) == 0)
Here's what i'm using to read it.
void readMissilesFile(char* fileName)
{
FILE* mFile;
char missile[7];
/* Open the file. */
mFile = fopen(fileName, "r");
if (mFile != NULL)
{
while (!feof(mFile))
{
fgets(missile, 7, mFile);
if (!(STR_MATCH(missile, "\n")))
{
printf("Missile: %s", missile);
}
}
fclose(mFile);
}
else
{
perror("Could not open the file.");
}
}
So i'm having difficulties as its printing out spaces when I read the line. I tried to ignore this by ensuring it only reads 7 characters which is the max length of each missile. Then I made a macro called strcmp which just checks if they are equal(to hopefully not print it).
Please find the macro attached as well.
Thanks in advance and any help is great. :)
If I understand your question correctly you can replace the newline characters by using strcspn.
You should not use feof like this, this post explains why. A safe way to read the file till the end is to use fgets as stop condition in the while loop.
The container, missile should be one char bigger than the max size of the largest string to accomodate for '\0'.
Live sample
#include <string.h>
//...
char missile[10];
//...
if (mFile != NULL)
{
while (fgets(missile, 10, mFile)) //will read till there are no more lines
{
missile[strcspn(missile, "\r\n")] = '\0'; //remove newline characters
printf("Missile: %s ", missile);
}
}
//...
I would advise the reading of this post which has detailed info about fgets, namely the issue of newline characters consumption.
There is getline function in stdio.h which reads line until delimiter. Its a POSIX though, so if you are on Windows you may lack it.
Here is example implementation:
https://github.com/ivanrad/getline/blob/master/getline.c
I'm trying to read text file with C. Text file is a simple language file which works in embeded device and EACH LINE of file has a ENUM on code side. Here is a simple part of my file :
SAMPLE FROM TEXT FILE :
OPERATION SUCCESS!
OPERATION FAILED!\nRETRY COUNT : %d
ENUM :
typedef enum
{
...
MESSAGE_VALID_OP,
MESSAGE_INVALID_OP_WITH_RETRY_COUNT
...
}
Load Strings :
typedef struct
{
char *str;
} Message;
int iTotalMessageCount = 1012;
void vLoadLanguageStrings()
{
FILE *xStringList;
char * tmp_line_message[256];
size_t len = 0;
ssize_t read;
int message_index = 0;
xStringList = fopen("/home/change/strings.bin", "r");
if (xStringList == NULL)
exit(EXIT_FAILURE);
mMessages = (Message *) malloc(iTotalMessageCount * sizeof(Message));
while ((read = fgets(tmp_line_message, 256, xStringList)) != -1 && message_index < iTotalMessageCount)
{
mMessages[message_index].str = (char *) malloc(strlen(tmp_line_message));
memcpy(mMessages[message_index].str, tmp_line_message, strlen(tmp_line_message) -1);
message_index++;
}
fclose(xStringList);
}
As you se in the Sample from text file i have to use \n Feed Line character on some of my lines. After all, i read file successfuly. But if i try to call my text which has feed line \n, feed line character just printed on device screen as \ & n characters.
I already try with getline(...) method. How can i handle \n character without raising the complexity and read file line by line.
As you se in the Sample from text file i have to use \n Feed Line
character on some of my lines.
No, I don't see that. Or at least, I don't see you doing that. The two-character sequence \n is significant primarily to the C compiler; it has no inherent special significance in data files, whether those files are consumed by a C program or not.
Indeed, if the system recognizes line feeds as line terminators, then by definition, it is impossible to embed a literal line feed in a physical line. What it looks like you are trying to do is to encode line feeds as the "\n" character sequence. That's fine, but it's quite a different thing from embedding a line feed character itself.
But after all, i read file successfuly.
But if i try to call my text which has feed line \n, feed line
character just printed on device screen as \ & n characters.
Of course. Those are the characters you read in (not a line feed), so if you write them back out then you reproduce them. If you are encoding line feeds via that character sequence, then your program must decode that sequence if you want it to output literal line feeds in its place.
I already try with getline(...) method. How can i handle \n character
without raising the complexity and read file line by line.
You need to process each line read to decode the \n sequences in it. I would write a function for that. Any way around, however, your program will be more complex, because the current version simply doesn't do all the things it needs to do.
I searched the forum, and can't find the answer to this problem. It seems to be common, but none of the mentioned fixes are applicable.
This is my code for opening a file:
#include <stdio.h>
#include <string.h>
void main() {
FILE *input;
char path[200];
printf("Enter the full file path and file name in the following format:"
"\nC:\\Users\\Username\\etc......\\filename.extension\n");
fgets(path, 200, stdin);
printf("%s",path);
input=fopen(path,"r");
if (input==NULL) {
perror("The following errors were encountered");
return(-1);
}
}
printf(%s,path) correctly displays the path and name of the file I want to open, but fopen always returns invalid argument. I have also tried using a pointer to path in fopen, but this always crashes the program.
You are getting path with fgets. \n is considered a valid character by fgets. You need to remove it manually.
fgets(path, 200, stdin);
path[strlen(path) - 1] = '\0';
Your problem is probably that fgets does not remove the trailing '\n' from the input line before returning it. fopen cheerfully tries to open a file whose name contains '\n', but (assuming, as your code suggests, that you are using Windows) the operating system does not allow file names to contain that character, which is why you are getting an "Invalid argument" message. On a Unix-type system, where the kernel imposes far fewer constraints on file names, you would have instead gotten "No such file or directory". This may be why you didn't find any previous answers to this question; I know I've seen variations before.
Try this:
...
fgets(path, 200, stdin);
char *p = path + strlen(path) - 1;
while (isspace(*p)) p--;
*(p+1) = '\0';
printf("%s\n", path);
input = fopen(path, "r");
...
You will need #include <ctype.h> for isspace.
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
Is there a function in C to read a file with a custom delimiter like '\n'?
For example: I have:
I did write \n to exemplify in the file is the LF (Line feed, '\n', 0x0A)
this is the firstline\n this is the second line\n
I'd like the file to read by part and split it in two strings:
this is the firstline\n
this is the second line\n
I know fgets I can read up to a num of characters but not by any pattern. In C++ I know there is a method but in C how to do it?
I'll show another example:
I'm reading a file ABC.txt
abc\n
def\n
ghi\n
With the following code:
FILE* fp = fopen("ABC.txt", "rt");
const int lineSz = 300;
char line[lineSz];
char* res = fgets(line, lineSz, fp); // the res is filled with abc\ndef\nghi\n
fclose(fp);
I excpected fgets had to stop on abc\n
But the res is filled with: abc\ndef\nghi\n
SOLVED: The problem is that I was using Notepad++ in WindowsXP (the one I used
I don't know it happens on other windows) saved the file with different
encoding.
The newline on fgets needs the CRLF not just the CR when you type
enter in notepad++
I opened the windows notepad And it worked the fgets reads the string
up to abc\n on the second example.
fgets() will read one line at a time, and does include the newline character in the line output buffer. Here's an example of the common usage.
#include <stdio.h>
#include <string.h>
int main()
{
char buf[1024];
while ( fgets(buf,1024,stdin) )
printf("read a line %lu characters long:\n %s", strlen(buf), buf);
return 0;
}
But since you asked about using a "custom" delimiter... getdelim() allows you to specify a different end-of-line delimiter.