By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,434 Members | 1,854 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,434 IT Pros & Developers. It's quick & easy.

How to pass this string into a linked list ?

P: n/a
I am expecting a string of this format:

"id1:param1,param2;id2:param1,param2,param3;id "

The tokens are seperated by semicolon ";"

However each token is really a struct of the following format:

struct mst_
{
int id;
struct params_* parms ; //0 or more
struct mst_ *next ;
};
where:

struct params_
{
double argval;
struct params_ * next;
};
Could anyone suggest an elegant way to parse strings with the specified
formatting into a linked list (struct mst_) ?
Nov 7 '08 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Nov 7, 2:24 am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
I am expecting a string of this format:

"id1:param1,param2;id2:param1,param2,param3;id "

The tokens are seperated by semicolon ";"

However each token is really a struct of the following format:

struct mst_
{
int id;
struct params_* parms ; //0 or more
struct mst_ *next ;

};

where:

struct params_
{
double argval;
struct params_ * next;

};

Could anyone suggest an elegant way to parse strings with the specified
formatting into a linked list (struct mst_) ?
Not quite sure i understood the string format supplied.
"id1:param1,param2;id2:param1,param2,param3;id "
as in?
"1:1.1,2.2;2:3.3,4.4,5.5;id"

i see the integer id's and the double argval's
but whats id at the end here?
or did you mean
"id1:param1,param2;id2:param1,param2,param3;id3:pa ram1"

Nov 7 '08 #2

P: n/a
On Nov 7, 7:24*am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
I am expecting a string of this format:

"id1:param1,param2;id2:param1,param2,param3;id "

The tokens are seperated by semicolon ";"

However each token is really a struct of the following format:

struct mst_
{
* * int id;
* * struct params_* parms ; //0 or more
* * struct mst_ *next ;

};

where:

struct params_
{
* * double argval;
* * struct params_ * next;

};

Could anyone suggest an elegant way to parse strings with the specified
formatting into a linked list (struct mst_) ?
Here is one way to do so:

#include <stdio.h>
#include <malloc.h>

struct params
{
double arg;
params* next;
};

struct mst
{
int id;
params* params;
mst* next;
};

void mst_print(FILE* file, mst* head)
{
for(;head; head = head->next)
{
fprintf(file, "%d", head->id);
if(head->params)
{
char sep = ':';
for(params* param = head->params; param; param = param-
>next)
{
fprintf(file, "%c%f", sep, param->arg);
sep = ',';
}
}
fprintf(file, ";");
}
}

mst* mst_destroy(mst* head)
{
while(head)
{
mst* node = head;
head = head->next;
for(params* node_params = node->params; node_params;)
{
params* p = node_params;
node_params = node_params->next;
free(p);
}
free(node);
}
return NULL;
}

mst* mst_parse(char const** input)
{
mst *head = NULL, **tail = &head;
while(*input)
{
// parse id
int id, eaten = 0;
sscanf(*input, "%d%n", &id, &eaten);
if(!eaten)
return head;
*input += eaten;
// allocate the next mst node and initialise it
mst* next = (mst*)malloc(sizeof(mst));
if(!next)
return mst_destroy(head);
next->id = id;
next->params = NULL;
next->next = NULL;
// append the node to the list
*tail = next;
tail = &next->next;
// parse params
if(':' == **input)
{
params** tail_params = &next->params;
++*input;
for(;;)
{
double arg;
eaten = 0;
sscanf(*input, "%lf%n", &arg, &eaten);
if(!eaten)
return head;
*input += eaten;
// allocate the next params node and initialise it
params* next_params =
(params*)malloc(sizeof(params));
if(!next_params)
return mst_destroy(head);
next_params->arg = arg;
next_params->next = NULL;
// append to the params list
*tail_params = next_params;
tail_params = &next_params->next;
// see if there are more params
if(',' != **input)
break;
++*input;
}
}
// see if there are more ids
if(';' != **input)
break;
++*input;
}
return head;
}

char const* inputs[] = {
""
, "1"
, "1:1.0"
, "1:1.0,2.0"
, "1:1.0,2.0;2:11.0,22.0;"
, "1:1.0,2.0;2:11.0,22.0;qwerty"
, NULL
};

int main()
{
for(char const** i = inputs; *i; ++i)
{
char const* input = *i;
printf("parsing '%s': ", input);
mst* head = mst_parse(&input);
if(*input)
printf("<choked at postion %d", (int)(input - *i));
mst_print(stdout, head);
mst_destroy(head);
printf("\n");
}
}

Output:
parsing '':
parsing '1': 1;
parsing '1:1.0': 1:1.000000;
parsing '1:1.0,2.0': 1:1.000000,2.000000;
parsing '1:1.0,2.0;2:11.0,22.0;':
1:1.000000,2.000000;2:11.000000,22.000000;
parsing '1:1.0,2.0;2:11.0,22.0;qwerty': <choked at postion 22>
1:1.000000,2.000000;2:11.000000,22.000000;

