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.
Related
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.
I'm trying to write some code to read my text file from stdin char by char, line by line, without using fopen. I need 42 lines with a maximum of 100 chars.
Help me to get this working and explain to me how it works. Thank you!
int main()
{
char str[100];
fgets(str, sizeof(str), stdin);
fputs(str, stdout);
return 0;}
without using fopen
If open is tolerated. Why not use it with read ? This solution will allow you to read char by char.
int main(void)
{
int file_descriptor = open("./path", O_RDWR); /* Open with read/write */
char text_block[10]; // Random size
read(file_descriptor, text_block, 1); /* This will read 1 characters
from the file */
/* Then do what you want with the char readed. */
}
Considering this solution, here is a process which will work :
Use stat() function to know the size of the file (read the manual)
Use the same process as above but instead of read 1 char read the size of the file
Each line is separated by '\n' exept the last one. Just use this to separate your fully readed file into lines
I guess it's for homework... This code have an error and won't compile until you found it. Which mean search the manual on the net and read it.
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.
Say you have a file dog.txt
The
quick
brown
fox
jumps
over
the
lazy
dog
You can print the lines like this
#include <stdio.h>
int
main (void)
{
char buf[10];
FILE *fp = fopen ("dog.txt", "r");
while (fgets (buf, sizeof buf, fp))
printf ("%s", buf);
return 0;
}
But what if each "line" was separated by a null character (\0), instead of a newline (\n)? How would you print each "line" ?
The difference between "text" file handling and any other file handling is that the "text" functions assume certain things (for example, that \n is a separator). If that's not the case for you, you obviously cannot use the "text" manipulation functions. You do fread, and parse the content yourself.
If the file is not a text file (that is, if it contains non-printable ASCII characters), treat it as binary.
Rather than reading a "line" at a time (which is a text file concept), read in a buffer at a time (e.g. 1024 characters at a time).
Output each character that you read one at a time, unless you encounter whatever line delimiter the file uses (e.g. the "null" character in your question). When that character is encountered, output a newline instead.
You open a file in binary mode by including the "b" flag, e.g.
FILE *fp = fopen("dog.txt", "rb");
Use fread to read data one buffer at a time.
n = fread(buffer, sizeof(char), BUFFER_SIZE, source);
This is a trimmed down version of
WhozCraig’s
deleted answer
If all you want to do is dump data from the input file to stdout, replacing any imbedded null-chars (0) with newlines, then just do that. read-ahead buffering and such is honestly overkill for the simplicity of this problem, and besides, the fopen/fread/etc.. family already buffers for you.
Note: this assumes exactly what the OP specified, the this is otherwise a reagular "text" file save for the oddity that imbedded null-chars (0)'s should be treated as newlines in the output stream:
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[])
{
FILE *fp = NULL;
fp = fopen(argv[1], "rb");
do
{ // pull next char, break on EOF, subst '\n' on 0.
int ch = fgetc(fp);
if (EOF == ch)
break;
if (0 == ch)
ch = '\n';
fputc(ch, stdout);
} while (true);
fclose(fp);
return EXIT_SUCCESS;
}
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