fgets() didn't print the first line - c

fgets() not printing the first line of the opened file.
this is the code i have done,
#include <stdio.h>
int main(int argc, char* argv[])
{
float num;
char const* const filename=argv[1];
FILE* file=fopen(filename,"r");
char line[256];
int j=0;
if(file!=NULL)
{
while(fgets(line,sizeof(line),file)!=NULL){
for(j=0; j<2;j++)
{
if(j==0)
{
fscanf(file,"%f",&num);
printf("%f \t",num);
}
else if(j==1)
{
fscanf(file,"%f",&num);
printf("%f \n",num);
}
}
}
fclose(file);
}
}
i get the output as,
650.000000 699.000000
99.000000 132.000000
150.000000 272.000000
128.000000 291.000000
302.000000 331.000000
95.000000 199.000000
instead of,
130.000000 186.000000
650.000000 699.000000
99.000000 132.000000
150.000000 272.000000
128.000000 291.000000
302.000000 331.000000
95.0000000 199.000000
I don't get the first line is my problem here. Please help me to solve this.

Your fgets reads the first line into line, which you never use. Then you proceed to read numbers directly from the file (not from line) using fscanf. The further calls to fgets basically consume the newlines from the file. Try switching fscanf to sscanf and read from line instead of file, or alternatively get rid of the fgets entirely and exit from the loop based on the return value of fscanf.

fgets() doesn't print anything, by definition. It only reads input.
In any event, your problem is that - each time through the while loop, the actions are one call of fgets() (the while loop condition) followed by two calls of fscanf(). Only the results read using fscanf() are output.
The first time through the loop, the data received by the first line of fgets() is simply discarded - so the first line will not be output at all.
On subsequent iterations, the only reason output isn't being skipped is that you're getting lucky. fscanf() - with your format string - stops reading when it encounters a whitespace character, but leaves that character waiting to be read from the file. If that is a newline character, it will be encountered by the next call of fgets(), which will return immediately (effectively discarding the newline).
The real problem is in how fgets() and fscanf(), when they are interleaved with each other to read the same file, interact with each other (in this case, because they handle newlines in ways that affect each other in unwanted ways). The usual guideline, in order to avoid such interactions, is to avoid mixing styles of input on the same file handle i.e. don't mix line-oriented input (e.g. fgets()) with formatted input (e.g. fscanf()) nor with character-oriented input (e.g. fgetc()) on the same file handle.
Incidentally, with your code as it stands, you will get even stranger behaviour if you change your input file slightly (e.g. merge two lines into one, add blank lines, etc). More data will be discarded, but the patterns of what is discarded will be a bit harder to pick.

Related

How fget works?

