strtok(NULL, ) segmentation fauls - c

Input to a piece of code is:
initfs /home/bin/usr/a.txt 1000 100
The code is as follows:
printf("Enter a command\n");
scanf("%99[0-9a-zA-Z ]s", userInput);
printf("%s\n", userInput);
command = strtok(userInput, " ");
filePath = strtok(NULL, " ");
In userInput, "initfs /home/bin/usr/a.txt 1000 100" is stored and
in the variable command, "initfs" is stored.
But if I print filePath, it is giving segmentation fault.
It should print "/home/bin/usr/a.txt"
What may be the issue?

In general, for parsing input from a keyboard, I find it much less of a headache than to read a full line of text with fgets (or getline, if you like) and then parse it from there. e.g.:
char userInput[1024];
while (fgets(userInput, 1024, stdin) != NULL) {
handleInput(userInput);
}
...
void handleInput(char *userInput)
{
char *command, *filePath;
command = strtok(userInput, " ");
filePath = strtok(NULL, " ");
...
}
Using scanf directly on user input is just too finicky and gets confused on very slight changes in input data too easily.

Related

[C]: Segmentation fault using strcpy() into String Arrays

My assignment is to write a function that takes an input string from a user, tokenize it into several strings each containing an individual word from the input sentence, and then reverses the sentence. The result will be the sentence input but with the words in the reverse order.
For now, I just have the function taking in the input, tokenizing it into individual words, storing those words into an array, and printing out each individual word in order. I do not have the process for reversing the order of the words written yet.
Here is the code for the function i have handling this so far:
void reverse(void){
printf("\n\n%s\n", "Reverse words in String: ");
char input[200];
printf("\n%s", "Enter string\n> ");
scanf("%s", &input);
char reverseSentence[200];
char sentenceParts[20][200];
int wordCount = 0;
char *thisWord = strtok(input, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
while(thisWord != NULL){
thisWord = strtok(NULL, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
}
printf("\n\n");
for(int i = 0; i < wordCount + 1; ++i){
printf("%s%s", sentenceParts[i], " ");
}
}
The problem lies in the while statement:
while(thisWord != NULL){
thisWord = strtok(NULL, " ");
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
}
The program exits with a segmentation fault error at the strcpy statement. I cannot understand for the life of me why it is doing this. It seems like it worked just fine outside of the while loop.
Any thoughts? I've been stuck on this for quite a bit now and can't find too many other resources out there to help.
Updating thisWord with the next token should happen at the end of the loop body. As is, you'll eventually update thisWord with a NULL, and then call strcpy with a NULL. And that is your segfault.
So the loop should look like this:
char *thisWord = strtok(input, " ");
while(thisWord != NULL){
strcpy(sentenceParts[wordCount], thisWord);
wordCount++;
thisWord = strtok(NULL, " ");
}
The other problem (pointed out by #WhozCraig in the comments) is that you are inputting the line using scanf("%s", ...). That doesn't work because scanf will stop at the first whitespace character. Hence, you'll only get one word at a time from scanf. To get an entire line, use the fgets function.

How to seperate user input word delimiter as space using strtok

Why am I getting a segmentation fault after only reading one word?
If I enter "why is this not work"
I only get back
why
and then I get a segmentation fault.
I've seen other examples but none have used user input like I am trying to do here. I can only read one word and it won't work. I tried changing all the %c to %s but it is not helping me. I also realize segmentation fault is pointer pointing to somewhere not in memory but I cannot see what is wrong with it. Please help me understand.
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
printf("Enter a sentence: ");
scanf("%s", word);
char *tok = strtok(word, " ");
printf("%s\n", tok);
while(tok != NULL)
{
tok = strtok(NULL, " ");
printf("%s\n", tok);
if(tok == NULL)
printf("finished\n");
}
return 0;
}
EDIT: I changed scanf("%s", word); to fgets(word, 100, stdin); and now it prints everything but I get a Segmentation fault.
As pointed in comments, there is at least two problems in your first code.
Do not use scanf to read a string that you want to parse. Use fgets instead.
You do not test that tok is not NULL before using it (inside the while loop)
Such problems would have been easily detected with debugging, so I encourage you to read how to debug small programs
Corrected code should be like:
#include <stdio.h>
#include <string.h>
int main(void)
{
char word[100];
printf("Enter a sentence: ");
/* read from stdin
note the `sizeof char`, if you need to change the size of `word`,
you won't have to change this line. */
fgets(word, sizeof word, stdin);
/* initialize parser */
char *tok = strtok(word, " ");
while (tok != NULL)
{
/* printf token: it cannot be NULL here */
printf("%s\n", tok);
/* get next token*/
tok = strtok(NULL, " ");
}
printf("finished\n");
return 0;
}
This code is not correct
while(tok != NULL)
{
tok = strtok(NULL, " ");
printf("%s\n", tok);
if(tok == NULL)
printf("finished\n");
}
suppose you get to the last pass through the loop.... it gets into the loop as you got last time.... so you make a tok = strtok(NULL, " "); which returns (and assigns) NULL as there is no more stuff.... then you printf(3) it, which produced the seg fault.
Just change that into this, so you don't enter into the loop if no more tokens are available.
while((tok = strtok(NULL, " ")) != NULL)
{
printf("%s\n", tok);
/* you don't touch tok inside the loop, so you don't need to
* test it again once you get inside */
}
/* if(tok == NULL) <-- you always have tok == NULL here */
printf("finished\n");
or simpler
while(tok = strtok(NULL, " "))
{
printf("%s\n", tok);
}
printf("finished\n");
Also, add \n to the second parameter of strtok(3) call (in the two calls you have in your listing, as you can have only one token, and the final line ending has to be dropped from the first call), as when you use fgets(3) you normally will get a \n at the end of the string (which you don't want):
char *tok = strtok(word, " \n");
printf("%s\n", tok);
while(tok = strtok(NULL, " \n"))
{
printf("%s\n", tok);
}
printf("finished\n");

Using strtok with various input sizes

So I've been working on some code that doesn't quite run as expected.
The code below should call a help function when only 'h' is typed in, and quit when 'q' is typed in. I can't really understand when is it when I press 'h' it gives an error:
printf("\n");
printf("Please input request (h-help, q-quit): ");
fgets(Input, 256, stdin);
char *array[256];
int count = 0;
char *token = strtok(Input, " ");
array[0] = token;
count++;
while(token != NULL)
{
int i = 1;
token = strtok(NULL, " ");
array[i] = token;
i++;
count++;
}
if(count == 1)
{
if(strlen(array[0]) == 2)
{
if(array[0] == 'h')
{
TRIGhelp();
return 0;
}
if(array[0] == 'q')
{
return 0;
}
}
else
{
printf("Error: Illegal input!");
}
}
I have used a count variable because larger strings can be input. For example the user can input three numbers, or a string and three numbers, etc.
I have tried using strlen(array[0]) == 1 as well, it still prints out the error message.
Thanks in advance!
Lots of problems here, but I'll concentrate on strtok as that is what you are asking about.
You're reading a line from the input with fgets but then tokenize only on space characters. Every line will end with a newline (\n) so what do you want to do with it? Users might also enter tabs and on some systems you might get \r characters at the end of the line. So you probably want
token = strtok(Input, " \t\r\n");
in order to tokenize on ALL whitespace, not just spaces.

Why is strtok printing only first word?

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.

2nd Call to strtok() returns null

I'm at the top of a while loop in the client file for a client/server communication. The client gets user input (input) and I need to strtok it into cmd and cmd2 for my ifs to work.
Say the user puts in "get lname" (this is a good command for the program).
Using the following code, cmd = "get" (yay!), but cmd2 = "(null)"
input is a char input[30]
cmd and cmd2 are char* initialized to NULL.
A little help here? Thanks!
/*Until the user exits the program*/
while(cmdNum != 7)
{
printf("\nPlease enter a command: ");
scanf("%30s", input);
cmd = strtok(input, " ");
printf("cmd: %s\n", cmd);
if(strcmp(cmd, "get") == 0)
{
cmd2 = strtok(NULL, "\0");
printf("cmd2: %s\n", cmd2);
pstatus = print(cmd, sockfd);
if(pstatus == 1)
{
printf("Error printing\n");
}
}
else if(strcmp(cmd, "put") == 0)..... etc, etc....
Your second strtok call should also use a single space for it's delimiter argument, not "\0", which , if you think about it, is simply an empty string.
And more importantly, you need to read the in entire line, which scanf with %s does not do. It stops at the first space. Try fgets instead, but remember that it leaves the newline in, so add that as a delimiter.
#include <stdio.h>
#include <string.h>
int main() {
char input[50];
printf("Please enter a command: ");
fgets(input, sizeof input, stdin);
char *cmd = strtok(input, " \t\n");
printf("cmd: [%s]\n", cmd);
if (strcmp(cmd, "get") == 0) {
char *cmd2 = strtok(NULL, " \t\n");
printf("cmd2: [%s]\n", cmd2);
}
return 0;
}
After thefirst call to strtok pass NULL for the first parameter. The function stores a static var to remember where it left off.
http://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm

Resources