Now i read somehwere:
The scanf() conversion %[\n] will
match a newline character, while
%[^\n] will match all characters up to
a newline.
But in the following code:
#include<stdio.h>
int main() {
printf("Enter Something: ");
char name[100];
scanf("%99[help]", name);
printf("%s",name);
}
I face no problem when i enter help me as the printed word is help. However when i enter I need help it prints garbage. Please help how to fix this problem?
My target is to match the word help entered anywhere along the input, e.g.,
"This is a test, i need help in this"
Should detect help.
You need to check the result of scanf. If it fails to match, the pointer you pass in is not modified. In your specific case, name would then contain arbitrary data.
Once you check the output of scanf, you'll see it's failing to match on that string. scanf is not a regular expression parser. It will only attempt a match on the first "item" it sees on the input stream.
The match specifier %99[help] means "i want to match anything that contains the letters h, e, l, p in any order, up to 99 chars long". That's all. So it fails on the very first letter of your input ("T"), which is not in the set.
If you want to look for a string inside another string, use strstr for example. To read a whole line, if your environment has it, the easiest is to use getline.
You need the scanset to recognize all the characters you might enter. You also need to check the return from scanf() to see whether it succeeded.
#include <stdio.h>
int main()
{
printf("Enter Something: ");
char name[100];
if (scanf("%99[Indhelp ]", name) != 1)
fprintf(stderr, "scanf() failed\n");
else
printf("%s",name);
return 0;
}
That will recognize "I need help" and many other phrases. The C standard says:
If a - character is in the scanlist and is not the first, nor the
second where the first character is a ^, nor the last character, the behavior is
implementation-defined.
In many implementations, you can use a notation such as %[a-zA-Z ] to pick up a string of letters or spaces. However, that is implementation-defined behaviour. That means it could do anything the implementation chooses, but the implementation must document what it does mean.
The reliable way to write the scanset is:
%[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ]
Of course, that leaves you with some issues around punctuation, not to mention accented characters; you can add both to the scanset if you wish.
Related
In the following simple code the input of the first gets is not showing up.
Any help please?
int main()
{
int x;
char tmp[1];
char anystr[10], srchstr[1];
printf("Enter an string : ");
gets(anystr);
printf("Enter any character you want to search in input string: ");
gets(srchstr);
printf("anystr : %s\n",anystr);
printf("anystr : %c\n",anystr[0]);
printf("srchstr : %c\n",srchstr[0]);
return 0;
}
The Output is null for first fgets string anystr:
Enter an string : hello
Enter any character you want to search in input string: h
anystr :
anystr :
srchstr : h
You have a problem because you have undefined behaviour.
The UB is caused by having second gets() write beyond the 1-char array srchstr. What is written beyond is the terminator '\0'.
See the gets() docu: http://en.cppreference.com/w/c/io/gets
No answer to this question should omit to mention (using Jonathan Lefflers nice link):
Why is the gets function so dangerous that it should not be used?
That is it. UB and dangerous. Done. End of answer.
Well....
One speculation of which specific nasal demon is flying around would be:
strchr is located right before anystr. This means that the one beyond access hits right the first char inside anystr.
I.e. it terminates that other string right after zero characters.
I.e. it makes it empty.
Printing it therefor has no output, even though the second character is still from the perviously written string.
Don't use gets() as pointed here in man 3 fges
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.
Use fgets() like
fgets(anystr,sizeof(anystr),stdin);
Also char srchstr[1]; should be char srchstr; as you are asking in printf Enter any character you want to search in input string:
And to scan srchstr use scanf(" %c",&srchstr);
you may want something like
int main(void ) {
char anystr[10],srchstr;
printf("Enter an string : ");
fgets(anystr,sizeof(anystr),stdin);/*use fgets instead of gets */
printf("Enter any character you want to search in input string: ");
scanf(" %c",&srchstr);/* give the space before %c to avoid buffering problem */
printf("anystr : %s\n",anystr);
printf("anystr : %c\n",anystr[0]);
printf("srchstr : %c\n",srchstr);
return 0;
}
My code looks like this:
int nameFull;
printf("What is your name?\n");
scanf("%d\n", &nameFull); \\up until here it seems to work
printf("Hello %d", nameFull);
return 0;
But my output every time I run the program is "Hello 0" no matter what I input.
Does anyone know how to fix this?
First of all scanf() doesn't emit a prompt so its not a good idea to use any trailing whitespace character in the format string like \n here , It will cause it to read and discard character until next non-whitespace character.
To read a name you can do it like :
char name[50];
scanf("%49s",name); // 49 to limit the buffer input to prevent buffer overrun , this is a security issue.
You should also check the return value of scanf to see if the operation was successful. Personally , I don't prefer using scanf() at all because of various potential problems. It takes as input only what the program author expects it to, not considering other inputs which user might accidentally input. Check out here and here. Also check the scanf() man page
A better and safer method would be use fgets(),
fgets(name,sizeof(name),stdin);
You want to read a string, but you are an integer to store the input. That's not the right approach.
A better aproach would be to use an array of characters, to store the string in it.
char nameFull[100]; // can store up to 100 characters, 99 + 1 for the null-terminator ideally
Now, you could use scanf, like this:
scanf(" %99[^\n]", nameFull);
Note that I used 99, as a guard for not overflowing your array nameFull, if the user inputs too many characters for the size of your array. I didn't use %s, which would stop at a whitespace, and you seem to want to input a full name, which is usually two words and a space in between.
An alternative would be to use fgets(), which provides more safety, like this:
fgets(nameFull, sizeof(nameFull), stdin)
It will read the whole line though and store the trailing newline, while scanf() will read a single string.
Moreover, use the string identifier to print, not the integer one (%s is for string, %d is for integers). Like this:
printf("Hello %d", nameFull);
to this:
printf("Hello %s", nameFull);
as discussed about the string format.
%s reads a string of characters.
%d reads a integer.
So, your correct code will be like following code :
#include <stdio.h>
int main(){
char nameFull[100];
printf("What is your name?\n");
scanf("%99s", nameFull); //to avoid potential buffer overflow
printf("Hello %s\n", nameFull);
return 0;
}
N.B: Check this comment for nice explanation.
Well, int stores a number, a name is not a number. A name is a set of characters (aka strings). So this program would work (no error checking and such since you are in an introductory course):
char name[1024]; // 1024 is more than enough space for a name
scanf("%s", name); // %s reads a string of characters
printf("Hello %s\n", name);
return 0;
You are trying to assign an array of character (commonly referred as string) to an integer variable.
That's not correct.
Just change your variable as such
char nameFull[1024] = {0};
And then use scanf(3) with the appropriate format specifiers for strings, which is %s
scanf("%s", nameFull);
Normally you would check for the return of scanf to know if errors occurs, and in such cases, handle them.
Anyway, I would advice you to use fgets(3) which prevents buffer overflow
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (aq\0aq) is stored after the last character in the buffer.
I'm new in programming and learning basics of C programming. I'm learning about how scanf() works but I think now I'm very much confused and really don't know how and what to ask. But I will try my best to put my question clear.
Questions
I'm really not able to understand the whole concept of whitespace. I mean when they are skip by the scanf and when they are not and biggest question: How they are skipped?
Along with the whitespace concept I'm not able to understand the working of scanf function also? I had read about it in many books and websites and also in this site but it confuse me more since each person has their own way of telling any concept and it vary from one to another.
Have a look at this short program:
#include<stdio.h>
int main()
{
int num;
char ch;
printf("enter the value of num and ch:\n");
scanf("%d",&num);
scanf("%c",&ch);
printf("num = %d and ch = %c",num,ch);
return 0;
}
I know that in this program user will be allowed to enter the value of num only, because of the new line character that stays back in the input buffer and next time scanf will input that new line character but can be solved if we add extra space before %c in the second scanf function.
But when I replace the char ch variable with int ch, scanf skips the new line. Why?
Why scanf do not skip non-white space character just like whitespace For example - a, b, c, d, #) # etc?
What is the difference between space and newline character in scanf? I mean there will some exceptions right?
First Question
I mean when they are skip by the scanf and when they are not
White-space characters are skipped unless the format specifier is %c, %n or %[. Relevant quote from the C11 standard:
7.21.6.2 The fscanf function
[...]
Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. 284)
How they are skipped?
Just read and discard them.
Second Question
I'm not able to understand the working of scanf function also?
scanf is a variadic function meaning that it can take any number of arguments with a minimum of one. scanf parses the first argument which is a string literal and accordingly, takes input.
Third Question
But when I replace the char ch variable with int ch, scanf skips the new line. Why?
First part of the first answer explains it. %d will skip whitespace characters.
Fourth Question
Why scanf do not skip non-white space character just like whitespace?
For some conversion specifiers like %c, non-whitespace characters are valid inputs. It doesn't make sense why they should skip them. For other like %d, characters ( not numbers ) are invalid inputs. scanf stops scanning and returns when it sees invalid input. It is designed this way.
Fifth Question
What is the difference between space and newline character in scanf?
There is no difference when any of them are placed in the format string in scanf. Both of them are considered as whitespace characters, although they are different characters. They skip any number of whitespace characters, including none, until the first non-whitespace character when they are used in the format string of scanf. Relevant quote from the C11 standard:
7.21.6.2 The fscanf function
[...]
A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.
Problem statement
Roy wanted to increase his typing speed for programming contests. So, his friend advised him to type the sentence "The quick brown fox jumps over the lazy dog" repeatedly, because it is a pangram. (Pangrams are sentences constructed by using every letter of the alphabet at least once.)
After typing the sentence several times, Roy became bored with it. So he started to look for other pangrams.
Given a sentence s, tell Roy if it is a pangram or not.
Input Format Input consists of a line containing s.
Constraints
Length of s can be at most 103 (1≤|s|≤103) and it may contain spaces, lower case and upper case letters. Lower case and upper case instances of a letter are considered the same.
Output Format Output a line containing pangram if s is a pangram, otherwise output not pangram.
void panagram(char s[])
{
int num1[26]={0};
int num2[26]={0};
int len=strlen(s);
int count=0,j,i;
for(i=0;i<len;i++)
{
if(s[i]>=97&&s[i]<=122)
{
num1[s[i]-97]++;
}
if(s[i]>=65&&s[i]<=90)
{
num2[s[i]-65]++;
}
}
for(j=0;j<26;j++)
{
if(num1[j]>=1||num2[j]>=1)
{ printf("%d\t\t%d\n",num1[j],num2[j]);
count++;
}
}
printf("%d\t",count);
if(count>=26)
printf("panagram");
else
printf("not panagram");
}
int main() {
char s[1000];
scanf("%s",s);
panagram(s);
return 0;
}
The code works fine for strings without blank spaces like "Wepromptlyjudgedantiqueivorybucklesforthenextprize" but fails to work for strings with blank spaces - "We promptly judged antique ivory buckles for the next prize"
Can anyone tell where I am going wrong?
Am I taking input incorrectly?
As per the C11 standard,
7.21.6.2 The fscanf function
[...]
The conversion specifiers and their meanings are:
[...]
s. Matches a sequence of non-white-space characters. 286
[...]
You have
scanf("%s",s);
to take input. %s will stop scanning the input until it encounters a whitespace character. A space is a whitespace character as per the C11 standard:
6.4 Lexical elements
[...]
[...]
Preprocessing tokens can be separated by white space; this consists of comments (described later), or white-space characters (space, horizontal tab, new-line, vertical tab, and form-feed), or both
[...]
So, when the %s sees the space after the first word, it stops scanning.
Fix the problem by using fgets as shown in #Gopi's answer or if you need to use scanf, use
scanf("%[^\n]",s);
The above scanf reads everything until it encounters a newline character. A better way would be to limit the amount of characters that scanf reads(a maximum of 999 in your case) in order to prevent buffer overflows and also, checking the return value of scanf to see if it was successful(The return value will be 1, in your case, if scanf was successful).
Note: The above fix, unlike fgets, will leave the newline character in the standard input stream(stdin).
Instead of scanf() use
fgets(s,sizeof(s),stdin);
It is never a good idea to use scanf() while reading strings.So I suggest you to use fgets()
PS: fgets() comes with a newline character and suppress the newline character.
So, I want to get 5 string inputs from the user using array of pointers to strings. However, I want those strings to have white spaces and hence, I am using the %[^\n]s which accepts the string till a line break occurs. But, this code doesn't work :/ Can someone please explain why??
P.S-> If you use %s in scanf, the code works. But I want white spaces compulsorily. So, please suggest something.
Thanks in advance!
#include<stdio.h>
#include<malloc.h>
void main()
{
char *f[5];
int i;
printf("\nEnter 5 strings:\n");
for(i=0;i<5;i++)
f[i]=malloc(20);
for(i=0;i<5;i++)
scanf("%[^\n]s",f[i]);
printf("The 5 strings are:\n");
for(i=0;i<5;i++)
{
printf("\n%s",f[i]);
}
}
One major problem is the trailing 's' in your format. If you read e.g. this reference you will see that the "%[" format is terminated by the ']' character. When you have that extra 's' in the format, scanf will wait until it matches a literal 's' in the input.
And to skip the ending newline, you can add a leading whitespace in the format and scanf will automatically read and skip all whitespace (including newline) that you don't want in the next iteration of the loop.
You also should limit the length of the input scanf reads, or you might have scanf read more than you have allocated. The limit should be 19 characters (which with the string terminator is 20, like you have allocated).
So the correct format should be " %19[^\n]".
As a side-note, since you allocate all strings equally, why not simply have an array of arrays? Like
char f[5][20];
And if you still decide to go with the pointers, don't forget to free them when you're done. You don't really need it in such a simple case such as your program, but it's better to get the good habits early.
You just need to 'consume' the '\n' character after you've read what you want. Use the following format directive:
"%[^\n]%*c"
Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').