I wrote a C function to take a char* as an input and split it using a space and store tokens again in a string array.
My code executes properly but before it finishes the execution, it gives an error saying segmentation error. Can anyone show me what is wrong.
void parseCommand(char *msg)
{
char buffer[25][30];
char *tok;
char *msgCopy;
//strcpy(msgCopy,msg);
msgCopy =msg;
tok = strtok(msgCopy," ");
strcpy(buffer[0],tok);
int i=1;
while(tok != NULL ){
tok = strtok (NULL, " ");
strcpy(buffer[i],tok); //me line eke error eka
printf("%d : %s\n",i,buffer[i]);
i++;
}
}
strtok finally returns NULL to signal that there are no more tokens and you call strcpy(buffer[i],tok); which attempts to read from NULL. This causes segfault.
You can solve it by moving strtok into loop condition:
while((tok = strtok (NULL, " ")) != NULL ){
strcpy...
or escaping loop using break statement:
while(1){
tok = strtok (NULL, " ");
if(tok == NULL) break;
strcpy...
Related
Here is a weird problem:
token = strtok(NULL, s);
printf(" %s\n", token); // these two lines can read the token and print
However!
token = strtok(NULL, s);
printf("%s\n", token); // these two lines give me a segmentation fault
Idk whats happened, because I just add a space before %s\n, and I can see the value of token.
my code:
int main() {
FILE *bi;
struct _record buffer;
const char s[2] = ",";
char str[1000];
const char *token;
bi = fopen(DATABASENAME, "wb+");
/*get strings from input, and devides it into seperate struct*/
while(fgets(str, sizeof(str), stdin)!= NULL) {
printf("%s\n", str); // can print string line by line
token = strtok(str, s);
strcpy(buffer.id, token);
printf("%s\n", buffer.id); //can print the value in the struct
while(token != NULL){
token = strtok(NULL, s);
printf("%s\n", token); // problem starts here
/*strcpy(buffer.lname, token);
printf("%s\n", buffer.lname); // cant do anything with token */
}}
fclose(bi);
return 1;}
Here is the example of string I read from stdin and after parsed(I just tried to strtok the first two elements to see if it works):
<15322101,MOZNETT,JOSE,n/a,n/a,2/23/1943,MALE,824-75-8088,42 SMITH AVENUE,n/a,11706,n/a,n/a,BAYSHORE,NY,518-215-5848,n/a,n/a,n/a
<
< 15322101
< MOZNETT
In the first version your compiler transforms printf() into a
puts() and puts does not allow null pointers, because internally
invokes the strlen() to determine the lenght of the string.
In the case of the second version you add a space in front of format
specifier. This makes it impossible for the compiler to call puts
without appending this two string together. So it invokes the actual
printf() function, which can handle NULL pointers. And your code
works.
Your problem reduces to the following question What is the behavior of printing NULL with printf's %s specifier?
.
In short NULL as an argument to a printf("%s") is undefined. So you need to check for NULL as suggested by #kninnug
You need to change you printf as follows:
token = strtok(NULL, s);
if (token != NULL) printf("%s\n", token);
Or else
printf ("%s\n", token == NULL ? "" : token);
I have this code in my program:
char* tok = NULL;
char move[100];
if (fgets(move, 100, stdin) != NULL)
{
/* then split into tokens using strtok */
tok = strtok(move, " ");
while (tok != NULL)
{
printf("Element: %s\n", tok);
tok = strtok(NULL, " ");
}
}
I have tried adding printf statements before and after fgets, and the one before gets printed, but the one after does not.
I cannot see why this fgets call is causing a segmentation failure.
If someone has any idea, I would much appreciate it.
Thanks
Corey
The strtok runtime function works like this
the first time you call strtok you provide a string that you want to tokenize
char s[] = "this is a string";
in the above string space seems to be a good delimiter between words so lets use that:
char* p = strtok(s, " ");
what happens now is that 's' is searched until the space character is found, the first token is returned ('this') and p points to that token (string)
in order to get next token and to continue with the same string NULL is passed as first argument since strtok maintains a static pointer to your previous passed string:
p = strtok(NULL," ");
p now points to 'is'
and so on until no more spaces can be found, then the last string is returned as the last token 'string'.
more conveniently you could write it like this instead to print out all tokens:
for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " "))
{
puts(p);
}
EDITED HERE:
If you want to store the returned values from strtok you need to copy the token to another buffer e.g. strdup(p); since the original string (pointed to by the static pointer inside strtok) is modified between iterations in order to return the token.
I'm trying to understand what's wrong with my code.
I have a string composed by words inserted by user input.
I've terminated the string so it should be ok.
Then I use another cycle to reverse the direction of the words. But when I call STRLEN on the last word of the string, it gives me segmentation fault.
(the reversal part is not done yet, since i'm stuck with this problem).
Why?
Here is the code:
char *frase, c;
int i=0;
int d=1;
frase = (char*)malloc(sizeof(char));
printf("Insert phrase: ");
while(c != '\n') {
c = getc(stdin);
frase = (char*)realloc(frase,d*sizeof(char)); //dynamic allocation
frase[i] = c;
d++;
i++;
}
//at the end i terminate the string
frase[i]='\0';
printf("\nInserted phrase: %s\n",frase);
// here I start the reversal, first of all I separate all the words
char *pch;
char s[2] = " ";
int messl=0;
pch = strtok (frase,s);
printf ("%s\n",pch);
messl += 1 + strlen(pch);
printf ("Lung stringa = %d\n",messl);
char *message = (char*) malloc(messl);
while (pch != NULL) {
pch = strtok (NULL, s);
printf("%s\n",pch);
messl += 1 + strlen(pch); //in the last cycle of the loop I get the error
}
//printf ("%s\n",message);
return 0;
In your code.
while(c != '\n')
at the very first iteration, c is uninitialised. It invokes undefined behaviour to use the value of an automatic local variable which has not been initialized explicitly.
getc() returns an int which , at times, may not fit into a char. Change the type of c to int.
That said, as you mentioned in your question, that you're getting segfault from strlen(), you need check for the non-NULL value of the passed pointer to strlen(). Add the NULL-check to pch immediately after tokenizing.
The main problem is:
while (pch != NULL) {
pch = strtok (NULL, s);
printf("%s\n",pch);
messl += 1 + strlen(pch);
When strtok returns NULL, you go on to call printf and strlen on it. You need to immediately test pch upon calling strtok. For example the loop structure could be:
while ( (pch = strtok(NULL, s)) != NULL ) {
There are various other problems too, as other answerers/commentors have noted.
I am using strtok(...) of the library and it appears to be working fine until the end condition, where it results in a segmentation fault and program crash. The API claims that strtok(...) will output a NULL when there are no more tokens to be found, which meant, I thought, that you had to catch this NULL in order to terminate any loops that you were running using strtok(...). What do I need to do to catch this NULL to prevent my program from crashing? I imagined the NULL was allowed for use as a terminating condition.
I have prepared a SSCCE for you to observe this behavior. I need strtok(...) to work for a much larger piece of software I am writing, and I am getting the exact same segmentation behavior. The output at the command line is shown below this code vignette (yes I know you use <...> to enclose libraries, but I was having difficulty getting this post to display the code libraries). I am using gcc version 4.5.3, on a Windows 8 OS, and below shows two different flavors of how I imagine one could try to catch the NULL in a loop.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
main(){
char* from = "12.34.56.78";
char * ch = ".";
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
printf("Broke out of loop!");
while(strcmp(token, 0) != 0){
printf("%s\n",token);
token = strtok(NULL, ch);
}
}
############ OUTPUT: ############
$ ./test
12
34
56
78
Segmentation fault (core dumped)
strtok modifies its first argument. You are passing it a string from read-only memory, and the segfault occurs when strtok tries to change it. Try changing from:
char* from = "12.34.56.78";
to
char from[] = "12.34.56.78";
you are first checking if token is not equal to NULL(when it is, it breaks out of the while loop). Then you are comparing token, which is a NULL with a constant NUMBER? here: strcmp(token, 0) when strcmp expects 2 strings, you provide a number. strcmp will try to fetch a string at 0th address(or NULL) giving you a segmentation fault.
while(strcmp(token, 0) != 0){
token = strtok(NULL, ch);
printf("%s\n",token);
}
Also this piece of code should be something like the following:
change
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
to
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
This is a problem:
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
You're checking for NULL, but then calling strtok again and not checking after that but before printing.
There are other problems with the code, but I suspect this is why it crashes where it does now.
The problem is that even though you terminate the loop when strtok() returns NULL, you try to print the NULL first:
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token); // not good when token is NULL
}
It turns out there are several opportunities in addition to this one for segfaults in this example, as pointed out by other answers.
Here's one way to handle your example tokenization:
char from[] = "12.34.56.78";
char * ch = ".";
char * token = strtok(from, ch);
while (token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
If purpose of code is only to print element separated by '.',
Only change in char declaration and before printing token check for its value NULL or not !
main(){
char from[] = "12.34.56.78.100.101";
char * ch = ".";
char * token = strtok(from, ch);
//printf("%s\n",token);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
}
OUTPUT
./test1
12
12
34
56
78
100
101
You have both memory access errors and logic errors. I will only address the memory access errors that are causing your program to crash.
strtok modifies it's first argument. Since you are passing in a string literal, it is unable to modify the string (string literals are not modifiable.)
Here's a possible fix to define from as a modifiable string array:
char from[] = "12.34.56.78";
Because strtok modifies the string passed into it, you cannot process that string again in your second while loop. You are essentially passing in a NULL into the strcmp function there. A possible fix would be to copy the from array into another buffer each time you wish to use strtok.
I've been reading up on strtok and thought it would be the best way for me to compare two files word by word. So far i can't really figure out how i would do it though
Here is my function that perfoms it:
int wordcmp(FILE *fp1, FILE *fp2)
{
char *s1;
char *s2;
char *tok;
char *tok2;
char line[BUFSIZE];
char line2[BUFSIZE];
char comp1[BUFSIZE];
char comp2[BUFSIZE];
char temp[BUFSIZE];
int word = 1;
size_t i = 0;
while((s1 = fgets(line,BUFSIZE, fp1)) && (s2 = fgets(line2,BUFSIZE, fp2)))
{
;
}
tok = strtok(line, " ");
tok2 = strtok(line, " ");
while(tok != NULL)
{
tok = strtok (NULL, " ");
}
return 0;
}
Don't mind the unused variables, I've been at this for 3 hours and have tried all possible ways I can think of to compare the values of the first and second strtok. Also I would to know how i would check which file reaches EOF first.
when i tried
if(s1 == EOF && s2 != EOF)
{
return -1;
}
It returns -1 even when the files are the same! Is it because in order for it to reach the if statement outside of the loop both files have reached EOF which makes the program always go to this if statement?
Thanks in advance!
If you want to check if files are same try doing,
do {
s1 = fgetc(fp1);
s2 = fgetc(fp2);
if (s1 == s2) {
if (s1 == EOF) {
return 1; // RETURN TRUE
}
continue;
}
else {
return -1; // RETURN FALSE
}
} while (1);
Good Luck :)
When you use strtok() you typically use code like this:
tok = strtok(line, " ");
while (NULL != tok)
{
tok = strtok(NULL, " ");
}
The NULL in the call in the loop tells strtok to continue from after the previously found token until it finds the null terminating character in the value you originally passed (line) or until there are no more tokens. The current pointer is stored in the run time library, and once strtok() returns NULL to indicate no more tokens any more calls to strtok() using NULL as the first parameter (to continue) will result in NULL. You need to call it with another value (e.g. another call to strtok(line, " ")) to get it to start again.
What this means is that to use strtok on two different strings at the same time you need to manually update the string position and pass in a modified value on each call.
tok = strtok(line, " ");
tok2 = strtok(line2, " ");
while (NULL != tok && NULL != tok2)
{
/* Do stuff with tok and tok2 here */
if (strcmp(tok, tok2)... {}
/* Update strtok pointers */
tok += strlen(tok) + 1;
tok2 += strlen(tok2) + 1;
/* Get next token */
tok = strtok(tok, " ");
tok2 = strtok(tok2, " ");
}
You'll still need to add logic for determining whether lines are different - you've not said whether the files are equivalent if a line break occurs at different position but the words surrounding it are the same. I assume it should be, given your description, but it makes the logic more awkward as you only need to perform the initial fgets() and strtok() for a file if you don't already have a token. You also need to look at how files are read in. Currently your first while loop just reads lines until the end of the file without processing them.