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).
Related
To understand the behavior of strtok() in C ANSI, I worte two code.
#include <stdio.h>
#include <string.h>
int main()
{
char str[101] = "This is";
char *pch;
printf("Splitting string %s into tokens : \n",str);
pch = strtok(str," ");`enter code here`
while(pch != NULL)
{
printf("%s\n",pch);
pch = strtok(NULL, " ");
}
return 0;
}
The result of This program is
Splitting string "This is " into tokens:
This
is
Next, I changed it a little bit.
#include <stdio.h>
#include <string.h>
int main()
{
char str[101] = ;
char *pch;
scanf("%s",str); //After launch program, I typed "This is "
str[strcspn(str,"\n")] = '\0'
printf("Splitting string %s into tokens : \n",str);
pch = strtok(str," ");`enter code here`
while(pch != NULL)
{
printf("%s\n",pch);
pch = strtok(NULL, " ");
}
return 0;
}
It prints
Splitting string "This" into tokens:
This
I can't understand why the second word is gone when I use stdin.
The problem isn't with strtok, but with your use of scanf and the "%s" format specifier. That format specifier reads space delimited strings, i.e you can not use "%s" to read anything with a space in it.
The natural solution is to use fgets instead, which you have already prepared for by "removing the newline" (which scanf would not usually read anyway).
It should have been pretty obvious that the strtok can't be involved, since you print the input string before even calling strtok.
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 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.
I am trying to get a function to split a string containing several words which are separated by 1 or more spaces and put each word without any spaces into an index of an array of strings.
I have been googling it for a while, it seems I need strtok but I am a bit clueless, would someone please shed some light?
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
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;
}
I am not the best with pointers, so maybe you can see what I'm doing wrong.
Let's say that I have an array that was initialized like this:
char *arrayOfCommands[]={"ls -l", "wc -l"};
My goal is to get an array called char *currentCommand out of this array that looks at a specific cell of arrayOfCommands and separates the command into pieces on spaces.
My final goal would be to have a new currentCommand array on each loop that each look like this:
First Loop:
currentCommand = [ls][-l]
First Loop:
currentCommand = [wc][-l]
Here is the code I have so far:
for (i = 0; i < 2; ++i) {
char str[] = arrayOfCommands[i];
char * currentCommand;
printf ("Splitting string \"%s\" into tokens:\n",str);
currentCommand = strtok (str, " ");
while (currentCommand != NULL){
printf ("%s\n",currentCommand);
currentCommand = strtok (NULL, " ");
}
.
.
.
//Use the currentCommand array (and be done with it)
//Return to top
}
Any help would be greatly appreciated! :)
UPDATE:
for (i = 0; i < commands; ++i) {
char str[2];
strncpy(str, arrayOfCommands[i], 2);
char *currentCommand[10];
printf ("Splitting string \"%s\" into tokens:\n",str);
currentCommand = strtok (str, DELIM);
while (currentCommand != NULL){
printf ("%s\n",currentCommand);
currentCommand = strtok (NULL, DELIM);
}
}
I am getting this error: ** incompatible types in assignment**
It's talking about the "str" I'm passing the strtok function.
strtok operates by modifying the string that you pass; this is easy to miss when using some man pages. Each command in your array is a literal string: attempts to modify them will cause problems. So you'll need to make a copy of each command before using it with strtok.
Furthermore, this is an invalid initialization for an array:
char str[] = arrayOfCommands[i];
Declare str as an array of some fixed size, then use strncpy to make copies of each command before tokenizing them using strtok:
char str[MAX_COMMAND_LEN + 1];
strncpy(str, arrayOfCommands[i], MAX_COMMAND_LEN);
// ...