--
Max
Nov 7 '08 #3

P: n/a
Maxim Yegorushkin wrote:
On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
>I am expecting a string of this format:

"id1:param1,param2;id2:param1,param2,param3;id "

The tokens are seperated by semicolon ";"

However each token is really a struct of the following format:

struct mst_
{
int id;
struct params_* parms ; //0 or more
struct mst_ *next ;

};

where:

struct params_
{
double argval;
struct params_ * next;

};

Could anyone suggest an elegant way to parse strings with the specified
formatting into a linked list (struct mst_) ?

Here is one way to do so:

#include <stdio.h>
#include <malloc.h>

struct params
{
double arg;
params* next;
};

struct mst
{
int id;
params* params;
mst* next;
};

void mst_print(FILE* file, mst* head)
{
for(;head; head = head->next)
{
fprintf(file, "%d", head->id);
if(head->params)
{
char sep = ':';
for(params* param = head->params; param; param = param-
>next)
{
fprintf(file, "%c%f", sep, param->arg);
sep = ',';
}
}
fprintf(file, ";");
}
}

mst* mst_destroy(mst* head)
{
while(head)
{
mst* node = head;
head = head->next;
for(params* node_params = node->params; node_params;)
{
params* p = node_params;
node_params = node_params->next;
free(p);
}
free(node);
}
return NULL;
}

mst* mst_parse(char const** input)
{
mst *head = NULL, **tail = &head;
while(*input)
{
// parse id
int id, eaten = 0;
sscanf(*input, "%d%n", &id, &eaten);
if(!eaten)
return head;
*input += eaten;
// allocate the next mst node and initialise it
mst* next = (mst*)malloc(sizeof(mst));
if(!next)
return mst_destroy(head);
next->id = id;
next->params = NULL;
next->next = NULL;
// append the node to the list
*tail = next;
tail = &next->next;
// parse params
if(':' == **input)
{
params** tail_params = &next->params;
++*input;
for(;;)
{
double arg;
eaten = 0;
sscanf(*input, "%lf%n", &arg, &eaten);
if(!eaten)
return head;
*input += eaten;
// allocate the next params node and initialise it
params* next_params =
(params*)malloc(sizeof(params));
if(!next_params)
return mst_destroy(head);
next_params->arg = arg;
next_params->next = NULL;
// append to the params list
*tail_params = next_params;
tail_params = &next_params->next;
// see if there are more params
if(',' != **input)
break;
++*input;
}
}
// see if there are more ids
if(';' != **input)
break;
++*input;
}
return head;
}

char const* inputs[] = {
""
, "1"
, "1:1.0"
, "1:1.0,2.0"
, "1:1.0,2.0;2:11.0,22.0;"
, "1:1.0,2.0;2:11.0,22.0;qwerty"
, NULL
};

int main()
{
for(char const** i = inputs; *i; ++i)
{
char const* input = *i;
printf("parsing '%s': ", input);
mst* head = mst_parse(&input);
if(*input)
printf("<choked at postion %d", (int)(input - *i));
mst_print(stdout, head);
mst_destroy(head);
printf("\n");
}
}

Output:
parsing '':
parsing '1': 1;
parsing '1:1.0': 1:1.000000;
parsing '1:1.0,2.0': 1:1.000000,2.000000;
parsing '1:1.0,2.0;2:11.0,22.0;':
1:1.000000,2.000000;2:11.000000,22.000000;
parsing '1:1.0,2.0;2:11.0,22.0;qwerty': <choked at postion 22>
1:1.000000,2.000000;2:11.000000,22.000000;

--
Max
Thanks Maxim. This is exactly what I needed.
Nov 7 '08 #4

P: n/a
Maxim Yegorushkin wrote:
On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
>I am expecting a string of this format:
<snip></snip>

Maxim: incidentally, there was a typo in the subject. I had meant to
type 'parse' (instead of pass) - but you understood anyway and provided
a useful solution to the question - many tx.
Nov 7 '08 #5

P: n/a
On Nov 7, 10:33*am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
Maxim Yegorushkin wrote:
On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.comwrote:
I am expecting a string of this format:

<snip></snip>

Maxim: incidentally, there was a typo in the subject. I had meant to
type 'parse' (instead of pass) - but you understood anyway and provided
a useful solution to the question - many tx.
Ok.

And there is a typo in mst_parse:

while(*input)

Should be:

while(**input)

;)

--
Max

Nov 7 '08 #6

P: n/a
I am expecting a string of this format:

"id1:param1,param2;id2:param1,param2,param3;id "

The tokens are seperated by semicolon ";"
Just as an reminder:

In some countries the decimal point in 456.23 is replaced with ','
like in 456,23.
Some languages, apps and locals do regognize that.
So just think about if ',' is a good seperator at all.

My 2 cents.
eiji
Nov 7 '08 #7

This discussion thread is closed

Replies have been disabled for this discussion.