issue to extract token from sub token using strtok() function in c - c

Have written following code in c
#include "stdio.h"
#include "string.h"
int main()
{
char str[] = "gatway=10.253.1.0,netmask=255.255.0.0,subnet=10.253.0.0,dns=10.253.0.203";
char name[100],value[100];
char *token1,*token2;
char *commasp = ", ";
char *equ="=";
token1 = strtok(str,commasp);
while(token1 != NULL)
{
token2 = strtok(token1,equ);
sprintf(name,"%s",token2);
token2 = strtok(NULL,commasp);
sprintf(value,"%s",token2);
printf("Name:%s Value:%s\n",name,value);
token1 = strtok(NULL,commasp);
}
return 0;
}
My problem is i got only one printf like Name:gatway Value:10.253.1.0. i know last strtok() in while loop followed by previous strok() which turns to null so token1 get null value and break the loop. Have think solution for it to not use strtok() in while loop for sub token (getting name and value) and use other method to extract name and value but it seems to lengthy code(using for or while loop for character match).So any one have batter solution to packup code in single loop.

You could use strtok_r instead of strtok.
char *key_value;
char *key_value_s;
key_value = strtok_r(str, ",", &key_value_s);
while (key_value) {
char *key, *value, *s;
key = strtok_r(key_value, "=", &s);
value = strtok_r(NULL, "=", &s);
printf("%s equals %s\n", key, value);
key_value = strtok_r(NULL, ",", &key_value_s);
}
gatway equals 10.253.1.0
netmask equals 255.255.0.0
subnet equals 10.253.0.0
dns equals 10.253.0.203
Frankly though I think it would be easier to just look for , and when you find one look for = backwards.

You can do this in two steps, first parse the main string:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "gatway=10.253.1.0,netmask=255.255.0.0,subnet=10.253.0.0,dns=10.253.0.203";
char name[100],value[100];
char *commasp = ", ";
char *ptr[256], **t = ptr, *s = str;
*t = strtok(str, commasp);
while (*t) {
t++;
*t = strtok(0, commasp);
}
for (t = ptr; *t; t++) {
printf("%s\n", *t);
// now do strtok for '=' ...
}
return 0;
}
Then parse individual pairs as before.
The above results in:
gatway=10.253.1.0
netmask=255.255.0.0
subnet=10.253.0.0
dns=10.253.0.203

Related

Taking only a part of a text to an array [duplicate]

How to split a string into an tokens and then save them in an array?
Specifically, I have a string "abc/qwe/jkh". I want to separate "/", and then save the tokens into an array.
Output will be such that
array[0] = "abc"
array[1] = "qwe"
array[2] = "jkh"
please help me
#include <stdio.h>
#include <string.h>
int main ()
{
char buf[] ="abc/qwe/ccd";
int i = 0;
char *p = strtok (buf, "/");
char *array[3];
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, "/");
}
for (i = 0; i < 3; ++i)
printf("%s\n", array[i]);
return 0;
}
You can use strtok()
char string[] = "abc/qwe/jkh";
char *array[10];
int i = 0;
array[i] = strtok(string, "/");
while(array[i] != NULL)
array[++i] = strtok(NULL, "/");
Why strtok() is a bad idea
Do not use strtok() in normal code, strtok() uses static variables which have some problems. There are some use cases on embedded microcontrollers where static variables make sense but avoid them in most other cases. strtok() behaves unexpected when more than 1 thread uses it, when it is used in a interrupt or when there are some other circumstances where more than one input is processed between successive calls to strtok().
Consider this example:
#include <stdio.h>
#include <string.h>
//Splits the input by the / character and prints the content in between
//the / character. The input string will be changed
void printContent(char *input)
{
char *p = strtok(input, "/");
while(p)
{
printf("%s, ",p);
p = strtok(NULL, "/");
}
}
int main(void)
{
char buffer[] = "abc/def/ghi:ABC/DEF/GHI";
char *p = strtok(buffer, ":");
while(p)
{
printContent(p);
puts(""); //print newline
p = strtok(NULL, ":");
}
return 0;
}
You may expect the output:
abc, def, ghi,
ABC, DEF, GHI,
But you will get
abc, def, ghi,
This is because you call strtok() in printContent() resting the internal state of strtok() generated in main(). After returning, the content of strtok() is empty and the next call to strtok() returns NULL.
What you should do instead
You could use strtok_r() when you use a POSIX system, this versions does not need static variables. If your library does not provide strtok_r() you can write your own version of it. This should not be hard and Stackoverflow is not a coding service, you can write it on your own.