I am using gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
I am writing a very simple script to take string as input and print the same with the some custom message. First user enters the T(no. of times to take string) and then takes input by fgets.. I used this&this as reference. I am getting a very strange output ie fgets is adding some extra new lines and even loop is not working properly for T=2 it is asking input only once. Can anybody explain me what is wrong with snippet. Thanks in advance!
#include<stdio.h>
#include<string.h>
int main()
{
int T;
scanf("%d",&T);
while(T--){
char str[100]={""};
int i;
printf("Hello\n");
fgets(str,80,stdin);
i = strlen(str)-1;
if(str[i]=='\n')
str[i]='\0';
printf("World\n");
printf("%s\n",str);
}
return 0;
}
Please see the image reference for T=2, even T=2 it is taking string only once and order of printing statement is also not as expected.
This is because your scanf() call
scanf("%d",&T);
does not consume the new line character \n accompanied by your input.
When you input T, your input is 2Enter.
scanf() consumes the 2, sees \n and stops consuming, leaving \n in the input buffer.
When the fgets() gets called, it sees the \n in the buffer and treats this as the input.
To solve this, you have a few choices (in decreasing order of my subjective preference):
Use fgets() to get the first input, then parse it using strtol() to get T.
Add an extra fgets() after the scanf().
Add getchar() to consume one extra character. This works if you are certain that exactly one \n will be present after the input. So for example it won't work if you type 2SpaceEnter. Alternatively, you may use while(getchar() != '\n'); after the scanf() to consume everything up to a new line, but this may cause problems if an empty line is a valid input to your later fgets() calls.
If your implementation supports it, you may use fpurge(stdin) or __fpurge(stdin).
And, very importantly, do not use fflush(stdin) unless your implementation clearly defines its behavior. Otherwise it is undefined behavior. You may refer to this question for more details. Also, note that the fpurge() and fflush() methods may not work correctly if your input can be piped into the program.
This line
scanf("%d",&T);
reads the input until the first non-numeral is found, which is newline. Then fgets() reads that newline for its first input.
I suggest using fgets() to read the number too.
fgets(str,80,stdin);
sscanf(str, "%d", &T);
With your first call to scanf you allow the user to input an integer for the number of loops. They do so, and use a carriage return to signal the end of input. At this point scanf reads the integer, but leaves the end-of-line (\n) in the stream..
So when you call fgets, fgets gets from the stream until it reaches the first newline -- in you code, on the first loop, this is the very first character it encounters.
If you discard the newline before calling fgets, you should get your desired results. You can do this, for example by changing your first three lines to:
int T;
char newline;
scanf("%d%c",&T, &newline);
Although there are probably stylistically superior ways of doing this.
You have a newline character in the input stream when you press "enter" after typing 2 for the first scanf. This is consumed by fgets() initially, hence it prints nothing (You replace the newline by \0).
In the next line, your input is read and echoed after World because you are printing it after it.

gets not working in C under Unix

