[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

How to pass this string into a linked list ?

(2b|!2b)==?

11/7/2008 7:25:00 AM

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_) ?
6 Answers

Salt_Peter

11/7/2008 8:44:00 AM

0

On Nov 7, 2:24 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
> 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:param1"

Maxim Yegorushkin

11/7/2008 10:29:00 AM

0

On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
> 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

(2b|!2b)==?

11/7/2008 10:31:00 AM

0

Maxim Yegorushkin wrote:
> On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
>> 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.

(2b|!2b)==?

11/7/2008 10:34:00 AM

0

Maxim Yegorushkin wrote:
> On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
>> 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.

Maxim Yegorushkin

11/7/2008 10:45:00 AM

0

On Nov 7, 10:33 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
> Maxim Yegorushkin wrote:
> > On Nov 7, 7:24 am, "(2b|!2b)==?" <void-s...@ursa-major.com> wrote:
> >> 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

eiji.anonremail

11/7/2008 10:52:00 AM

0


> 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