gets not working in C under Unix - c

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.)

Related

How can I fix the problem with gets() function in C?

There is a problem with gets function. The first gets I write does not work but the ones comes next works properly.
I put an extra gets() function at the beginning, program just skips it and gets the string I want. But it is not safe and reliable. So what is the problem with gets and how can I fix it?
if (choice == 1) {
printf("Please enter an English phrase with upper case: ");
gets(a);
gets(engphr);
for (i = 0; engphr[i] != '\0'; i++) {
As Eraklon mentions in their comment, the most likely cause is that you have a scanf call before the gets call, and the trailing newline from the previous input is getting consumed by gets before you have a chance to enter anything else.
You should never use gets anyway - it was removed from the standard library in the 2011 version of the language. It is inherently unsafe to use, and will introduce a security hole in your code. Use fgets instead. Its behavior is slightly different (it will save the trailing newline to the input buffer if there's room, where gets discarded it), but it's much safer:
if ( fgets( engphr, sizeof engphr, stdin ) ) // assumes engphr is declared as an array, not a pointer
{
// process engphr
}
Having said that, you really shouldn't mix calls to scanf and fgets, again because scanf will leave trailing newlines in the input stream from previous inputs, and fgets will immediately return after seeing that newline. Either read all input using fgets and use sscanf to read specific items from the input buffer, or read all input with scanf.

C skips user input from subsequent scanf statement [duplicate]

I've been having a lot of problems trying to figure out how to use scanf(). It seems to work fine with integers, being fairly straight forward scanf("%d", &i).
Where I am running into issues is using scanf() in loops trying to read input. For example:
do {
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
When I enter in a validly structured input like c P101, it seems to loop again before prompting me. This seems to happen even with a single:
scanf("%c", &c)
in a while loop. It'll do the loop twice before prompting me again. What is making it loop twice, and how do I stop it?
When I enter in less amount of input that programmatically wouldn't have another character or number such as q, pressing enter seems to prompt me to enter more. How do I get scanf() to process both single and double character entries?
When you enter "c P101" the program actually receives "c P101\n". Most of the conversion specifiers skip leading whitespace including newlines but %c does not. The first time around everything up til the "\n" is read, the second time around the "\n" is read into command, "c" is read into prefix, and "P" is left which is not a number so the conversion fails and "P101\n" is left on the stream. The next time "P" is stored into command, "1" is stored into prefix, and 1 (from the remaining "01") is stored into input with the "\n" still on the stream for next time. You can fix this issue by putting a space at the beginning of the format string which will skip any leading whitespace including newlines.
A similiar thing is happening for the second case, when you enter "q", "q\n" is entered into the stream, the first time around the "q" is read, the second time the "\n" is read, only on the third call is the second "q" read, you can avoid the problem again by adding a space character at the beginning of the format string.
A better way to do this would be to use something like fgets() to process a line at a time and then use sscanf() to do the parsing.
It's really broken! I didn't know it
#include <stdio.h>
int main(void)
{
int counter = 1;
char command, prefix;
int input;
do
{
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
printf("---%c %c%d---\n", command, prefix, input);
counter++;
} while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
g3---
The output seems to fit with Robert's answer.
Once you have the string that contains the line. i.e. "C P101", you can use the parsing abilities of sscanf.
See:
http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html
For question 1, I suspect that you've got a problem with your printf(), since there is no terminating "\n".
The default behavior of printf is to buffer output until it has a complete line. That is unless you explicitly change the buffering on stdout.
For question 2, you've just hit one of the biggest problems with scanf(). Unless your input exactly matches the scan string that you've specified, your results are going to be nothing like what you expect.
If you've got an option you'll have better results (and fewer security issues) by ignoring scanf() and doing your own parsing. For example, use fgets() to read an entire line into a string, and then process the individual fields of the string — maybe even using sscanf().
Perhaps using a while loop, not a do...while loop will help. This way the condition is tested before execution of the code.
Try the following code snippet:
while(command != 'q')
{
//statements
}
Also, if you know the string length ahead of time, 'for' loops can be much easier to work with than 'while' loops. There are also some trickier ways to dynamically determine the length as well.
As a final rant: scanf() does not "suck." It does what it does and that is all.
The gets() function is very dangerous (though convenient for no-risk applications), since it does not natively do any checking of the input. It is VERY commonly known as a point of exploit, specifically buffer overflow attacks, overwriting space in registers not allocated for that variable. Therefore if you choose to use it, spend some time putting some solid error checking/correction in.
However, almost invariably, either fgets() or POSIX getline() should be used to read the line — noting that the functions both include the newline in the input string, unlike gets(). You can remove the trailing newline from string read by either fgets() or getline() using string[strcspn(string, "\n")] = '\0'; — this works reliably.

Inputting characters and integers in a line in c reading characters from past input stream

I was always bad at inputting characters in C and this is another example. Though I understood (maybe) what's happening but I can't figure out the solution.
I have the following code
scanf("%ld %ld",&n,&m);
for(i=0;i<n;i++)
scanf("%ld",&array[i]);
for(i=0;i<m;i++)
{
fflush(stdin);
//inputting a character 'R' but it is picking '\n' from past buffer
scanf("%c",&query);
//As a result of above problem, it is also acting wierd for same reason
scanf("%ld",&d);
printf("%c %ld",query,d);
printf("\nI=%ld\n",i);
}
Please help me figure out the reason why its happening and what is the solution.
Using scanf with %d (or %ld) only extracts the number from the input stream; it leaves the newline in the stream.
So when you write scanf("%c", it reads that newline.
To fix this (if your intent is that scanf("%c" reads the first character of the next line), you need to flush the input of the previous line. One way to do that is:
int ch; while ( (ch == getchar()) != EOF && ch != '\n' ) { }
Your line fflush(stdin); causes undefined behaviour - don't do that. The fflush function is only for output streams.
Also , it is a really good idea to check the return value of scanf. If it was not what you expected then you may wish to take some action, instead of pretending that a number was entered.
Since you are tired of input issues, I can give you a method that can help to simplify your live.
I can observe that:
You have problems in handling end-of-lines.
Sometimes you need to input numbers and sometimes you need characters or another kind of input. So, you (think that you) are forced to use formatted input.
My advice is that you separate the issue of reading input from the issue of interpreting data entered from input.
The standard C brings only a few functions to handle input/output operations, in the standard header <stdio.h>.
If you are not interested in very sofisticated I/O results, the standard library is enough.
However, the functions of <stdio.h> usually have the effect that input is read one line at the time, which includes the end-of-line character: '\n'.
What you can do, then, it's what follows:
Read a line with fgets(..., stdin) and put the result in a buffer (not so long), used only for this purpose.
Once you have read an entire line, no more issues with end-of-line will bother you.
Then, re-read this line, that it's held in a buffer, and apply to it all the formatted input that you need.
A short example:
#include <stdio.h>
int main(void) {
char buffer[200] = ""; // Initialize array to 0's
long int n, m;
char c;
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%ld %ld",&n,&m);
// Now you have processed the "integer number" input,
// read input characters again, withou any "flushes" and extrange things:
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%c", &c);
fgets(buffer, sizeof(buffer), stdin);
// and so on...
}
Thus, every time you need to separate a section of input from a previous one, just do a new line reading with fgets(..., stdin), which stores the input in buffer, and then process the buffer with sscanf(), which applies the format string to the buffer instead of the input itself (in its flesh).
Note: This method can have a little problem: If the string input has more than sizeof(buffer) characters (in the example: 200), the line is not completely read. This situation can be handled by checking if the character before last in buffer is not equal to '\n' nor '\0'. In such a case, you would make automatically some kind of "flushing input" operation (reading and discarding characters till the next end-of-line is found).

How do I return a printf statement if the user inputs nothing?

I want to execute a statement based on the input of the user:
#include <stdio.h>
#include <string.h>
void main() {
char string_input[40];
int i;
printf("Enter data ==> ");
scanf("%s", string_input);
if (string_input[0] == '\n') {
printf("ERROR - no data\n");
}
else if (strlen(string_input) > 40) {
printf("Hex equivalent is ");
}
else {
printf("Hex equivalent is ");
}
}
When I run it, and just press enter, it goes to a new line instead of saying "ERROR - no data".
What do I do?
CANNOT USE FGETS as we have not gone over this in class.
Use
char enter[1];
int chk = scanf("%39[^\n]%c", string_input, enter);
but string_input will not have a '\n' inside. Your test
if (string_input[0] == '\n') {
printf("ERROR - no data\n");
}
will have to be changed to, for example
if (chk != 2) {
printf("ERROR - bad data\n");
}
use fgets instead of scanf. scanf doesn't check if user enters a string longer than 40 chars in your example above so for your particular case fgets should be simpler(safer).
Can you use a while loop and getch, then test for the <Enter> key on each keystroke?
scanf won't return until it sees something other than whitespace. It also doesn't distinguish between newlines and other whitespace. In practice, using scanf is almost always a mistake; I suggest that you call fgets instead and then (if you need to) use sscanf on the resulting data.
If you do that, you really ought to deal with the possibility that the user enters a line longer than the buffer you pass to fgets; you can tell when this has happened because your entire buffer gets filled and the last character isn't a newline. In that situation, you should reallocate a larger buffer and fgets again onto the end of it, and repeat until either you see a newline or the buffer gets unreasonably large.
You should really be similarly careful when calling scanf or sscanf -- what if the user enters a string 100 characters long? (You can tell scanf or sscanf to accept only a limited length of string.)
On the other hand, if this is just a toy program you can just make your buffer reasonably long and hope the user doesn't do anything nasty.
fgets does what you need. Avoid using scanf or gets. If you can't use fgets try using getchar
The problem is that "%s" attempts to skip white-space, and then read a string -- and according to scanf, a new-line is "whitespace".
The obvious alternative would be to use "%c" instead of "%s". The difference between the two is that "%c" does not attempt to skip leading whitespace.
A somewhat less obvious (or less known, anyway) alternative would be to use "%[^\n]%*[\n]". This reads data until it encounters a new-line, then reads the new-line and doesn't assign it to anything.
Regardless of which conversion you use, you want (need, really) to limit the amount of input entered so it doesn't overflow the buffer you've provided, so you'd want to use "%39c" or "%39[^\n]". Note that when you're specifying the length for scanf, you need to subtract one to leave space for the NUL terminator (in contrast to fgets, for which you specify the full buffer size).
What platform are you running on?
Is the character sent when your press the ENTER key actually '\n', or might it be '\r'? Or even both one after the other (ie. "\r\n").

Parsing input with scanf in C

I've been having a lot of problems trying to figure out how to use scanf(). It seems to work fine with integers, being fairly straight forward scanf("%d", &i).
Where I am running into issues is using scanf() in loops trying to read input. For example:
do {
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
When I enter in a validly structured input like c P101, it seems to loop again before prompting me. This seems to happen even with a single:
scanf("%c", &c)
in a while loop. It'll do the loop twice before prompting me again. What is making it loop twice, and how do I stop it?
When I enter in less amount of input that programmatically wouldn't have another character or number such as q, pressing enter seems to prompt me to enter more. How do I get scanf() to process both single and double character entries?
When you enter "c P101" the program actually receives "c P101\n". Most of the conversion specifiers skip leading whitespace including newlines but %c does not. The first time around everything up til the "\n" is read, the second time around the "\n" is read into command, "c" is read into prefix, and "P" is left which is not a number so the conversion fails and "P101\n" is left on the stream. The next time "P" is stored into command, "1" is stored into prefix, and 1 (from the remaining "01") is stored into input with the "\n" still on the stream for next time. You can fix this issue by putting a space at the beginning of the format string which will skip any leading whitespace including newlines.
A similiar thing is happening for the second case, when you enter "q", "q\n" is entered into the stream, the first time around the "q" is read, the second time the "\n" is read, only on the third call is the second "q" read, you can avoid the problem again by adding a space character at the beginning of the format string.
A better way to do this would be to use something like fgets() to process a line at a time and then use sscanf() to do the parsing.
It's really broken! I didn't know it
#include <stdio.h>
int main(void)
{
int counter = 1;
char command, prefix;
int input;
do
{
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
printf("---%c %c%d---\n", command, prefix, input);
counter++;
} while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
g3---
The output seems to fit with Robert's answer.
Once you have the string that contains the line. i.e. "C P101", you can use the parsing abilities of sscanf.
See:
http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html
For question 1, I suspect that you've got a problem with your printf(), since there is no terminating "\n".
The default behavior of printf is to buffer output until it has a complete line. That is unless you explicitly change the buffering on stdout.
For question 2, you've just hit one of the biggest problems with scanf(). Unless your input exactly matches the scan string that you've specified, your results are going to be nothing like what you expect.
If you've got an option you'll have better results (and fewer security issues) by ignoring scanf() and doing your own parsing. For example, use fgets() to read an entire line into a string, and then process the individual fields of the string — maybe even using sscanf().
Perhaps using a while loop, not a do...while loop will help. This way the condition is tested before execution of the code.
Try the following code snippet:
while(command != 'q')
{
//statements
}
Also, if you know the string length ahead of time, 'for' loops can be much easier to work with than 'while' loops. There are also some trickier ways to dynamically determine the length as well.
As a final rant: scanf() does not "suck." It does what it does and that is all.
The gets() function is very dangerous (though convenient for no-risk applications), since it does not natively do any checking of the input. It is VERY commonly known as a point of exploit, specifically buffer overflow attacks, overwriting space in registers not allocated for that variable. Therefore if you choose to use it, spend some time putting some solid error checking/correction in.
However, almost invariably, either fgets() or POSIX getline() should be used to read the line — noting that the functions both include the newline in the input string, unlike gets(). You can remove the trailing newline from string read by either fgets() or getline() using string[strcspn(string, "\n")] = '\0'; — this works reliably.

Resources