I am trying to input a string in C Language under Unix using gets function and it doesn't work!
It shows the following warning :
warning: the `gets' function is dangerous and should not be used.
If I run the program I dont get the input field.
The code is
#include<stdio.h>
int main()
{
int i;
char ch,newfile[10],content[100];
FILE *create;
printf("Enter New File Name to Create : ");
scanf("%s",newfile);
create=fopen(newfile,"w+");
printf("\nEnter Contents for %s : ",newfile);
//fgets(content,sizeof content,stdin);
//scanf("%s",&content);
//gets(content);
for(i=0;i<100;i++)
{
if(content[i]!='\0')
{
ch=content[i];
putc(ch,create);
}
else
break;
}
printf("\nYour File Is Created\n");
return 0;
}
Some one kindly help me out with this. I've commented all the possibilities that I tried.
Thank You!
raw scanf("%s") is just as dangerous as gets() (both are exposed to buffer overflows). You should use fgets() instead, which limits the length of the string.
Another difference between gets() and fgets() is that the latter puts the '\n' in the string, which while annoying at first glance allows you to see whether the line was truncated. What you should do is:
Use fgets()
Seek the '\n'
If it's present, then the line was small enough to fit the buffer. Just replace the '\n' with a '\0' and you're golden.
If it isn't present, then the user typed a line longer than the buffer. Depending on the situation, you are or aren't OK with this. But in both cases, you'll have to finish reading the line (either into a new buffer or simply by calling getchar() in a loop until you get the '\n' or EOF) before your next input.
The first scanf doesn't consume the end of line character -- you can study this by feeding say "foo bar" as the file name.
The next line should be formatted as scanf("\n%99s", content);
- note the '\n' in front to read the line feed, and the guard 99 to prevent buffer overflow. Still unfortunately this approach is not sufficient to produce expected results, if one types "foo bar" as the file name. Counter-intuitively 'bar' is read as the contents.
And finally the gets suffers from the same problem as the previous ones. (+ the major problem, that it doesn't have a guard against buffer overflow.)

C while loop feof

This is part of a much bigger program to make a filmgenie and for some reason the program crashes as it reaches this while loop and i don't understand what my problem is.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
FILE *fp, *fopen();
char *arrayoffilms[45];
int main()
{
char line[100],junk[100];
fp=fopen("filmtitles.txt","r");
int i=0;
while(!feof(fp)) {
fscanf(fp,"%[^\n]s",line);
strcpy(arrayoffilms[i],line);
fscanf(fp,"%[\n]s",junk);
i++;
}
fclose(fp);
printf("%s\n\n\n",arrayoffilms[i]);
return 0;
}
feof will never return true until an actual read attempt is made, and EOF has been reached. The read attempts usually have return values that indicate failure. Why not use those, instead?
Don't confuse the %[ and %s format specifiers; %[ doesn't provide a scanset for %s; %[^\n]s tells scanf to read "one or more non-'\n' characters, followed by a 's' character". Does that make sense? Think about it, carefully. What is the purpose of this format specifier? What happens if the user merely presses enter, and scanf doesn't get it's "one or more non-'\n' characters"? Before we look for non-'\n' characters, it's important to get rid of any '\n' characters. Any whitespace bytes in the format string will cause scanf to consume as much whitespace as possible, up until the first non-whitespace character. I'm going to presume you wanted %[^\n], or perhaps even %99[^\n], which would prevent overflows of line.
Perhaps you'd also want to count the number of bytes processed by scanf, so you can malloc the correct length and copy into arrayoffilms, for some reason I can't imagine. You can use the %n format specifier, which will tell you how many bytes scanf processed.
I noticed that you want to read and discard the remainder of a line. In my example, the remainder of a line will only ever be discarded if 99 characters are read before a newline is encountered. I'll use the assignment suppression '*': %*[^\n].
Combining these format specifiers results in a format string of " %99[^\n]%n%*[^\n]", two arguments (a char * for %[ and an int * for %n), and an expected return value of 1 (because 1 input is being assigned). The loop will end when the return value isn't 1, which will likely be caused by an error such as "reading beyond eof".
int length;
while (fscanf(fp, " %99[^\n]%n%*[^\n]", line, &length) == 1) {
arrayoffilms[i] = malloc(length + 1);
strcpy(arrayoffilms[i], line);
i++;
}
The problem might be about the feof. You want your while loop to terminate when you reach the end of the file, or in other words, when you can not get anything using fscanf.
You can go for the code below:
while(fscanf(fp,"%[^\n]s",line)) {
strcpy(arrayoffilms[i],line);
fscanf(fp,"%[\n]s",junk);
i++;
}
Also, error checking associated with file pointers is absolutely necessary and is a good habbit. You would definitely want to use it:
fp=fopen("filmtitles.txt","r");
if(fp == NULL) /* error handling */
printf("Could not open file: filename\n");
else{
/* do stuff */
}
A similar thing happens with fgets() so some people say to never use it. Look at it this way, if you say
while (!feof(ipf)) {
by the time feof() is true you've hit the end of the file. The byte you just read is garbage, maybe a NULL. Don't use it. This works:
while (!feof(ipf)) {
if (!feof(ipf)) {
ch = fgetc(ipf);
And it works for fgets() too, I've used it this way for years. If this were Pascal (or maybe Perl) and you read "until" feof that would work, it's a pre-test vs a post-test issue. So test twice.

How to read blank lines using %[^\n]s?

I am having a program where
fscanf(fp,"%[^\n]s",line);
is used for reading a line.
If I put in a while loop,
while(!feof(fp))
fscanf(fp,"%[^\n]s",line);
the above code works for first line and for the rest, I am getting
line as NULL. ( line = "" )
My file contains many lines even many blank lines. How can I make the above code work?
First, the conversion specifier would be %[^\n] (no s on the end).
Secondly, you don't want to use the %[ conversion specifier without an explicit size; otherwise you run the risk of a buffer overflow:
char line[132];
...
fscanf(fp, "%131[^\n]", line);
Third, this will leave the newline in the input stream, potentially fouling up the next read.
Finally, you don't want to use feof as your loop condition, since it won't return true until after you try to read past EOF, causing your loop to execute one too many times.
Frankly, I think the better option is to use fgets(); it will read everything up to and including the next newline or one less than the specified size. IOW, if line is sized to hold 20 characters and the input line has 80 characters (including the newline), fgets will read 19 characters and append the 0 terminator into line. If the input line is 10 characters, it will read the whole input line into line (including the newline).
fgets will return NULL on EOF or error, so you should structure your loop as
while (fgets(line, sizeof line, fp))
{
// do something with line
}
if (feof(fp))
// hit end of file
else
// error on read.
I'm pretty sure that \n is not allowed within a scanset. It would be helpful if you state what you're trying to code there.
If you want to read in entire lines, I'd strongly suggest you go for the fgets() library routine. With fgets() you're able to state, how much characters to read in at max, so you're able to avoid buffer overflows.

how to read scanf with spaces

I'm having a weird problem
i'm trying to read a string from a console with scanf()
like this
scanf("%[^\n]",string1);
but it doesnt read anything. it just skips the entire scanf.
I'm trying it in gcc compiler
Trying to use scanf to read strings with spaces can bring unnecessary problems of buffer overflow and stray newlines staying in the input buffer to be read later. gets() is often suggested as a solution to this, however,
From the manpage:
Never use gets(). Because it is
impossible to tell without knowing the
data in advance how many characters
gets() will read, and because gets()
will continue to store characters past
the end of the buffer, it is extremely
dangerous to use. It has been used to
break computer security. Use fgets()
instead.
So instead of using gets, use fgets with the STDIN stream to read strings from the keyboard
That should work fine, so something else is going wrong. As hobbs suggests, you might have a newline on the input, in which case this won't match anything. It also won't consume a newline, so if you do this in a loop, the first call will get up to the newline and then the next call will get nothing. If you want to read the newline, you need another call, or use a space in the format string to skip whitespace. Its also a good idea to check the return value of scanf to see if it actually matched any format specifiers.
Also, you probably want to specify a maximum length in order to avoid overflowing the buffer. So you want something like:
char buffer[100];
if (scanf(" %99[^\n]", buffer) == 1) {
/* read something into buffer */
This will skip (ignore) any blank lines and whitespace on the beginning of a line and read up to 99 characters of input up to and not including a newline. Trailing or embedded whitespace will not be skipped, only leading whitespace.
I'll bet your scanf call is inside a loop. I'll bet it works the first time you call it. I'll bet it only fails on the second and later times.
The first time, it will read until it reaches a newline character. The newline character will remain unread. (Odds are that the library internally does read it and calls ungetc to unread it, but that doesn't matter, because from your program's point of view the newline is unread.)
The second time, it will read until it reaches a newline character. That newline character is still waiting at the front of the line and scanf will read all 0 of the characters that are waiting ahead of it.
The third time ... the same.
You probably want this:
if (scanf("%99[^\n]%*c", buffer) == 1) {
Edit: I accidentally copied and pasted from another answer instead of from the question, before inserting the %*c as intended. This resulting line of code will behave strangely if you have a line of input longer than 100 bytes, because the %*c will eat an ordinary byte instead of the newline.
However, notice how dangerous it would be to do this:
scanf("%[^n]%*c", string1);
because there, if you have a line of input longer than your buffer, the input will walk all over your other variables and stack and everything. This is called buffer overflow (even if the overflow goes onto the stack).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *text(int n);
int main()
{
char str[10];
printf("enter username : ");
scanf(text(9),str);
printf("username = %s",str);
return 0;
}
char *text(int n)
{
fflush(stdin);fflush(stdout);
char str[50]="%",buf[50],st2[10]="[^\n]s";
char *s;itoa(n,buf,10);
// n == -1 no buffer protection
if(n != -1) strcat(str,buf);
strcat(str,st2);s=strdup(str);
fflush(stdin);fflush(stdout);
return s;
}

Resources