File read in 'c' using fgets - c

If i have a text file with each line of different length, how does the following code work??
FILE *ptr;
char str[100];
ptr=fopen("hi.txt","r");
while(fgets(str,100,ptr)!=NULL)
{
........
........
}
In this code the 'str' will hold 100 characters which includes some of the characters from 2nd line of text file(if the 1st line of file is 90 chars then 10 chars from second line will also be read)..
If i am correct, can you please tell how to read exactly only one line during every ready?

fgets will read up to a single line OR the value passed in as the second parameter.
fgets man page
As long as none of your lines are longer than 99 characters (saving one for the NUL terminator, your code will work as expected.
If you call fgets on a line that is longer than N-1, your next read will continue where it left off and go another 99 bytes or until it finds the end of the line.

Related

Reading the string with defined number of characters from the input

So I am trying to read a defined number of characters from the input. Let's say that I want to read 30 characters and put them in to a string. I managed to do this with a for loop, and I cleaned the buffer as shown below.
for(i=0;i<30;i++){
string[i]=getchar();
}
string[30]='\0';
while(c!='\n'){
c=getchar(); // c is some defined variable type char
}
And this is working for me, but I was wondering if there is another way to do this. I was researching and some of them are using sprintf() for this problem, but I didn't understand that solution. Then I found that you can use scanf with %s. And some of them use %3s when they want to read 3 characters. I tried this myself, but this command only reads the string till the first empty space. This is the code that I used:
scanf("%30s",string);
And when I run my program with this line, if I for example write: "Today is a beatiful day. It is raining, but it's okay i like rain." I thought that the first 30 characters would be saved in to the string. But when i try to read this string with puts(string); it only shows "Today".
If I use scanf("%s",string) or gets(string) that would rewrite some parts of my memory if the number of characters on input is greater than 30.
You can use scanf("%30[^\n]",s)
Actually, this is how you can set which characters to input. Here, carat sign '^' denotes negation, ie. this will input all characters except \n. %30 asks to input 30 characters. So, there you are.
The API you're looking for is fgets(). The man page describes
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

Reading a C file line by line where each line has an unknown length

I am writing a program in C that opens a file and reads in the file line by line performing various actions with each string after it reads in the line.
Now my issue is that I have a loop set up so I read one line in and do the necessary things to that line and then move to the next one until the end of the file. The problem I am having is that I know the maximum line length is 80 characters but it can be less than this so I am having a lot of trouble stopping at the end of the line in order to properly perform the necessary actions.
I would attach code but I am stumped at this part and it is so early that I don't really know if my code would help as it is just at the reading stage. I am unable to figure out how to read in a line when it's length is unknown. Any help would be greatly appreciated!
Define a char buffer with a size at least 82 (80 chars + linefeed + null byte).
In a loop, repeatedly call fgets(buffer, sizeof buffer, file) to read one line and perform the tasks until you reach the end of file:
char buffer[82];
while (fgets(buffer, sizeof buffer, file)) {
/* handle the line in buffer */
...
}
caution: buffer contains a '\n' as the last character.

Reading line by line in C

Currently to read a file line by line in C I am using:
char buffer[1024];
while(fgets(buffer, sizeof(buffer), file) != NULL) {
//do something with each line that is now stored in buffer
}
However there is no guarantee in the file that the line will be shorter than 1024. What will happen if a line is longer than 1024? Will the rest of the line be read in the next iteration of the while loop?
And how can I read line by line without a maximum length?
Yes, the rest of the line will be read in the next iteration.
You can detect whether or not you read a whole line by inspecting the last character of the string (i.e. the one before the null terminator) to see if it is '\n' or not -- fgets passes '\n' through to you.
There is no Standard C function which will read a line whilst dynamically allocating enough memory for it, however there is a POSIX function getline() which does that. You could write your own that uses fgets or otherwise to do the reading, in a loop with realloc, of course.
From the standards §7.19.7.2,
char *fgets(char * restrict s, int n, FILE * restrict stream);
The fgets function reads at most one less than the number of
characters specified by n from the stream pointed to by stream into the
array pointed to by s. No additional characters are read after a
new-line character (which is retained) or after end-of-file. A null
character is written immediately after the last character read into
the array.
From MSDN,
fgets reads characters from the current stream position to and including the first newline character, to the end of the stream, or until the number of characters read is equal to n – 1, whichever comes first. The newline character, if read, is included in the string.
So, yes fgets will read the rest of the line in next iteration if the it doesn't encounters the newline character within sizeof(buffer)-1 range.
If you want to read the whole line in one shot, then it is better to go with malloc and, if needed, reallocing the memory as per your needs.

I/O in C Errors

I'm trying for hours to find the answer for this question i've got in university. I tried running this with writing a file with two lines of :
hello
world
and it reads the file perfectly, So i cant find the answer. I would appreciate your help !
A student wrote the next function for reading a text file and printing it exactly as it is.
void ReadFile(FILE *fIn)
{
char nextLine[MAX_LINE_LENGTH];
while(!feof(fIn))
{
fscanf(fIn,"%s",nextLine);
printf("%s\n",nextLine);
}
}
What are the two errors in this function?
You can assume that each line in the file is not longer than MAX_LINE_LENGTH characters, and that it is a text file that contains only alphabet characters, and that each line is terminated by '\n'.
Thanks.
It discards white space. Try adding multiple spaces and tabs.
It may evaluate a stream more than once, and If there is a read error, the loop never terminates.
See: Why is “while ( !feof (file) )” always wrong?
Reading strings via scanf is dangerous. There is no bounds checking. You may read past you MAX_LINE_LENGTH.(and boom! Segfault)
The main error is that fsacnf( fIn, "%s", nextLine ) doesn't scan a complete line.
From man page:
s
Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
Thus if you have a line "a b" the first fscanf() will scan just "a" and the second one "b" and both are printed in two different lines. You can use fgets() to read a whole line.
The second one is maybe that it's stated "each line in the file is not longer than MAX_LINE_LENGTH characters" but nextLine can contain atmost MAX_LINE_LENGTH-1 characters (+ '\0'). That problem becomes even more important if you replace fscanf() by fgets() because than nextLine must have also capacity to store '\n' or '\r\n' (depending on the platform you're on)
A correct way of doing that is:
void ReadFile(FILE *fIn)
{
char nextLine[MAX_LINE_LENGTH];
while(fgets(nextLine, MAX_LINE_LENGTH, fIn)) {
printf("%s", nextLine);
}
}
As some have posted using feof to control a loop is not a good idea nor using fscanf to read lines.

can't read string from file in c

I'm trying to read a text file line by line and printing the first 17 characters.
FILE *devices;
devices = NULL;
devices = fopen("devices.txt", "r");
char deviceaddr[17];
char addr[17];
char line[1024];
while (fgets(line,1024,devices) != NULL)
{
fscanf(devices,"%s", deviceaddr);
printf("%s\n", deviceaddr);
}
fclose(devices);
the output should be 00:07:80:4C:0E:EEfor the first line but it gives 6.
The while loop is reading a line of text, then the fscanf will read the next set of text (and possibly overrun that buffer incidentally). It seems as if you should just be printing the desired data inside the loop from the buffer line.
For example, suppose there are three lines of text.
00:07:80:4C:0E:EE --> ends up line buffer line
second --> ends up in deviceaddr
third line --> ends up in line (unless the fscanf did not consume newline)
There's no way the output can be "00:07:80:4c:0E:EE", since
that would result in undefined behavior, due to buffer
overrun—the string requires 18 bytes, but you only provide
17. You should never us "%s" in an fscanf without
specifying the length.
And you're calling fscanf on devices after having read
a line from it; if you're reading line by line, you want to use
sscanf on the line you've read.

Resources