I'm writing a program to find the location of a certain character in a string using strchr. When using fgets to input the string from the user, the program does not execute properly.
However when using gets everything works fine.
Code that works using gets():
#include <stdio.h>
#include <string.h>
int main() {
char let;
char input[50];
char *ptr;
printf("what is the string that you would like to check?\n");
gets(input);
printf("what is the character that you would like to find?\n");
let = getchar();
printf("in string \"%s\"...\n", input);
ptr = strchr(input, let);
while (ptr != NULL) {
printf("the letter %c was found at character %d\n", let, ptr - input + 1);
ptr = strchr(ptr + 1, let);
}
return 0;
}
Output:
what is the string that you would like to check?
what is the character that you would like to find?
in string "why is the world when wondering"...
the letter w was found at character 1
the letter w was found at character 12
the letter w was found at character 18
the letter w was found at character 23
Code that does not work usgin fgets():
#include <stdio.h>
#include <string.h>
int main() {
char let;
char input[50];
char *ptr;
printf("what is the string that you would like to check?\n");
fgets(input, 16, stdin);
printf("what is the character that you would like to find?\n");
let = getchar();
printf("in string \"%s\"...\n", input);
ptr = strchr(input, let);
while (ptr != NULL) {
printf("the character is found at %d \n", ptr - input + 1);
ptr = strchr(ptr + 1, let);
}
return 0;
}
Output:
what is the string that you would like to check?
what is the character that you would like to find?
in string "abcdefghijklmno"...
Change
fgets(input, 16, stdin)
to
fgets(input, sizeof(input), stdin)
When you pass an argument of 16 to fgets() you are instructing it to read no more than 15 characters. Why?
From the fgets() manpage:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.
If you provide more than size -1 characters, the remaining characters are left in the input buffer.
Then when the program subsequently calls
let = getchar();
let is assigned whatever the next character in the input buffer is - without even waiting for you to type anything else. It then searches for this character in the string you provided - but in the example you provided doesn't find it.
In the first code snippet the call
gets (input);
does not restrict the number of characters the user can input. Take into account that the function gets is not supported by the C Standard and is unsafe.
In the second code snippet you declared the variable input as
char input[50];
So it is more natural to call fgets the following way
fgets (input,sizeof( input ),stdin );
instead of
fgets (input,16,stdin);
The standard function getchar reads any character including white spaces.
So instead it it is much better to use
scanf( " %c", &let );
Otherwise getchar can read any character (including for example the new line character) leaved in the input buffer. While the call of scanf will skip any white space character.
Related
I was trying to input a string of characters and only output the last and the first character respectively. Below is the code I'm using.
#include<stdio.h>
int main(){
for(int i=0;i<3;i++){
int n; // length of the string
char string[101];
scanf("%d %s", &n, &string);
fflush(stdin); // sometimes I also use getchar();
printf("%c%c", string[n+1], string[0]);
}
printf("\n");
return 0;
}
I'm using for loop because i wanted to input the string 3 times, but when I ran the code the input isn't what I expected. If I input e.g.
5 abcde
output
a //there's space before the a
can you help me tell where I've gone wrong?
input:
5 abcde
6 qwerty
3 ijk
excpeted output:
ea
yq
ki
Few problems in your code:
In this statement
scanf("%d %s", &n, &string);
you don't need to give & operator with string. An array name, when used in an expression, converts to pointer to first element (there are few exceptions to this rule). Also, the size of string array is 101 characters but if you provide input more than 101 characters, the scanf() end up accessing string array beyond its size. You should restrict the scanf() to not to read more than 100 characters in string array when input size is more than that. (keep the remain one character space is for null terminating character that scanf() adds). For this, you can provide width modifier in the format specifier - %100s.
You are not validating the string length input against the input string from user. What happen, if the input string length is greater than or less than the actual length of input string!
fflush(stdin) is undefined behaviour because, as per standard, fflush can only be used with output streams.
I was trying to input a string of characters and only output the last and the first character respectively.
For this, you don't need to take the length of the string as input from user. Use standard library function - strlen(). This will also prevent your program from the problems that can occur due to erroneous length input from user, if that is not validated properly.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main (void) {
for (int i = 0; i < 3 ; i++) {
char string[101];
printf ("Enter string:\n");
scanf("%100s", string);
printf("Last character: %c, First character: %c\n", string[strlen(string) - 1], string[0]);
int c;
/*discard the extra characters, if any*/
/*For e.g. if user input is very long this will discard the input beyond 100 characters */
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
return 0;
}
Note that, scanf(%<width>s, ......) reads up to width or until the first whitespace character, whichever appears first. If you want to include the spaces in input, you can use the appropriate conversion specifier in scanf() or a better alternative is to use fgets() for input from user.
Line 11: string[n+1] -> string[n-1]
Having a doubt regarding a very simple C code. I wrote a code to calculate the length of a string without using the strlen function. The code below works correctly if i enter a string with no spaces in between. But if i enter a string like "My name is ---", the length shown is the length of the word before the first white space, which in the example, would be 2. Why is that? Aren't white space and null character two different characters? Please guide me as to how i can change the code so that the entire string length is returned?
char s[1000];
int length = 0;
printf ("Enter string : ");
scanf ("%s", s);
for (int i = 0; s[i] != '\0'; i++)
{
length++;
}
printf ("Length of given string : %d", length);
It is because scanf with %s reads until it finds white space.
from man scanf
Matches a sequence of non-white-space characters; the next pointer
must be a pointer to character array that is long enough to hold the
input sequence and the terminating null byte ('\0'), which is added
automatically. The input string stops at white space or at the maximum
field width, whichever occurs first.
If you want read until \n including white space you can do as below.
scanf("%999[^\n]", s);
Or you could use fgets.
scanf reads the data until "\0" or "\20". So use "fgets" method which reads the data until "\n" (next line) with "stdin",
Example Program:
#include <stdio.h>
int main() {
char s[100];
printf("Input String: ");
fgets(s, sizeof(s), stdin);
printf("\nLength of the string is = %d", printf("%s"), s);
return 0;
}
In C Programming, how do I store user input in a variable so that I can get a substring from it?
When typing in "hello Point" in the console I get an error: The substring is NULL. This means my word variable is empty? What exactly did I do wrong and why?
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
printf ("Enter a word: ");
scanf ("%s", word);
const char needle[] = "Point";
char *ret;
ret = strstr(word, needle);
printf("The substring is: %s\n", ret);
return(0);
}
%s for scanf() stops reading when it found a whitespace.
Try using scanf ("%99[^\n]", word); instead. (added 99 to avoid buffer overrun)
strstr returns NULL if the substring is not found. This is the case here. You are using scanf to read string. It will stop scanning after first occurrence of a white space, an ' ' here. Therefore, only hello will be stored in word and strstr(word, needle) will return NULL.
Use fgets instead to read string.
fgets(word, sizeof(word), stdin);
I'm working through an example of using the strstr() function.
If I input "Pamela Sue Smith", why does the program output ""Pamela" is a sub-string!" and not ""Pamela Sue Smith" is a sub-string!".
#include <stdio.h>
#include <string.h>
void main(void)
{
char str[72];
char target[] = "Pamela Sue Smith";
printf("Enter your string: ");
scanf("%s", str);
if (strstr( target, str) != NULL )
printf(" %s is a sub-string!\n", str);
}
main does not have return-type void but int.
scanf can fail. Check the return-value.
If successful, it returns the number of parameters assigned.
%s only reads non-whitespace, until the next whitespace (thus 1 word).
%s does not limit how many non-whitespace characters are read. A buffer-overflow can be deadly.
Use %71s (buffer-size: string-length + 1 for the terminator)
You swapped the arguments to strstr.
From the manual page for scanf:
“s” — Matches a sequence of non-white-space characters; the next
pointer must be a pointer to character array that is long enough
to hold the input sequence and the terminating null byte ('\0'),
which is added automatically. The input string stops at white
space or at the maximum field width, whichever occurs first.
So, the part “Sue Smith” never makes it to str. You could use fgets which allows you to read a whole line at a time:
if (fgets(str, sizeof str, stdin) == NULL) {
printf("End of file\n");
return;
}
Note that in this case, str contains the terminating end-of-line character. You could do
if (*str != '\0')
str[strlen(str) - 1] = '\0';
to remove it.
(Also, as some others already pointed out, the “haystack” argument to strstr goes first.)
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