How to pass this string into a linked list ?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • (2b|!2b)==?

    How to pass this string into a linked list ?

    I am expecting a string of this format:

    "id1:param1,par am2;id2:param1, param2,param3;i d"

    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_) ?
  • Salt_Peter

    #2
    Re: How to pass this string into a linked list ?

    On Nov 7, 2:24 am, "(2b|!2b)== ?" <void-s...@ursa-major.comwrote:
    I am expecting a string of this format:
    >
    "id1:param1,par am2;id2:param1, param2,param3;i d"
    >
    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,par am2;id2:param1, param2,param3;i d"
    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,par am2;id2:param1, param2,param3;i d3:param1"

    Comment

    • Maxim Yegorushkin

      #3
      Re: How to pass this string into a linked list ?

      On Nov 7, 7:24 am, "(2b|!2b)== ?" <void-s...@ursa-major.comwrote:
      I am expecting a string of this format:
      >
      "id1:param1,par am2;id2:param1, param2,param3;i d"
      >
      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(si zeof(mst));
      if(!next)
      return mst_destroy(hea d);
      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(hea d);
      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(&inpu t);
      if(*input)
      printf("<choked at postion %d", (int)(input - *i));
      mst_print(stdou t, head);
      mst_destroy(hea d);
      printf("\n");
      }
      }

      Output:
      parsing '':
      parsing '1': 1;
      parsing '1:1.0': 1:1.000000;
      parsing '1:1.0,2.0': 1:1.000000,2.00 0000;
      parsing '1:1.0,2.0;2:11 .0,22.0;':
      1:1.000000,2.00 0000;2:11.00000 0,22.000000;
      parsing '1:1.0,2.0;2:11 .0,22.0;qwerty' : <choked at postion 22>
      1:1.000000,2.00 0000;2:11.00000 0,22.000000;

      --
      Max

      Comment

      • (2b|!2b)==?

        #4
        Re: How to pass this string into a linked list ?

        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,pa ram2;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(si zeof(mst));
        if(!next)
        return mst_destroy(hea d);
        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(hea d);
        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(&inpu t);
        if(*input)
        printf("<choked at postion %d", (int)(input - *i));
        mst_print(stdou t, head);
        mst_destroy(hea d);
        printf("\n");
        }
        }
        >
        Output:
        parsing '':
        parsing '1': 1;
        parsing '1:1.0': 1:1.000000;
        parsing '1:1.0,2.0': 1:1.000000,2.00 0000;
        parsing '1:1.0,2.0;2:11 .0,22.0;':
        1:1.000000,2.00 0000;2:11.00000 0,22.000000;
        parsing '1:1.0,2.0;2:11 .0,22.0;qwerty' : <choked at postion 22>
        1:1.000000,2.00 0000;2:11.00000 0,22.000000;
        >
        --
        Max
        Thanks Maxim. This is exactly what I needed.

        Comment

        • (2b|!2b)==?

          #5
          Re: How to pass this string into a linked list ?

          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.

          Comment

          • Maxim Yegorushkin

            #6
            Re: How to pass this string into a linked list ?

            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

            Comment

            • eiji.anonremail@googlemail.com

              #7
              Re: How to pass this string into a linked list ?

              I am expecting a string of this format:
              >
              "id1:param1,par am2;id2:param1, param2,param3;i d"
              >
              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

              Comment

              Working...