gets warning message in c [duplicate] - c

This question already has answers here:
Disable warning: the `gets' function is dangerous in GCC through header files?
(10 answers)
why gets() is not working?
(4 answers)
Closed 6 years ago.
I'm doing a school project in C where I have to make a function that gets a string input and reverses the string as an output. I could use scanf("%s", answer);, but this only stores the first word of the string. Therefore I decided to go with gets(answer). I know this is unsafe because it doesn't allocate a specific memory size in answer, but I allready did this when defining the array: char answer[100];
I'm not interested in using fgets because the teachers will compile using Cygwin and this warning usually only shows up on Terminal when using a Mac:
warning: this program uses gets(), which is unsafe.
It will display this in the terminal right before prompting the user to type in a string. The other problem I have is that gets(answer) sometimes catches input from the printf("Type a string: ") above it. Is there any way to unvoid this?
Source code:
#include <stdio.h>
#include <string.h>
void reverseString();
int main() {
char str[100];
printf("Type your string here: ");
gets(str); /* Catching return from prinf so add one extra */
gets(str);
reverseString(str);
}
void reverseString(char string[]) {
char temp;
int startChar = 0;
int endChar = strlen(string) - 1;
while (startChar < endChar) {
temp = string[startChar];
string[startChar] = string[endChar];
string[endChar] = temp;
startChar++;
endChar--;
}
printf("\nReverse string is: %s\n", string);
}
Running the code:
warning: this program uses gets(), which is unsafe.
Type your string here: hello world
Reverse string is: dlrow olleh
EDIT:
So I tried using fgets(str, sizeof(str), stdin), but it still skips the user input part. I allso defined a buffer size for str like this: #define BUFFER_SIZE 100 and added it to the array, char str[BUFFER_SIZE].
EDIT:
The apaerant reason why fgets(str, sizeof(str), stdin) isn't working, is because it catches the \n from stdin. I might have to flush it in one way or another.

The question as I understand it is to give you a way to read in a string with spaces. However you don't want to use fgets() because of some reason I didn't follow. Here is another way to do so.
scanf ("%[^\n]%*c", str);

Related

C program won't use printf after scanf [duplicate]

This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Why does printf not flush after the call unless a newline is in the format string?
(10 answers)
Closed 2 days ago.
I am new to C and am writing a very simple C program which just provides a input and repeats it back to you. The code shows the first print f which is a $ and lets you input something but will not print the text back to you. Here is the code:
char input[50];
printf("$");
scanf("%s\n", input);
printf("\n %s", input);
I thought it might have been a compile issue but nothing changes. I use make token which is the name of the file.
Remove the "\n" in the scanf() format string. The trailing "\n" instructs scanf() to match any number of white space characters and it will only know when it's done when encountering a non-white space character. Meanwhile you expect it to return after reading the first "\n". Consider using fgets() instead.
#include <stdio.h>
int main() {
char input[50];
printf("$");
scanf("%s", input);
printf("\n %s", input);
}
and example session:
$abc
abc

User inputs a sentence (string). How to finish the input with Enter in C?

I've tried different types of string input(scanf, getchar, gets), but none of them can finish input with Enter. Do you guys have any ideas?
As Cheatah said, the function you looking for is fgets(). Always try to avoid gets() as it offers no protections against a buffer overflow vulnerability and can cause big problems in your program. You can read some of the answers to this question to clarify the utility of each function
Scanf() vs gets() vs fgets()
#include <stdio.h>
char str[20]; // String with 19 characters (because last character is null character)
int main() {
fgets(str, 20, stdin); // Read string
puts(str); // Print string
return 0;
}

Why does gets() read in more characters to the pointer than the limit I set it when initializing it with calloc()? [duplicate]

This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Closed 4 years ago.
I'm trying to get a hold of dynamic memory allocation and I just want my program to get a string and the max number of characters that should be printed from the string from the user, then just output the string up to the number of characters I allocated with calloc. When I run the program, it completely disregards the limit I set for it using calloc() and just prints out the whole string.
I tried using malloc but had the same results. Also, I dereferenced text when I first tried printing out the inputted text but it caused the program to stop after you entered the string you wanted printed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int max;
char *text = NULL;
printf("\n\n");
printf("Please enter the limit for the string as a positive integer: \n");
scanf("%d", &max);
text = (char *)calloc(max, sizeof(char));
if (text != NULL)
{
printf("Please enter the string you want printed: \n");
scanf(" "); //read in next character so it pauses
gets(text);
printf("Inputted text is : %s\n", text);
}
free(text);
text = NULL;
return 0;
}
Yes, I know, I get the warning that gets is unsafe but I was watching from a tutorial and the instructor's version built and ran fine. Even if I use scanf to read in a string into text, the result it the same.
Revised code using fgets():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int max;
char *text = NULL;
printf("\n\n");
printf("Please enter the limit for the string as a positive integer: \n");
scanf("%d", &max);
text = (char *)calloc(max, sizeof(char));
if (fgets(text, max, stdin))
{
printf("Please enter the string you want printed: \n");
fgets(text, max, stdin);
text[strcspn(text, "\n")] = '\0';
printf("Inputted text is : %s\n", text);
}
free(text);
text = NULL;
return 0;
}
I changed my code to use fgets instead and made some corrections. It returns 1 less character than the "max" the user inputs. Also, does using fgets mean I don't need to bother with calloc?
When you allocate memory and assign it to a pointer, there is no way to deduce the size of the memory from the pointer in hand. So gets has no chance (and will therefore not check) if it will exceed the amount of memory you reserved. BTW: gets is not part of C standard any more (since C11). Use fgets instead and pass your max as argument:
if (fgets(text, max, stdin)) {
// something successfully read in
text[strcspn(text, "\n")] = '\0';
}
Note that fgets, in contrast to gets, preserves any entered new line and keeps it at the end of text. To get rid of this, you can use text[strcspn(text, "\n")] = '\0', which will let the string end at the new line character (if any).
I think the exact reason your code is disregarding the max variable is that the gets() function is writing over all the null bytes in your text character array when the string provided on standard input is longer than max. This is one of the many reasons why we always say “never use gets()”!
More specifically, gets() will continue to write into your array from stdin until it reaches a newline or EOF character, with no regard to the bound of it. The fact that you’re seeing the entire string printed if just undefined behavior.

Program is not writing to the file after a whitespace is encountered in the string [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 5 years ago.
For Example if I
Input: 'stephen 8108' it outputs
'stephen'
Instead of outputing 'stephen 8108'.
Can someone help me out!
I want the full string to appear in the output.
It reads the string only till the first white space.
Even if i remove the for loop condition it doesn't seem to work it still reads only till the first white space.
#include<fcntl.h>
#include<stdio.h>
#include <unistd.h>
void main()
{
char a[100];
int i,f2,f3,f4;
f2 = creat("a.txt",0666);
f3 = open("a.txt",O_RDWR);
printf("Enter your name & Roll-no\n");
scanf("%s",a);
for(i=0;a[i] != '\0';i++);
write(f3,a,i);
close(f3);
}
This is intended sprintf functionality.
Cite: http://www.cplusplus.com/reference/cstdio/scanf/
Any number of non-whitespace characters, stopping at the first whitespace character found.
One option is to use the negated character matching (quoted from link above):
[^characters] Negated scanset
Any number of characters none of them specified as characters between the brackets.
For example, to match everything excluding a newline:
scanf("%[^\n]", a);
(Full working example below - although please don't take this as necessarily a full and perfect example of reading user input in C++...)
#include<fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
char a[100];
int fp;
fp = open("a.txt", O_CREAT|O_WRONLY|O_TRUNC);
printf("Enter your name & Roll-no\n");
scanf("%[^\n]", a);
write(fp, a, strlen(a));
close(fp);
}
However: I would really encourage you to read the extensive warnings about buffer overflows: https://stackoverflow.com/a/1248017/817132
In short, make sure you don't allow the user to write beyond your (currently 100 character long) memory allocation.
At the current state of your code, the for loop doens't have a body { ... } , so the write and the close operations would be executed only one time.
Also if you want scanf to read a string with spaces you can use %[0-9a-zA-Z ] instead of %s
Regarding the input, there are at least two problems:
The s conversion of scanf() parses until it finds whitespace, it's documented that way.
Without a field width, scanf() will continue parsing when it doesn't find whitespace, overflowing your buffer -> undefined behavior.
The quick fix is to replace scanf("%s",a); with scanf("%99[^\n]",a);. But scanf() is definitely not the best tool to read input, it is for parsing. You seem to just want to read a whole line of input and there is already a function for that: fgets(). Use it in your example like this (include string.h if you want to use this method of stripping the newline character):
fgets(a, 100, stdin);
a[strcspn(a, "\n")] = 0; // remove the newline character if it was read by fgets

Reading string from input with space character? [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 4 years ago.
I'm using Ubuntu and I'm also using Geany and CodeBlock as my IDE.
What I'm trying to do is reading a string (like "Barack Obama") and put it in a variable:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
scanf("%s", name);
printf("Your Name is: %s", name);
return 0;
}
Output:
Enter your name: Barack Obama
Your Name is: Barack
How can I make the program read the whole name?
Use:
fgets (name, 100, stdin);
100 is the max length of the buffer. You should adjust it as per your need.
Use:
scanf ("%[^\n]%*c", name);
The [] is the scanset character. [^\n] tells that while the input is not a newline ('\n') take input. Then with the %*c it reads the newline character from the input buffer (which is not read), and the * indicates that this read in input is discarded (assignment suppression), as you do not need it, and this newline in the buffer does not create any problem for next inputs that you might take.
Read here about the scanset and the assignment suppression operators.
Note you can also use gets but ....
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.
Try this:
scanf("%[^\n]s",name);
\n just sets the delimiter for the scanned string.
Here is an example of how you can get input containing spaces by using the fgets function.
#include <stdio.h>
int main()
{
char name[100];
printf("Enter your name: ");
fgets(name, 100, stdin);
printf("Your Name is: %s", name);
return 0;
}
scanf(" %[^\t\n]s",&str);
str is the variable in which you are getting the string from.
The correct answer is this:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
// pay attention to the space in front of the %
//that do all the trick
scanf(" %[^\n]s", name);
printf("Your Name is: %s", name);
return 0;
}
That space in front of % is very important, because if you have in your program another few scanf let's say you have 1 scanf of an integer value and another scanf with a double value... when you reach the scanf for your char (string name) that command will be skipped and you can't enter value for it... but if you put that space in front of % will be ok everything and not skip nothing.
NOTE: When using fgets(), the last character in the array will be '\n' at times when you use fgets() for small inputs in CLI (command line interpreter) , as you end the string with 'Enter'. So when you print the string the compiler will always go to the next line when printing the string. If you want the input string to have null terminated string like behavior, use this simple hack.
#include<stdio.h>
int main()
{
int i,size;
char a[100];
fgets(a,100,stdin);;
size = strlen(a);
a[size-1]='\0';
return 0;
}
Update: Updated with help from other users.
#include <stdio.h>
// read a line into str, return length
int read_line(char str[]) {
int c, i=0;
c = getchar();
while (c != '\n' && c != EOF) {
str[i] = c;
c = getchar();
i++;
}
str[i] = '\0';
return i;
}
Using this code you can take input till pressing enter of your keyboard.
char ch[100];
int i;
for (i = 0; ch[i] != '\n'; i++)
{
scanf("%c ", &ch[i]);
}
While the above mentioned methods do work, but each one has it's own kind of problems.
You can use getline() or getdelim(), if you are using posix supported platform.
If you are using windows and minigw as your compiler, then it should be available.
getline() is defined as :
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
In order to take input, first you need to create a pointer to char type.
#include <stdio.h>
#include<stdlib.h>
// s is a pointer to char type.
char *s;
// size is of size_t type, this number varies based on your guess of
// how long the input is, even if the number is small, it isn't going
// to be a problem
size_t size = 10;
int main(){
// allocate s with the necessary memory needed, +1 is added
// as its input also contains, /n character at the end.
s = (char *)malloc(size+1);
getline(&s,&size,stdin);
printf("%s",s);
return 0;
}
Sample Input:Hello world to the world!
Output:Hello world to the world!\n
One thing to notice here is, even though allocated memory for s is 11 bytes,
where as input size is 26 bytes, getline reallocates s using realloc().
So it doesn't matter how long your input is.
size is updated with no.of bytes read, as per above sample input size will be 27.
getline() also considers \n as input.So your 's' will hold '\n' at the end.
There is also more generic version of getline(), which is getdelim(), which takes one more extra argument, that is delimiter.
getdelim() is defined as:
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
Linux man page
If you need to read more than one line, need to clear buffer. Example:
int n;
scanf("%d", &n);
char str[1001];
char temp;
scanf("%c",&temp); // temp statement to clear buffer
scanf("%[^\n]",str);
"%s" will read the input until whitespace is reached.
gets might be a good place to start if you want to read a line (i.e. all characters including whitespace until a newline character is reached).
"Barack Obama" has a space between 'Barack' and 'Obama'. To accommodate that, use this code;
#include <stdio.h>
int main()
{
printf("Enter your name\n");
char a[80];
gets(a);
printf("Your name is %s\n", a);
return 0;
}
scanf("%s",name);
use & with scanf input

Resources