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;
}
Related
I wrote the below code but I keep getting a "Command terminated by signal 11".
#include<stdio.h>
int main()
{
char *goodnight_message[20];
printf ("Enter the goodnight message.\n");
scanf ("%s", &goodnight_message);
printf ("%s Buddy.\n", *goodnight_message);
return 0;
}
I suspect that you want one char array with 20 chars, not an array of 20 char* which is what you've got now.
Note that when passing arrays to functions, like scanf and printf, they decay into pointers to the first element. Also note that when using scanf to read strings, always set a maximum number of characters to read (one less than the size of the array to leave room for the null terminator). Otherwise the user may enter more characters and your program will write out of bounds.
You should also always check if scanf is successful by checking if it returns the same number of conversions you requested. You request one only, so check if it returns 1.
A working program would then look like this:
#include <stdio.h>
int main() {
char goodnight_message[20]; // now a char[] instead
printf("Enter the goodnight message.\n");
if(scanf("%19s", goodnight_message) == 1) { // decays into a char*
printf("%s Buddy.\n", goodnight_message); // decays into a char*
}
}
This will however not read more than one word. To make scanf read until a newline you can add a set of characters to match in the conversion specifier with [characters].
If the first character of the set is ^, then all characters not in the set are matched.
We want all characters except \n so lets add the set [^\n]
#include <stdio.h>
int main() {
char goodnight_message[20];
// an alternative to printf when you don't need formatting is puts:
puts("Enter the goodnight message.");
if(scanf("%19[^\n]", goodnight_message) == 1) {
printf("%s Buddy.\n", goodnight_message);
}
}
There seems like you have a misconception of array and pointers..
While using array-like goodnight_message[20];
The correct way to address its address is to use &goodnight_message[0] indicating the beginning of the array or to use goodnight_message simply. Both of these point to the 0th index of the array..
#include<stdio.h>
int main()
{
char *goodnight_message[20];
printf ("Enter the goodnight message.\n");
scanf ("%s", goodnight_message);
printf ("%s Buddy.\n", goodnight_message);
return 0;
}
Tip: You should use gets(goodnight_message) instead of scanf when you want a string that includes a space. You can also do this by using scanf("%[^\n]s",goodnight_message);, like this:
#include<stdio.h>
int main()
{
char *goodnight_message[20];
printf ("Enter the goodnight message.\n");
scanf ("%[^\n]s", goodnight_message);
printf ("%s Buddy.\n", goodnight_message);
return 0;
}
line char *goodnight_message[20]; creates an array of strings (array of char pointers)
to create single string use char *goodnight_message; or char goodnight_message[20];
warning: if you use char *goodnight_message;, you have to malloc it, so just stick to [20] for now
scanf ("%s" reads one string from input, but note that it is only to the next whitespace
for example, input good night would read only good and output good buddy
to read whole line use gets(goodnight_message) or getline
warning: getline is a bit complicated (explanation)
How to get rid of buffer overflow on taking input from user? By using fgets or scanf? If fgets then how it prevents. Some explanation required as a beginner.
#include <stdio.h>
#include <stdlib.h>
int main(){
char choice[5];
char one='1', two='2', three='3';
printf("%c. Create new account\n",one);
printf("%c. Update information of existing account\n",two);
printf("%c. For transactions\n",three);
printf("Enter your choice: ");
// fgets(choice, sizeof choice, stdin); // This OR
// fgets(choice, 3, stdin); // This one
scanf("%s",choice); // This one
printf("Here is your choice: %s", choice);
return 0;
}
A well-written program reports invalid input with a comprehensible error message, not with a crash.
Fortunately, it is possible to avoid scanf buffer overflow by either specifying a field width or using the a flag.
When you specify a field width, you need to provide a buffer (using malloc or a similar function) of type char *.You need to make sure that the field width you specify does not exceed the number of bytes allocated to your buffer.
On the other hand, you do not need to allocate a buffer if you specify the a flag character -- scanf will do it for you. Simply pass scanf an pointer to an unallocated variable of type char *, and scanf will allocate however large a buffer the string requires, and return the result in your argument. This is a GNU-only extension to scanf functionality.
Here is a code example that shows first how to safely read a string of fixed maximum length by allocating a buffer and specifying a field width, then how to safely read a string of any length by using the a flag.
int main()
{
int bytes_read;
int nbytes = 100;
char *string1, *string2;
string1 = (char *) malloc (25);
puts ("Please enter a string of 20 characters or fewer.");
scanf ("%20s", string1);
printf ("\nYou typed the following string:\n%s\n\n", string1);
puts ("Now enter a string of any length.");
scanf ("%as", &string2);
printf ("\nYou typed the following string:\n%s\n", string2);
return 0;
}
There are a couple of things to notice about this example program. First, notice that the second argument passed to the first scanf call is string1, not &string1. The scanf function requires pointers as the arguments corresponding to its conversions, but a string variable is already a pointer (of type char *), so you do not need the extra layer of indirection here. However, you do need it for the second call to scanf. We passed it an argument of &string2 rather than string2, because we are using the a flag, which allocates a string variable big enough to contain the characters it read, then returns a pointer to it.
I'm trying to scanf an integer to see if it's legal in my program. However, if I input a number followed by a char it still treats it as legal number (my guess is that it only refers to the integer while saving the char in the buffer). Assume I can only use scanf and not something else (since that's what we've leraned). Also, if I input only a char it automatically casts it to an integer. This is what I have tried so far, with the help of what I saw here -
int number_of_numbers;
char number='\n';
printf("Enter size of input:");
if (scanf("%d%c",&number_of_numbers, &number)>=1 && number!='\n')
{
printf("Invalid size");
return 0;
}
How can I identify when I scanf only an integer or an integer followed by a char or just a char?
Thanks!
If you enter "only a character" it does not "automatically cast it to an integer". It does not accept any input at all, as shown by scanf returning 0, but that situation escapes your test.
But the answer to your question is: with difficulty when using scanf.
Here is a way to do it getting the input with fgets. It will tolerate any amount of whitespace before or after the number, but not any letters.
The reason for the space before %c is to instruct it to filter any leading whitespace. This is automatic anyway for %d, but not for %c. Then if there are no readable characters, nothing will be read into extra. If there is at least one character (apart from whitespace) then the sscanf conversion count will be incorrect.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int number_of_numbers = 0;
while(number_of_numbers >= 0) {
bool success = false;
char str[100];
if(fgets(str, sizeof str, stdin) != NULL) {
char extra;
if(sscanf(str, "%d %c", &number_of_numbers, &extra) == 1) {
success = true;
}
}
if(success) {
printf("Success: %d\n\n", number_of_numbers);
} else {
printf("Invalid size\n\n");
}
}
return 0;
}
Program session:
123
Success: 123
123a
Invalid size
123 a
Invalid size
123 9
Invalid size
a
Invalid size
-1
Success: -1
The reasons for using fgets are
it doesn't "stall" if there is invalid input: it has already been read.
if there is a mistake, the string can easily be dumped and another one requested.
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].
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