Whenever I compile this I get that error, and I am not sure why. I am copying this straight out of a book. Can anyone help?
#include <stdio.h>
#include <string.h>
int main(void) {
char buffer[256];
printf("Enter your name and press enter:\n");
fgets(buffer);
printf("Your name has %d characters and spaces!", strlen(buffer));
return 0;
}
Use fgets() because the gets() function is a common source of buffer overflow vulnerabilities and should never be used.
char *fgets(char *str, int n, FILE *stream)
str -- This is the pointer to an array of chars where the string read
is stored.
n -- This is the maximum number of characters to be read (including
the final null-character). Usually, the length of the array passed as
str is used.
stream -- This is the pointer to a FILE object that identifies the
stream where characters are read from.
fgets takes three parameters. Did they mean gets perhaps?
The book's code fgets(buffer); does not match any C compiler using standard libraries. Code corrected below.
#include <stdio.h>
#include <string.h>
int main(void) {
char buffer[256];
printf("Enter your name and press enter:\n");
// fgets(buffer);
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
// Remove potential \n
buffer[strcspn(buffer, "\n")] = 0;
// printf("Your name has %d ...
printf("Your name has %zu characters and spaces!\n", strlen(buffer));
}
return 0;
}
fgets() takes 3 parameters: buffer, size, stream.
char *fgets(char * restrict s, int n, FILE * restrict stream);
Always check return value with I/O functions.
Remove potential '\n' as printf(..."characters and spaces" ...) reports as if \n was not there.
strlen() return type size_t. To print, use specifier "%zu".
Related
My code:
#include <stdio.h>
int main() {
char words[30];
printf("Please typing text under 30 text!:");
scanf_s("%s", words);
printf("text: %s \n", words);
return 0;
}
The error I get:
Missing integer argument to 'scanf_s' that corresponds to coversion
specifier '2', 'scanf_s' not enough arguments passed for format string
Consider using fgets instead if you're simply reading everything into a string buffer. It's simpler and more portable:
char buffer[31]; // 1 extra for the zero terminator
printf("Please enter text with less than %zu characters\n", sizeof(buffer) - 1);
if (!fgets(buffer, (int)sizeof(buffer), stdin)) {
puts("Failed to read input");
} else {
// use input
}
As you can see in the scanf_s documentation:
specifiers each expect two arguments (the usual pointer and a value of
type rsize_t indicating the size of the receiving array, which may be
1 when reading with a %c into a single char)
I.e. for each argument you want scanf_s to parse, you need to pass its size.
Also scanf family return the number of arguments parsed, and you should check it to find out if it actually succeeded.
In your case change the scanf_s line to:
int n = scanf_s("%s", words, sizeof(words));
if (n != 1)
{
// handle error
}
Note that sizeof(words) works here because it is an array allocated on the stack. If you allocate it as a pointer with malloc family you'll need to pass the right size (because then sizeof will return the size of the pointer itself).
Try this code:
#include <stdio.h>
int main() {
char words[30];
printf("Please typing text under 30 text!:");
scanf_s("%s", words,30);
printf("text: %s \n", words);
return 0;
}
Also, you could put sizeof(words) instead of 30 as someone suggested (note that this is only possible if you are working with static memory).
If you are using scanf_s, I think you want to ensure to read n symbols.
Someone already suggested you to use fgets. Another possible solution is to use memcpy (you will read the exact bytes):
#include <stdio.h>
int main() {
char words[30];
char words2[30];
printf("Please typing text under 30 text!:");
scanf("%s", words);
memcpy(words2,words,sizeof(char)*30);
words2[sizeof(char)*30]='\0';
printf("text: %s \n", words2);
return 0;
}
I want one message to appear if the name Emily or Jack is entered and a different message for another input.
My code:
#include <stdio.h>
#include <string.h>
int main()
{
char name;
printf("What is your name?");
gets(name);
if ((strcmp(name,"Emily") == 0) || (strcmp(name,"Jack") == 0))
{
printf("Hello %s\n", name);
} else
{
printf("Welcome Stranger!\n");
}
return 0;
}
This code will compile but won't output anything.
The first problem is that name can store exactly one char, to store a string of characters you'll need a char array.
The second problem, not causing the faulty behavior but equaly important, is the use of gets. This function was deprecated in C99 and removed from the international standard with C11, and for good reason, it's very dangerous as it can easily overflow the destination buffer, it has no control over the length of the input stream. fgets is regularly used instead.
char name[256]; //array store the name
//...
fgets(name, sizeof name, stdin); //safe, can't overflow the buffer, input size is limited
name[strcspn(name, "\n")] = '\0'; //fgets parses the newline character, it must be removed
//...
I'm trying to write a program that i have to enter a word from the keyboard and then it will check how much times appears in a text file using the strcmp() function. here is my code. i can write the word but when i enter the enter button the program stops. anyone can help me to figured out whats going wrong?
#include "stdafx.h"
#include <string.h>
#include <stdio.h>
int main()
{
char input[20];
char string[20];
int num = 0;
FILE *text;
printf("Enter a word:\n");
scanf_s("%s\n", &input);
fopen_s(&text, "C:\\Users\\USER\\Documents\\Visual Studio 2015\\Projects\\ConsoleApplication8\\text.txt", "r");
if (text == NULL) {
printf("Failed to open file\n");
return (-1);
}
while (!feof(text))
{
fscanf_s(text, "%s", string);
if (!strcmp(string, input));
num++;
}
printf("we found the word %d times\n", num);
return 0;
}`
[From this "C:\\Users\\USER\\Documents\\Visual Studio 2015\\ ... I concluded the compiler in use is MS-VC]
Besides the wrong use of feof() as pointed out by MarianD in this answer, there is the following fatal mistake:
This line misses the size of the buffer to scan into:
fscanf_s(text, "%s", string);
It should be
fscanf_s(text, "%s", string, (unsigned) sizeof string);
Same plus 1 issue here:
scanf_s("%s\n", &input)
Pass input, not its address. %s expects a char* (to which input decays). Doing &input would in fact pass the same value, but use the wrong type, namely char(*)[20], which would invoke UB.
Pass its size:
scanf_s("%s\n", input, (unsigned) sizeof input)
From fscanf_s documentation:
The main difference between the more secure functions (that have the _s suffix) and the other versions is that the more secure functions require the size in characters of each c, C, s, S, and [ type field to be passed as an argument immediately following the variable.
[...]
The size parameter is of type unsigned, not size_t.
change
scanf_s("%s\n", &input);
by
scanf_s("%s\n", input);
Indeed input is already a char* and you are sending a char (*)[20].
I'm learning C from a textbook but cannot see why this does not compile. Code::Blocks states there is too few arguments at 'fgets'. I am assuming 'buffer' is storing keyboard input to volatile memory & fgets should be waiting for arguments from input & Enter.
Any help &/or explanation much appreciated if possible! Thanks
/*ex02-05.c*/
#include <stdio.h>
#include <string.h>
int main(void)
{
char buffer[256];
printf("Enter your name and press Enter:\n");
fgets(buffer);
printf("\nYour name has %d characters and spaces",
strlen(buffer));
return 0;
}
fgets() takes 3 arguments. This is the prototype:
char *fgets(char *s, int size, FILE *stream);
So change
fgets(buffer);
to
fgets(buffer, sizeof buffer, stdin);
Also, note that fgets() will read the newline character if the buffer has enough space. If this is something you don't want, then you can strip it with:
buffer[strcspn(buffer, "\n")] = 0;
As suggested by #Sebastian, you can also use #define the size:
#define SIZE 256
int main(void)
{
...
fgets(buffer, SIZE, stdin);
}
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