break a string into 'first' and 'second'

I have read through countless strtok posts, even copied some directly in their entirety into a new int main, but I can't figure out how to create the functions get_first and get_second.
get_first("This is a sentence."); //returns "This"
get_rest("This is a sentence."); //returns "is"
This is what I have so far, I have had nothing but trouble with strtok, but I don't know what else to use.
#include <stdio.h>
#include <string.h>
char * get_first(char * string) {
string = strtok(string, " ");
return string;
}
char * get_second(char * string) {
string = strtok(string, " ");
string = strtok(NULL, " ");
return string;
}
int main(int argc, char * argv[]) {
char * test_string = "This is a sentence.";
char * first = get_first(test_string);
char * second = get_second(test_string);
printf("%s\n", first);
printf("%s\n", second);
}
Getting no faults compiling with gcc -g -Wall, but it always seg faults. I think I have tried every permutation of char c[] and char * c there is.
strtok changes the string. (but String literals are not allowed to change.)
So create a copy.
Do the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * get_first(const char *string){
char *clone = strdup(string);//create copy, strdup is non standard. malloc and copy.
char *token = strtok(clone, " ");
if(token)
token = strdup(token);
free(clone);
return token;
}
char * get_second(const char *string) {
char *clone = strdup(string);
char *token = strtok(clone, " ");
if(token && (token = strtok(NULL, " ")))
token = strdup(token);
free(clone);
return token;
}
int main(void) {
char * test_string = "This is a sentence.";
char * first = get_first(test_string);
char * second = get_second(test_string);
printf("%s\n", first);
printf("%s\n", second);
free(first);
free(second);
}

How to pass a character string to a function in C

I am trying to process a character string in order to change something in a file. I read from a file a character string which contains a command and an argument, separated by a space character. I separated this array in tokens.
Now I want to pass the second token, which is the argument to a function. My problem is that when I run my program, the screen freezes and nothing happens. Here is my separating way and the call to the function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void create_file(char *argument)
{
//some code goes here
}
int main()
{
int i = -1;
char *token[5];
char command[20];
const char delim[1] = " ";
FILE *fin;
fin = fopen("mbr.op", "r");
while(fscanf(fin, "%[^\n]", command) == 1)
{
i = -1;
token[++i] = strtok(command, delim);
while(token[i] != NULL)
token[++i] = strtok(NULL, delim);
if(strcmp(token[0], "CREATE_FILE") == 0)
create_file(token[1]);
}
fclose(fin);
return 0;
}
You have a few errors, first command[20] is an uninitialised string and that will cause undefined behaviour. Second, you failed to check the first arg as well as the second, so I added a test where commented. Also, the strings are not long enough so I removed the length. Lastly I test for a NULL pointer passed to the function.
Edit code was added to the question to show that command[20] was initialised, but it is still too short to take the command and a reasonable file name (thanks to #ameyCU).
#include <stdio.h>
#include <string.h>
void create_file(char *argument)
{
if(argument == NULL)
printf("NULL pointer\n");
else
printf("Arg: %s\n", argument);
}
int main(void)
{
int i = -1;
char *token[5];
char command[] = "CREATE_FILE myfile.txt";
const char delim[] = " ";
token[++i] = strtok(command, delim);
while(token[i] != NULL)
token[++i] = strtok(NULL, delim);
if(token[0] != NULL && strcmp(token[0], "CREATE_FILE") == 0) // added test
create_file(token[1]);
return 0;
}
Program output
Arg: myfile.txt
The first error is present in array definition:
const char delim[1] = " ";
In C "" is a string - an array of characters delimited by '\0'. This means that what stands to the right of "=" is a string of two chars:
// ' ' + '\0'
//0x20 0x00
Therefore this should be an array of two chars:
const char delim[2] = " ";
or
const char delim[] = " ";

Split char array in 'C' to CSV's

I need to split a char array into CSV's. Actually we can do the reverse of it using strtok() like:
#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;
}
But in my case, there's an char array suppose char bits[1024]="abcdefghijklmn". I need to get the output as a,b,c,d,e,f,g,h,i,j,k,m,n.
Is there any function or library to do this i.e. in terms of raw meaning, for every character it has to put a comma.
Just iterate over the string until you hit the end-of-string '\0' character. Or use the length of the data in the array (which may be smaller than the array size) and use a simple for loop.
This works for a null terminated string. But it will leave a dangling comma at the end.
void tokenise(char *s, char *d)
{
while(*d++ = *s++) *d++ = ',';
}
If you know the length of the string already, you can pass that through. This will not leave a dangling comma.
void tokenise(char *s, char *d, int length)
{
int i = 0;
while((*d++ = *s++) && ((i++)<(length-1))) *d++ = ',';
}
In both examples, s is a pointer to the source string and d points to the output tokenised string. It is up to the calling code to ensure the buffer d points to is sufficiently large.
you can use this simple function from old basic :
// ............................................................. string word at
char * word_at(char *tString, int upTo, char *dilim) {
int wcount;
char *rString, *temp;
temp= (char *) malloc(sizeof(char) * (strlen(tString)+1));
strcpy(temp, tString);
rString= strtok(temp, dilim);
wcount=1;
while (rString != NULL){
if (wcount==upTo) {
return rString;
}
rString= strtok(NULL, dilim);
wcount++;
}
return tString ;
}
parameter : string , index and character delimiter
return : word : ( char *)
If you find easy to implement it, then this could help you to start
char* split_all( char arr[], char ch )
{
char *new, *ptr;
new = ptr = calloc( 1, 2*strlen( arr ) ); // FIXME : Error checks
for( ; *(arr + 1) ; new++, arr++ )
{
*new = *arr;
new++;
*new = ch;
}
*new = *arr;
return ptr;
}
You can re-use, optimize this for your requirement. Its a quick and dirty solution, feel free to fix it..

