I am trying to use strtok() to parse a string deliminated by spaces. From what I can tell, I am using it correctly, but it won't run on ideone.com. Is there anything wrong with the following code? I just get Runtime error time: 0 memory: 2288 signal:11
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void test(char *command)
{
char* output = strtok(command, " ");
printf("%s\n", output);
}
int main(void) {
test("set_rate 200");
return 0;
}
Here it is on ideone.com if you want to try it.
Always consult the man pages first.
strtok(3) says:
Be cautious when using these functions. If you do use them, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
strtok will modify the string passed as the first parameter, so you can't pass a string literal, change your main like this:
int main(void) {
char str[] = "set_rate 200";
test(str);
return 0;
}
str here is an char array, but not a string literal.
As strtok modifies the string, it requires that the string is not in read-only memory. So when you pass a string literal to your test function, it crashes.
This is better:
char s[] = "set_rate 200";
test(s);
When you pass hard coded string that was stored in read-only memory.
strtok() does not work with string which is read-only memory.
You need to use string variable rather than string literal .
you can first store string in some variable and then you can pass it to the function.
char[]="set_rate 200";
test(str);
See example:
char *str = malloc(20);
char *tok = NULL;
int len = 0;
strcpy(str, "This is a string");
len = strlen(str);
printf("string before strtok(): %s\n", str);
tok = strtok(str, " ");
while (tok) {
printf("Token: %s\n", tok);
tok = strtok(NULL, " ");
}
Edit
From #Yu Hao comment i am adding this
char *str = "set_rate 200";
test(str); // This won't work. here str is pointer to the string literal.
Related
#include <stdio.h>
#include <string.h>
int main(){
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *str;
printf("%s\n", name)
str = strtok(name, ".cities");
printf("%s\n", str);
return 0;
}
This is the output:
eseumdesconhecidolheoferecerflores.issoeimpulse.cities
umd
I have no idea what is happening at all. What I want is for the output of strtok to be a pointer to "eseumdesconhecidolheoferecerflores.issoeimpulse"
The delimiter argument to strtok is a string containing individual characters used to separate the string.
You specified delimiters ., c, i, t, e, and s.
So it's no surprise the output is umd for the first token, since it is surrounded by characters in your delimiter string.
If you want to find a whole string, you should use strstr instead.
For example:
char name[] = "eseumdesconhecidolheoferecerflores.issoeimpulse.cities";
char *pos;
pos = strstr(name, ".cities");
if (pos)
{
*pos = '\0';
printf("%s\n", name);
}
here is my code,
#include <string.h>
#include <stdio.h>
main ()
{
explode (" ", "this is a text");
}
explode (char *delimiter, char string[])
{
char *pch;
printf ("Splitting string \"%s\" into tokens:\n",string);
pch = strtok (string,delimiter);
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, delimiter);
}
return 0;
}
I compile this code using gcc -o 1.exe 1.c and shows no error. But when i execute 1.exe it shows Splitting string "this is a text" into tokens: and at that moment 1.exe stops working (a dialogue box of windows shows). can anybody tell the problem and solve the problem? I am using windows 10.
While you can't do this with strtok because the literal can't be modified, it can be done with strcspn.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void explode (char *delimiter, char *string);
int main()
{
explode (" ", "this is a text");
return 0;
}
void explode (char *delimiter, char *string)
{
int span = 0;
int offset = 0;
int length = 0;
if ( delimiter && string) {
length = strlen ( string);
printf ("Splitting string \"%s\" into tokens:\n",string);
while (offset < length) {
span = strcspn ( &string[offset],delimiter);//work from offset to find next delimiter
printf ("%.*s\n",span, &string[offset]);//print span number of characters
offset += span + 1;// increment offset by span and one characters
}
}
}
In your explode() function, you're passing a string liteal ("this is a text") and using the same as the input to strtok().
As strtok() modifies the input string, here, it will invoke invokes undefined behavior. As mentioned in th C11 standard, chapter ยง6.4.5, String literals
[...] If the program attempts to modify such an array, the behavior is
undefined.
You can either
Define an array and initalize it with the string literal and the use the array as input to strtok().
take a pointer, use strdup() to copy the initializer and then supply that pointer to strtok().
The bottom line is, the input string to strtok() should be modifiable.
I am new to C and I am trying to split a date/time string into separate variables. However, when I step through the code in gdb line by line, it works, however, when I let it run through normally without breakpoints it seg faults and I can't see why.
Below is the code:
char * dateTimeString = "2011/04/16 00:00";
char dateVar[11];
char timeVar[6];
if (splitTimeAndDateString(dateVar, timeVar, dateTimeString))
{
exit(1);
}
printf("Date: %s\tTime: %s\n", dateVar, timeVar);
Below is the function
int splitTimeAndDateString(char date[11], char time[6], char * dateString)
{
char *token;
token = strtok(dateString, " ");
int i = 0;
while (token != NULL)
{
if (i == 0)
{
strcpy(date, token);
}
else if (i == 1)
{
strcpy(time, token);
}
else
{
printf("Overrun date time string\n");
return 1;
}
token = strtok(NULL, " ");
i++;
}
return 0;
}
Thanks for any help you can provide.
The strtok() function modifies string that you wants to parse, and replace all delimiters with \0 nul symbol.
Read: char * strtok ( char * str, const char * delimiters );
str
C string to truncate.
Notice that the contents of this string
are modified and broken into smaller strings (tokens). Alternativelly,
a null pointer may be specified, in which case the function continues
scanning where a previous successful call to the function ended.
In your code:
strtok(dateString, " ");
^
| is a constant string literal
dateString points to "2011/04/16 00:00" a constant string literal, and by using strtok() your code trying to write on read-only memory - that is illegal and this caused segmentation fault.
Read this linked answer for diagram to understand: how strtok() works?
Edit:
#: char * strtok ( char * str, const char * delimiters ); In given code example, str is an array, not constant string literal. Its declaration:
char str[] ="- This, a sample string.";
Here str[] is an nul terminated array of chars, that initialized with string and its length is equals to size of the assigned string. You can change the content of str[] e.g. str[i] = 'A' is a valid operation.
Whereas in your code:
char * dateTimeString = "2011/04/16 00:00";
dateTimeString is pointer to string literal that is not modifiable e.g dateTimeString[i] = 'A' is an illegal operation this time.
I am new to C and I am trying to split a date/time string into separate variables. However, when I step through the code in gdb line by line, it works, however, when I let it run through normally without breakpoints it seg faults and I can't see why.
Below is the code:
char * dateTimeString = "2011/04/16 00:00";
char dateVar[11];
char timeVar[6];
if (splitTimeAndDateString(dateVar, timeVar, dateTimeString))
{
exit(1);
}
printf("Date: %s\tTime: %s\n", dateVar, timeVar);
Below is the function
int splitTimeAndDateString(char date[11], char time[6], char * dateString)
{
char *token;
token = strtok(dateString, " ");
int i = 0;
while (token != NULL)
{
if (i == 0)
{
strcpy(date, token);
}
else if (i == 1)
{
strcpy(time, token);
}
else
{
printf("Overrun date time string\n");
return 1;
}
token = strtok(NULL, " ");
i++;
}
return 0;
}
Thanks for any help you can provide.
The strtok() function modifies string that you wants to parse, and replace all delimiters with \0 nul symbol.
Read: char * strtok ( char * str, const char * delimiters );
str
C string to truncate.
Notice that the contents of this string
are modified and broken into smaller strings (tokens). Alternativelly,
a null pointer may be specified, in which case the function continues
scanning where a previous successful call to the function ended.
In your code:
strtok(dateString, " ");
^
| is a constant string literal
dateString points to "2011/04/16 00:00" a constant string literal, and by using strtok() your code trying to write on read-only memory - that is illegal and this caused segmentation fault.
Read this linked answer for diagram to understand: how strtok() works?
Edit:
#: char * strtok ( char * str, const char * delimiters ); In given code example, str is an array, not constant string literal. Its declaration:
char str[] ="- This, a sample string.";
Here str[] is an nul terminated array of chars, that initialized with string and its length is equals to size of the assigned string. You can change the content of str[] e.g. str[i] = 'A' is a valid operation.
Whereas in your code:
char * dateTimeString = "2011/04/16 00:00";
dateTimeString is pointer to string literal that is not modifiable e.g dateTimeString[i] = 'A' is an illegal operation this time.
Is there any pre-defined function in C that can split a string given a delimeter? Say I have a string:
"Command:Context"
Now, I want to store "Command" and "Context" to a two dimensional array of characters
char ch[2][10];
or to two different variables
char ch1[10], ch2[10];
I tried using a loop and it works fine. I'm just curious if there is such function that already exists, I don't want to reinvent the wheel. Please provide a clear example, thank you very much!
You can use strtok
Online Demo:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="Command:Context";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,":");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ":");
}
return 0;
}
Output:
Splitting string "Command:Context" into tokens:
Command
Context
You can tokenise a string with strtok as per the following sample:
#include <stdio.h>
#include <string.h>
int main (void) {
char instr[] = "Command:Context";
char words[2][10];
char *chptr;
int idx = 0;
chptr = strtok (instr, ":");
while (chptr != NULL) {
strcpy (words[idx++], chptr);
chptr = strtok (NULL, ":");
}
printf ("Word1 = [%s]\n", words[0]);
printf ("Word2 = [%s]\n", words[1]);
return 0;
}
Output:
Word1 = [Command]
Word2 = [Context]
The strtok function has some minor gotchas that you probably want to watch out for. Primarily, it modifies the string itself to weave its magic so won't work on string literals (for example).