Why is strtok printing only first word? - c

I am using strtok for converting string into individual words. I have done the following:
int main() {
char target[100];
char *t;
scanf("%s",target);
t = strtok(target," ");
while (t!= NULL)
{
printf("<<%s>>\n", t);
t = strtok (NULL, " ");
}
return 0;
}
The input is a string such as 'this is a string', the output I am getting is<<this>>.

The way you have written scanf it will accept string till white space only
scanf("%s",target);
SO You need to change the way you take input from console
scanf("%99[^\n]",target);

Change:
scanf("%s",target);
to:
fgets(target, 100, stdin);
since the first won't stop when encounters the whitespace in your input.
Output:
this is a string
<<this>>
<<is>>
<<a>>
<<string
>>
Notice how the newline fgets() stores affects the output. You can simply discard it if you want, like this:
fgets(target, 100, stdin);
target[strlen(target) - 1] = '\0';
and now the output is:
this is a string
<<this>>
<<is>>
<<a>>
<<string>>

If you want to continue using scanf(), then you can use the below code snippet:
#include<stdio.h>
#include <string.h>
int main() {
char target[100];
char *t;
//scanf("%s",target);
scanf("%99[0-9a-zA-Z ]", target);
printf("%s\n",target);
t = strtok(target," ");
while (t!= NULL)
{
printf("<<%s>>\n", t);
t = strtok (NULL, " ");
}
return 0;
}
Working code here.
Just writing scanf("%s",target); will read the input only till the first white space; which is why you get only the first word as the output. By writing scanf("%99[0-9a-zA-Z ]", target);, you are reading 99 characters (including numbers 0-9, a-z or A-Z and white space) from the input stream.
Hope this is helpful.

Related

How to parse through a string of STDIN word by word in C

I would like to read standard input of a command and its argument in a C program, for instance:
ATTACK 50 30
I would like my program to parse through the input using whitespace and assign each word to a variable but right now I would just like to print each word. However, when I tried the program only returned ATTACK and not ATTACK 50 30.
I tried:
int main(){
// Grid size declaration //
int *x, *y;
char command[20];
char user_input[100];
scanf("%s", user_input);
printf("%s", user_input);
return 0;
}
As I said I used ATTACK 50 30 as my STDIN but my printf function only returned ATTACK. I thought of maybe using a while loop to keep scanning until the character interpreted is the return key (which I believe in this case would just be the null character?). I tried it using the code below:
int main(){
// Grid size declaration //
int *x, *y;
char command[20];
char user_input[100];
while(scanf("%s", user_input)!="\0"){
scanf("%s", user_input);
printf("%s", user_input);
}
return 0;
}
This did not work, the error produced declared I was comparing a pointer to an integer.
Since you are dealing with stdin it would probably be a better idea to utilize the fgets function in lieu of the scanf function, and then parse the inputted line of data utilizing the strtok string function.
Utilizing that strategy, following is a snippet of code allowing for the parsing of entered text where each word or data group is identified.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 64
int main()
{
char line[MAX + 1];
const char delim[2] = " ";
char * wd;
printf("Enter some text or type \"quit\" to end: ");
while (fgets(line, MAX, stdin))
{
line[strlen(line) - 1] = ' '; /* Replace newline character at the end with a space */
wd = strtok(line, delim);
while (wd != NULL)
{
if (strcmp(wd, "quit") == 0)
{
return 0;
}
printf("%s\n", wd);
wd = strtok(NULL, delim);
}
printf("Enter some text or type \"quit\" to end: ");
}
return 0;
}
Testing out this code utilizing your text example yielded the following terminal output.
#Dev:~/C_Programs/Console/ParseWord/bin/Release$ ./ParseWord
Enter some text or type "quit" to end: ATTACK 50 30
ATTACK
50
30
Enter some text or type "quit" to end: quit
#Dev:~/C_Programs/Console/ParseWord/bin/Release$
This is just a springboard from where you might go, but test that out and see if it meets the spirit of your project.