strtok_r causing "assignment makes pointer from integer without a cast"

I'm attempting to tokenize a String in C and save the tokens into multiple variables using strtok_r. As far as I can tell, I'm using it exactly as documented:
char *saveptr;
char *ticketuser = strtok_r(request, ":", &saveptr);
char *ticketservice = strtok_r(NULL, ":", &saveptr);
char *ticketkey = strtok_r(NULL, ":", &saveptr);
//And so on...
Where 'request' is a String of colon-delimited tokens. When I try to compile, I get "assignment makes pointer from integer without a cast" on each line where I assign one of the Strings. Since strtok_r is supposed to return a char*, I can't see what the issue is.
EDIT: Here's ALL my code:
#include <stdio.h>
char *add( char *request ) {
char *name = "add";
char *secret = "secret1";
char *failcode = "0:add:0";
char returncode[80];
char *saveptr;
char *username = strtok_r(request, ":", &saveptr);
char *servicename = strtok_r(NULL, ":", &saveptr);
int parameter1 = atoi(strtok_r(NULL, ":", &saveptr));
int parameter2 = atoi(strtok_r(NULL, ":", &saveptr));
int ticketlead1 = atoi(strtok_r(NULL, ":", &saveptr));
char *ticketuser = strtok_r(NULL, ":", &saveptr);
char *ticketservice = strtok_r(NULL, ":", &saveptr);
char *ticketkey = strtok_r(NULL, ":", &saveptr);
//Catch any issues with the request
if (strcmp(username,ticketuser) != 0){
printf("username did not match ticket username\n");
return failcode;
}//if
else if (strcmp(servicename,ticketservice) != 0){
printf("service name did not match ticket service name\n");
return failcode;
}//else if
else if (strcmp(secret,ticketkey) != 0){
printf("secret key did not match ticket secret key\n");
return failcode;
}//else if
//request was good, return value
else{
int val = parameter1 + parameter2;
sprintf(returncode, "1:add:%d", val);
return returncode;
}//else
}//add
int main( int argc, char **argv ) {
char *returned;
char *req = "user:serv:5:8:1:user:serv:secret1";
returned = add(req);
printf(returned);
printf("\n");
return 1;
}//main
Answer was found in comments: I was missing #include <string.h> at the top of the file.
EDIT: I should add that there were other issues besides the one mentioned above. Firstly, saveptr should be initialized to null. Secondly, as BLUEPIXY pointed out, returncode[] was a local variable. Replaced its definition with char *returncode = malloc ( . . . );
This can be removed by using "string.h" header file in C

Resources