strtok is causing a Segmentation Fault - c

I have to get the third word in a string and wanted to use strtok. Now, the first printf works but after that I get a Seg Fault. So tokenizedString = strtok(NULL, " "); must be causing the issue, right?
Just for context: I'm looking for the third word in a string and there can be as many spaces as possible between the words.
#include <string.h>
#include <stdio.h>
char *tokenizeString(char *userCommand)
{
char *tokenizedString;
int counterForToken;
tokenizedString = strtok(userCommand, " ");
for(counterForToken = 0; counterForToken != 3; counterForToken++)
{
printf("%s\n", tokenizedString);
tokenizedString = strtok(NULL, " ");
if(tokenizedString == NULL)
{
break;
}
}
printf("%s\n", tokenizedString);
return tokenizedString;
}
int main(void)
{
char userCommand[255] = {0};
fgets(userCommand, sizeof(userCommand), stdin);
tokenizeString(userCommand);
}

Now, the first printf works but after that I get a Seg Fault. So tokenizedString = strtok(NULL, " "); must be causing the issue, right?
No, that is very poor correlation. The issue is in fact in the second call to printf. You can pass it tokenizedString when tokenizedString == NULL. The format specified %s is specified to expect a valid pointer to the first character of a zero terminated array of characters. Passing it NULL is illegal and leads to undefined behavior (causing a crash for instance). The fix is simple: check for a null pointer value. And the same applies to the first iteration of the loop, of course
char *tokenizeString(char *userCommand)
{
char *tokenizedString;
int counterForToken;
tokenizedString = strtok(userCommand, " ");
for(counterForToken = 0; counterForToken != 3 && tokenizedString != NULL; counterForToken++)
{
printf("%s\n", tokenizedString);
tokenizedString = strtok(NULL, " ");
}
if(tokenizedString != NULL)
printf("%s\n", tokenizedString);
return tokenizedString;
}

Related

Taking multiple strings and integers in a single line

I want to take multiple integer and strings in a single line such as "45 A4 Paper 217" but I want to store string A4 Paper in a single char array. I tried using scanf but it scans until space for string.
int int1;
int int2;
char str1[81];
scanf("%d %s %d",&int1,&str1,&int2);
I want str1 to be A4 Paper in str1 array
The scanf family functions are known as a poor man's parser. They can easily parse blank separated tokens, but anything more complex is at best tricky, or even impossible - more exactly other tools should be used.
Your requirement is to accept in a single string any token until an integer token is found (token here being a blank delimited string). This is just not possible in single scanf.
If the type and number of blank characters does not matter, you could use a scanf loop first trying to find an integer, next getting tokens as string:
i = scanf("%d", &int1); // get first integer
if (i != 1) {
// error condition
}
char *cur = str1;
for(;;) {
if (1 == scanf("%d", &int2)) break; // ok we have found the second integer
i = scanf("%s", cur);
if (i != 1) {
// error condition
}
cur += strlen(cur); // move cur to end of string
*cur++ = ' '; // and add a space
}
if (cur != str1) {
cur[-1] = '\0'; // erase last space
}
This should detect read errors, but does not even try to control overflow of str1. It should be added for production grade code.
This is my solution
#include <stdio.h>
#include <string.h>
int main() {
int int1,int2;
char str[100],str1[81];
char *p;
scanf("%[^\n]s",str);
p = strtok (str," ");
sscanf(p, "%d", &int1);
p = strtok (NULL, " ");
strcpy(str1,p);
strcat(str1," ");
p = strtok (NULL, " ");
strcat(str1,p);
p = strtok (NULL, " ");
sscanf(p, "%d", &int2);
printf("%d %s %d",int1,str1,int2);
return 0;
}

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");

strtok() strcat() Unexpected output

#include "stdio.h"
#include "string.h"
int main(){
int counter;
char *token;
char s[]={"I am John"};
char con[256];
token = strtok(s," ");
while(token != NULL){
if (counter==0){
strcat(con,token);
token = strtok(NULL," ");
counter++;
}else{
strcat(con,token);
token = strtok(NULL," ");
strcat(con," ");
}
}
printf("%s\n",con);
return 0;
}`
printf()'s output is "I am John"
I would like the output to be "am John"
strcat expects the first argument to be null-terminated, which isn't guaranteed by declaring con, since its uninitialized. so the invocation of strcat is undefined behavior. Therefore your program is undefined behavior. Do
con[0] = '\0';
to resolve this issue.
counter is uninitialized. Using it in an expression is undefined behavior too.
counter and array con is uninitialized . So it will lead to erroneous results.

Segmentation fault (core dumped) issue

I am trying to read in input from a user, and then tokenize each word and put each word into an array of strings. At the end, the contents of the array are printed out for debugging. My code is below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int MAX_INPUT_SIZE = 200;
volatile int running = 1;
while(running) {
char input[MAX_INPUT_SIZE];
char tokens[100];
printf("shell> ");
fgets(input, MAX_INPUT_SIZE, stdin);
//tokenize input string, put each token into an array
char *space;
space = strtok(input, " ");
tokens[0] = space;
int i = 1;
while (space != NULL) {
space = strtok(NULL, " ");
tokens[i] = space;
++i;
}
for(i = 0; tokens[i] != NULL; i++) {
printf(tokens[i]);
printf("\n");
}
printf("\n"); //clear any extra spaces
//return (EXIT_SUCCESS);
}
}
After I type in my input at the "shell> " prompt, gcc gives me the following error:
Segmentation fault (core dumped)
Any idea as to why this error is happening? Thanks in advance for your help!
char tokens[100];
This declaration should be array of array of characters(two dimensional character array) to hold Multiple strings
char tokens[100][30];
//in your case this wont work because you require pointers
//while dealing with `strtok()`
USE
Array of character pointers
char *tokens[100];
This is also wrong
printf(tokens[i]);
You should use printf with format specifier %s while printing string.
change like this
printf("%s", tokens[i]);

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