2nd Call to strtok() returns null - c

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

Related

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.

strtok() then strcmp() returning false when true

I'm guessing this is a type issue, so maybe you can show me how it is correctly done.
I'm reading command inputs from stdin and I want to quit when the user enters q.
I'm reading a user input from stdin using fgets() into a pointer to a character array. Then I splice off the first word using strtok() and assign it to another pointer to a character array. Then I compare it to a q in order to see if the user wants to quit the program by using the strcmp() function.
Here is some code:
char *input = (char*)malloc(32 * sizeof(char));
char *command = (char*)malloc(8 * sizeof(char));
while (strcmp(command, "q") != 0)
{
memset(input, 0, sizeof(input));
printf("Enter command: ");
fgets(input, 64, stdin);
command = strtok(input, " ");
//if I enter q --> printf("%d", strcmp(command, "q")) == 10
//if I enter w --> printf("%d", strcmp(command, "q")) == 6
}
What I want is, if command == q then printf("%d", strcmp(command, "q")) should equal 0 else it should print any other integer.
I should also note that I have verified command is being correctly assigned. In other words, when I enter q, command == "q".
Maybe you can try this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *input = (char*)malloc(32 * sizeof(char));
char *command = (char*)malloc(8 * sizeof(char));
while (strcmp(command, "q") != 0)
{
memset(input, 0, sizeof(input));
printf("Enter command: ");
fgets(input, 64, stdin);
command = strtok(input, " \n"); // Line corrected.
//if I enter q --> printf("%d", strcmp(command, "q")) == 10
//if I enter w --> printf("%d", strcmp(command, "q")) == 6
}
return 0;
}
Several issues here.
The memory allocated here
char *command = (char*)malloc(8 * sizeof(char));
leaks the moment this line
command = strtok(input, " ");
gets execute as the one and only reference to the memory allocated gets overwritten and therefore lost.
A possible buffer overflow can occur here
fgets(input, 64, stdin);
as allowing to read more bytes (64) ito input as it points to be the allocation done here
char *input = (char*)malloc(32 * sizeof(char));
Assuming the data input by the user does not contain a sequence like '[blanks]q ...thencommandget assignedNULL` by this call
command = strtok(input, " ");
which leads to passing NULL to strcmp() here on testing for next iteration here
while (strcmp(command, "q") != 0)
Doing so invoke undefined behaviour.
The code misses to check the outcome of relevant function calls, like malloc()`` andfgets()`.
Casting the result of malloc() & friends isn't needed in C nor is it recommended in way. So just do not do it. It might very well hide errors.
sizeof (char) is defined to be 1. No need to use it.
Do not spoil you code with "Magic Numbers"/"Tokens" like 32, 8, 64, "q" ...
Using while-loop conceptionally is the wrong approach if you want to perform a certain action at least once. In such cases use a do-while loop.
Fixing all this might lead to the following code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define INPUT_BUFFER_SIZE (64)
#define QUIT_STRING "q"
int main(void)
{
int result = EXIT_SUCCESS; /* Be optimistic. */
char *input = malloc(INPUT_BUFFER_SIZE * sizeof *input);
if (NULL == input)
{
perror("malloc () failed");
result = EXIT_FAILURE;
}
else
{
char *command;
do
{
printf("Enter command:\n");
if (NULL == fgets(input, INPUT_BUFFER_SIZE, stdin))
{
if (!feof(stdin))
{
result = EXIT_FAILURE;
fprintf(stderr, "fgets() failed.\n");
}
break;
}
command = strtok(input, " \n");
} while ((command == NULL) || strcmp(command, QUIT_STRING) != 0);
if (NULL != command)
{
printf("User quit.\n");
}
free(input);
}
return result;
}

strtok(NULL, ) segmentation fauls

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.

Taking a string, and parsing/tokenizing into smaller strings using hyphen delimiter

I am tasked with writing a C program that will take a string with hyphens in it, and check to see that the first group of the string (before the hyphen) is alphabet/letter only, the next group is numeric only, and the last group is alphabet/letter only. It is similar to this project: http://wps.aw.com/wps/media/objects/7257/7431666/Case_Studies/GaddisJavaCSO_CS6.pdf
So far I am stuck on splitting the string into 3 variables. I have read about strtok and manipulating the scanf function, but I haven't been successful:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char serial [50];
char * part1 = NULL, part2 = NULL, part3 = NULL;
printf("Enter Serial Number:\n");
scanf("%s", serial);
part1 = strtok (serial, "-");
part2 = strtok(NULL, "-");
part3 = strtok(NULL, "-");
printf("You entered %s\n", part1);
printf("You entered %s\n", part2);
printf("You entered %s\n", part3);
return 0;
}
you are using strtok wrong, pass parameters to it and it should work fine.
char * pch = strtok (serial, "-" );
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, "-");
}
or in your example you need to define each as a char* :
char * part1= strtok (serial, "-");
char * part2 = strtok(NULL, "-");
char* part3 = strtok(NULL, "-")
StrTok + example
strcpy(part1, strtok(serial, "-"));//premise: string has hyphen
strcpy(part2, strtok(NULL, "-"));
strcpy(part3, strtok(NULL, "-"));
You could utilize scanf's formatting rules to read your strings directly from the input line.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char part1[40], part2[40], part3[40];
int count, n;
do{
n = 0;
flushall();
printf("Enter Serial Number:\n");
count = scanf(" %39[A-Za-z]-%39[0-9]-%39[A-Za-z]%n", part1, part2, part3, &n);
if( count != 3 || n == 0 ){
printf("Recognize %i parts, %s\n", count, n == 0 ? "did not parse to the end" : "parsed to the end");
}
}while(count != 3 || n == 0);
printf("You entered %s\n", part1);
printf("You entered %s\n", part2);
printf("You entered %s\n", part3);
return 0;
}
This is quite a strict form of parsing the input and requires the user to keep the outer form. You can easily filter allowed strings by not using %s but rather something like %[0-9]. The best way for me to filter serialnumber inputs was always Regex if available... but i dont think this is part of your homework yet :)

Resources