Input of multiple char arrays isn't working [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 1 year ago.
char toFind[100];
char replace[100];
int pos = 0;
printf("Enter a text: ");
scanf("%[^\n]", str);
printf("Enter a search pattern: ");
scanf("%[^\n]", toFind);
printf("Enter a substitute: ");
scanf("%[^\n]", replace);
pos = strnfnd(0, toFind);
strins(pos, replace);
printf("Der Text ist: %s", str);
This code sample let me read the value for str but skips the other two scanf. I have no idea why.
What can I do to fix this?
Ps: str is a global char array
After this call of scanf
scanf("%[^\n]", str);
the new line character '\n' still is present in the input buffer.
So the next call of scanf
scanf("%[^\n]", toFind);
that reads input until the new line character '\n' is encountered reads nothing.
You should write for example
scanf("%[^\n]%*c", str);
to remove the new line character '\n' from the input buffer.
Here is a demonstration program
#include <stdio.h>
int main( void )
{
char s[100];
scanf( "%99[^\n]%*c", s );
puts( s );
scanf( "%99[^\n]", s );
puts( s );
return 0;
}
In this case if to enter strings for example like
Hello
World
then the output will be
Hello
World
Another and more simple approach is to prepend the format string with a blank. For example
scanf(" %[^\n]", toFind);
^^^^
In this case all leading white space characters will be skipped.
Here is a demonstration program.
#include <stdio.h>
int main( void )
{
char s[100];
scanf( "%99[^\n]", s );
puts( s );
scanf( " %99[^\n]", s );
puts( s );
return 0;
}
In this case if to enter strings as shown above that is
Hello
World
then the program output will be
Hello
World
It depends where you run the compiled code - the operating system. In some cases when the "Enter" key is pressed, two bytes are emitted in the input stream (10 and 13) instead of '\n' (10). In that case you need to flush the extra symbols. Check the comments for the exact implementation.
There are problems with your scanf() usage: scanf("%[^\n]", str);
you do not specify the maximum number of characters to store into str, hence a sufficiently long line typed by the user will cause undefined behavior. This is a typical software flaw hackers can try and exploit. You can prevent this by specifying the limit as scanf("%99[^\n]", str);
you do not read the trailing newline entered by the user, so the next call scanf("%[^\n]", toFind); will fail because no characters different from '\n' are present in the input stream, since the first pending byte is '\n', or EOF.
you do not check the return value of the scanf() calls, so you cannot detect input errors such as the above.
note however that scanf("%99[^\n]", str); will fail if the user types enter immediately and str will not be modified in this case.
It is much safer to use fgets() instead of scanf() for this task:
char str[100];
char toFind[100];
char replace[100];
int pos = 0;
printf("Enter a text: ");
if (!fgets(str, sizeof str, stdin)) {
printf("input error\n");
return 1;
}
str[strcspn(str, "\n")] = '\0'; /* strip the trailing newline if any */
printf("Enter a search pattern: ");
if (!fgets(toFind, sizeof toFind, stdin)) {
printf("input error\n");
return 1;
}
toFind[strcspn(toFind, "\n")] = '\0'; /* strip the trailing newline if any */
printf("Enter a substitute: ");
if (!fgets(replace, sizeof replace, stdin)) {
printf("input error\n");
return 1;
}
replace[strcspn(replace, "\n")] = '\0'; /* strip the trailing newline if any */
pos = strnfnd(0, toFind);
strins(pos, replace);
printf("Der Text ist: %s\n", str);

When I try to input a string that contains spaces it's supposed to go to the error message, it does not do that?

