Finding a string inside string

Discussion in 'C Programming' started by arnuld, Nov 23, 2010.

  1. arnuld

    arnuld Guest

    Program works fine. I know there are improvements left to be done but
    they unidentified by as of now. Help will be appreciated as usual :).
    2nd, any strange values that can crash this program and how to avoid them.


    /* A program to save input. Input is a character string of key=value
    pairs separated by a separator. e.g "name=clc,messages=100".
    * We will write a program which will save value when provided with a
    belonging key.
    *
    * VERSION 0.0
    */

    #include <stdio.h>
    #include <string.h>


    enum {
    SIZE_VALUE = 20
    };


    int get_value_using_key(const char* s, const char* k, const int lenk,
    char* v, const int lenv);

    int main(void)
    {
    const char* arr = "group=,messages=";
    const char* key = "group";

    char value[SIZE_VALUE+1] = {0};
    int ret;



    printf("input: %s\n", arr);
    ret = get_value_using_key(arr, key, strlen(key), value, SIZE_VALUE);

    if(ret >= 0)
    {
    printf("%s: %s\n", key, value);
    }
    else
    {
    printf("Error finding values\n");
    }

    printf("ret: %d\n", ret);

    return 0;
    }


    /* if input (fist argument) is not a character string then this program
    will Segfault. Do not know how to avoid this :( */
    int get_value_using_key(const char* s, const char* k, const int lenk,
    char* v, const int lenv)
    {
    int idx;
    char* p;
    int bool_small_string = 0;
    const char separator = ',';

    p = strstr(s, k);

    if(NULL == p)
    {
    printf("No match found\n");
    return -1;
    }

    p = p + lenk + 1; /* +1 for equal character*/

    printf("*p = %c\n", *p);

    for(idx = 0; idx != lenv; ++idx)
    {
    if('\0' == *p || separator == *p)
    {
    bool_small_string = 1;
    break;
    }

    *v++ = *p++;
    }

    if(bool_small_string)
    {
    printf("Input size is lesser than recommended. This is fine\n");
    }
    else if(('\0'== *p || separator == *p) && lenv == idx)
    {
    printf("Input Size exhausted completely\n");
    }
    else
    {
    printf("*p: %c, idx: %d, lenv: %d\n", *p, idx, lenv);
    printf("*ERROR - size of input exceeded the allowed limit\n");
    return -1;
    }

    return idx; /* return number of characters read */
    }

    ================= OUTPUT ====================
    [arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra save-values.c
    [arnuld@dune programs]$ ./a.out
    input: group=clc,messages=
    *p = c
    Input size is lesser than recommended. This is fine
    group: clc
    ret: 3
    [arnuld@dune programs]$


    --
    www.lispmachine.wordpress.com
     
    arnuld, Nov 23, 2010
    #1
    1. Advertising

  2. On 23 Nov 2010 05:00:38 GMT, arnuld <> wrote:

    >Program works fine. I know there are improvements left to be done but
    >they unidentified by as of now. Help will be appreciated as usual :).
    >2nd, any strange values that can crash this program and how to avoid them.
    >
    >
    >/* A program to save input. Input is a character string of key=value
    >pairs separated by a separator. e.g "name=clc,messages=100".
    > * We will write a program which will save value when provided with a
    >belonging key.
    > *
    > * VERSION 0.0
    > */
    >
    >#include <stdio.h>
    >#include <string.h>
    >
    >
    >enum {
    > SIZE_VALUE = 20
    >};
    >
    >
    >int get_value_using_key(const char* s, const char* k, const int lenk,
    >char* v, const int lenv);
    >
    >int main(void)
    >{
    > const char* arr = "group=,messages=";
    > const char* key = "group";
    >
    > char value[SIZE_VALUE+1] = {0};


    Since value is initialized only once (when it is created), you cannot
    use it as the output array for multiple calls to your function unless
    the values extracted never decrease in length.

    > int ret;
    >
    >
    >
    > printf("input: %s\n", arr);
    > ret = get_value_using_key(arr, key, strlen(key), value, SIZE_VALUE);
    >
    > if(ret >= 0)
    > {
    > printf("%s: %s\n", key, value);
    > }
    > else
    > {
    > printf("Error finding values\n");
    > }
    >
    > printf("ret: %d\n", ret);
    >
    > return 0;
    >}
    >
    >
    >/* if input (fist argument) is not a character string then this program
    >will Segfault. Do not know how to avoid this :( */


    Many of the str** functions suffer from the same "problem". You
    simply document the interface for your function that both s and k must
    point to strings.

    >int get_value_using_key(const char* s, const char* k, const int lenk,
    >char* v, const int lenv)
    >{
    > int idx;
    > char* p;
    > int bool_small_string = 0;
    > const char separator = ',';
    >
    > p = strstr(s, k);
    >
    > if(NULL == p)
    > {
    > printf("No match found\n");
    > return -1;
    > }
    >
    > p = p + lenk + 1; /* +1 for equal character*/


    By not including the '=' in the comparison, you have allowed the
    function to accept a source like "grouping=" and incorrectly assume
    the '=' followed the 'p'.

    >
    > printf("*p = %c\n", *p);


    What makes the first character after the '=' worth printing?
    Especially since you print it again later.

    >
    > for(idx = 0; idx != lenv; ++idx)
    > {
    > if('\0' == *p || separator == *p)
    > {
    > bool_small_string = 1;
    > break;
    > }
    >
    > *v++ = *p++;
    > }
    >
    > if(bool_small_string)
    > {
    > printf("Input size is lesser than recommended. This is fine\n");
    > }
    > else if(('\0'== *p || separator == *p) && lenv == idx)
    > {
    > printf("Input Size exhausted completely\n");


    The actual thing exhausted is the array value in main. I have no idea
    why this would be called input. It looks more like output.

    > }
    > else
    > {
    > printf("*p: %c, idx: %d, lenv: %d\n", *p, idx, lenv);
    > printf("*ERROR - size of input exceeded the allowed limit\n");
    > return -1;
    > }
    >
    > return idx; /* return number of characters read */
    >}
    >
    >================= OUTPUT ====================
    >[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra save-values.c
    >[arnuld@dune programs]$ ./a.out
    >input: group=clc,messages=


    There is no text "clc" in arr in main. What program did this output
    come from? Not from the one you showed above.

    >*p = c
    >Input size is lesser than recommended. This is fine
    >group: clc
    >ret: 3
    >[arnuld@dune programs]$


    --
    Remove del for email
     
    Barry Schwarz, Nov 23, 2010
    #2
    1. Advertising

  3. arnuld

    arnuld Guest

    > On Mon, 22 Nov 2010 22:06:45 -0800, Barry Schwarz wrote:
    >> On 23 Nov 2010 05:00:38 GMT, arnuld <> wrote:


    > Since value is initialized only once (when it is created), you cannot
    > use it as the output array for multiple calls to your function unless
    > the values extracted never decrease in length.


    Thanks. I have taken care of this in the program I am writing (which
    sadly is proprietary :( ).



    > Many of the str** functions suffer from the same "problem". You
    > simply document the interface for your function that both s and k must
    > point to strings.


    This is where I think C is dangerous.



    >> p = p + lenk + 1; /* +1 for equal character*/


    > By not including the '=' in the comparison, you have allowed the
    > function to accept a source like "grouping=" and incorrectly assume the
    > '=' followed the 'p'.


    corrected.



    >> printf("*p = %c\n", *p);

    >
    > What makes the first character after the '=' worth printing? Especially
    > since you print it again later.


    Oh.. my bad... its left from those debugging calls to printf().




    >> else if(('\0'== *p || separator == *p) && lenv == idx)
    >> {
    >> printf("Input Size exhausted completely\n");


    > The actual thing exhausted is the array value in main. I have no idea
    > why this would be called input. It looks more like output.


    That is really funny thing I did.


    >>gcc -ansi -pedantic -Wall -Wextra save-values.c [arnuld@dune programs]$
    >>./a.out
    >>input: group=clc,messages=

    >
    > There is no text "clc" in arr in main. What program did this output
    > come from? Not from the one you showed above.


    too many urxvt tabs cause confusion.





    --
    www.lispmachine.wordpress.com
     
    arnuld, Nov 23, 2010
    #3
  4. arnuld

    Dann Corbit Guest

    Dann Corbit, Nov 23, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Daves
    Replies:
    0
    Views:
    2,481
    Daves
    Jun 14, 2005
  2. =?Utf-8?B?U3JpZGhhcg==?=

    finding the control types inside a datagrid

    =?Utf-8?B?U3JpZGhhcg==?=, Dec 29, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    547
    =?Utf-8?B?U3JpZGhhcg==?=
    Dec 29, 2005
  3. Jim in Arizona

    Finding a control inside an <itemtemplate>

    Jim in Arizona, Jan 4, 2007, in forum: ASP .Net
    Replies:
    5
    Views:
    388
    Eliyahu Goldin
    Jan 4, 2007
  4. Brad Baker
    Replies:
    7
    Views:
    490
    Brad Baker
    May 28, 2007
  5. arnuld

    Finding a word inside a string

    arnuld, Sep 24, 2010, in forum: C Programming
    Replies:
    35
    Views:
    1,056
    Barry Schwarz
    Oct 7, 2010
Loading...

Share This Page