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");
Related
I am able to use this to print my default string, but when I go to print a user input it does not work--instead I get some random characters and symbols back
int i=0;
char* tok=strtok(defaultString," ");
while(tok!=NULL){
i++;
if (i==defaultInd){
printf("%s \n", tok);
break;
}
tok=strtok(NULL, " ");
}
I believe that there is some issue with accessing memory or something store in a memory that I haven't actually initialized yet, but when I try to use
char* tok=(char *)malloc(strlen(strtok(sent, " ")+1));
it just stops printing things period.
My work around had been to print argv using a for loop but I still don't know what the actual problem is.
Here is what I have to print the user input
char* tok=strtok(argv," ");
while(tok!=NULL){
printf("%s\n", tok);
tok=strtok(NULL," ");
}
I get back a series of symbols (alphanumeric, greek, etc) instead of the string I input
In
char* tok=(char *)malloc(strlen(strtok(sent, " ")+1));
you just allocate a piece of memory whose size depends on the result of strtok, but the result of strtok is not copied into the returned block of memory
char* tok=strtok(argv," ");
while(tok!=NULL){
printf("%s\n", tok);
tok=strtok(NULL," ");
}
If argv is the second argument of main that one is not a char* but a char**, so your call is wrong
What did you expect to do ? if it is to print the arguments or the program you have to do something like :
while (*++argv != 0)
puts(*argv);
If you want to get each word from a group of words given in the first argument of the program :
#include <stdio.h>
#include <string.h>
int main(int argc, char ** argv)
{
if (argc == 2) {
char* tok=strtok(argv[1]," ");
while(tok!=NULL){
printf("%s\n", tok);
tok=strtok(NULL," ");
}
}
return 0;
}
Execution :
pi#raspberrypi:/tmp $ ./a.out "aze qsd wxc"
aze
qsd
wxc
As you see I have to use a string when I call ./a.out else there are 3 argument and the first argument is just aze
In
int i=0;
char* tok=strtok(defaultString," ");
while(tok!=NULL){
i++;
if (i==defaultInd){
printf("%s \n", tok);
break;
}
tok=strtok(NULL, " ");
}
if defaultString is for instance "11 22 33" and defaultInd values 2 you will print 22
but you do not said what are the value of these variables
char* tok = strtok(defaultString, " ");
while (tok != NULL){
myarg[count]=strdup(tok);
count ++;
printf("%s\n", tok);
tok = strtok(NULL, " ");
}
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;
}
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.
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.
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 :)