when I try to input a string that contains a semi colon it goes to the error message( please enter a string without any spaces) similarly if I try to enter a string with spaces it still goes to the error message.
what my program should do is if the input does not contain a space run the program else go to the error message.If the input contains a semi colon but no spaces run the program.
printf("Enter a string\n");
scanf("%20s", string_buffer);
stringp1 = string_buffer;
The format specifier %s doesn't read blank spaces at all. Let's take a look at this code snippet:
scanf("%s", string);
puts(string);
Input :
Hello, my name is Claudio
The output will be :
Hello,
To avoid that you should use an inverted group scansion inside of your scanf instruction, just like this one :
scanf("%string_size[^\n]", string);
This will do the trick.
By the way, I would advise you to use other function like getline or fgets to take string from stdin.
Note that scanf will break at spaces. So, if you have this code:
scanf("%20s", string_buffer);
And you enter "hello there" is the input, then the contents of string_buffer will be only "hello".
try this
#include <stdio.h>
#include <string.h>
int main(void){
char string_buffer[20];
char *stringp;
printf("Enter a string\n");
scanf("%19[^\n]", string_buffer);//20 --> 19, include space
stringp = string_buffer;
if (strstr(stringp, " ") == NULL) {//!= --> ==
printf("Converted semicolon to 4 spaces\n");
for (; *stringp; stringp++) {
if (*stringp == ';'){//strsep is not needed
printf(" ");
} else {
printf("%c", *stringp);
}
}
} else {
printf("Please enter a string without any spaces\n");
}
printf("\n");
return 0;
}
scanf("%20s", string_buffer);
Use fgets instead of scanf as %s in scanf matches a sequence of non-white-space characters only.
So if you enter foo bar, it will only accept foo and not the whole string.
if (strstr(&stringp1, " ") != 0)
strstr expects both arguments to be char * and here first argument is char**.
Remove & address of operator.
if (strstr(&stringp1, " ") != 0)
If substring is found then strstr returns char * pointer to substring else it returns NULL.
That means this if expression will be true if there's a white space in the string. And we want an error message to be printed for that. So clearly reverse condition.
Solution: change that if to
if (!strstr(stringp1, " "))
So the correct code snippet would be:
...
printf("Enter a string\n");
fgets(string_buffer, 20, stdin);
stringp1 = string_buffer;
if (!strstr(stringp1, " ")) {
...

Tokenizing a string

I am in the process of writing a C program that parses a string and tokenizing it by breaking the string characters into words that are seperated by white space. My question is when i run my current program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[20];
printf("Please enter your word:\n");
scanf("%c", &input);
printf("%c", input[1]);
return 0;
}
If i was to enter the word "This", i would expect to get back "h" when i run the program but instead i get a downwards pointing arrow. However, when the input is set to print out input[0] i get back a "T".
Edit: I have modified my code so that it prints out the whole string now which i will show below
int main()
{
char input[20];
printf("Please enter your words:\n");
scanf("%s", input);
printf("%s", input);
return 0;
}
My goal is to be able to break that string into chars that i can search through to find whitespace and thus being able to isolate those words for example, if my input was "This is bad" i'd like the code to print out
This
is
bad
Edit:
I have modified my code to fit one of these answers but the problem i run into now is that it won't compile
int main()
{
char input[20];
printf("Please enter your words:\n");
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
}
printf("%c", input[]);
return 0;
Problems:
1) scanf("%c", input); only set the first element of the array input.
2) printf("%c", input[1]); prints the second element of the array input, which has uninitialized data in it.
Solution:
Small state machine. No limit on string size like 20.
#include <ctype.h>
#include <stdio.h>
int main() {
int ch = fgetc(stdin);
while (ch != EOF) {
while (isspace(ch)) {
// If only 1 line of input allowed, then add
if (ch == '\n') return 0;;
ch = fgetc(stdin);
}
if (ch != EOF) {
do {
fputc(ch, stdout);
ch = fgetc(stdin);
} while (ch != EOF && !isspace(ch));
fputc('\n', stdout);
}
}
return 0;
}
scanf("%c", &input); does not do what you think it does.
First of all, %c scans only a single character: http://www.cplusplus.com/reference/cstdio/scanf/
Second, array's name is already a pointer to it's first element, so stating &input you make a pointer to a pointer, so instead of storing your character in array's first element you store it in pointer to the array which is a very bad thing.
If you really want to use scanf, I recommend a loop:
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
Using scanf("%s", input") leaves you vulnerable to buffer overflow attacks if the word is longer than 20 characters http://en.wikipedia.org/wiki/Buffer_overflow
In my example I assumed, that you want to finish your word with a newline character.
EDIT: In scanf documentation is also a good example:
scanf("%19s", input);
It scans no more than 19 characters, which also prevent buffer overflow. But if you want to change input size, you have to change it two places.
You can use
char * strtok ( char * str, const char * delimiters );
to tokenize your string. If you have your input in input[] array and want to tokenize the string accoring to whitespace character, you can do the following :
char *ptr;
ptr = strtok(input, " ");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
Only the first call to strtok() requires the character array as input. Specifying NULL in the next calls means that it will operate on the same character array.
Your scanf only picks up the first character, input[1] contains random garbage. Use scanf("%19s", input) instead.

Below function does not work as desired

I need to write a function which takes 2 words and count its length. I wrote below one but this code only woks for 1st word. How can I improve it to count whole sentence?
#include <stdio.h>
int findlen(int *s);
int main(void)
{
char string1[80];
printf("Enter a string: ");
scanf("%s", string1);
printf("Lenght of %s is %d\n", string1, findlen(string1));
}
//find the length of the inputted string
int findlen(char *s)
{
int count = 0;
while (*s != '\0')
{
s++;
count++;
}
return count;
}
scanf will take the one word input only.. (i.e) it breaks when space appears..
Try fgets to read the complete string till \n
You can use fgets to safely get the line from your file:
From here:
char *fgets(char *s, int size, FILE *stream);
so replace your scanf line with:
fgets(string1, sizeof(string1), stdin);
If you used gets instead, it doesn't know how large your buffer is and it would crash when reading too large line.
Next, if you want to know a length of your string you could use strlen function from string.h:
#include<string.h>
...
printf("Lenght of %s is %d\n", string1, strlen(string1));
use [%^\n] format specifier so that it will scan the string till '\n' encounter so the problem in scanning string having space(eg. "hello word") will be solved.
scanf("[%^\n]",straddr);

Resources