Thread: Need suggestions on elegant use of string and stdlib libraries.

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    182

    Need suggestions on elegant use of string and stdlib libraries.

    I have the following program. Yes, I know it's incomplete and the atoi function fails. I was hoping to get a little direction with that part of the program.

    The question at hand is found in the code as well. What is an elegant way to deal with the parenthesis around the area code? I could tokenize the area code with ")" as the delimiter and offset the pointer by 1 but I feel like there has to be a better way to do it with the libraries at hand( ctype is available to me as well ).

    Code:
    /*
    Write a program that inputs a telephone number as a string in the form
    (555) 555-5555.  The program should use function strtok to extract the area 
    code as a token, the first three digits of the phone number as a token and the 
    last four digits of the phone number as a token.  The seven digits of the phone
    number should be concatenated into one string.  The program should convert the
    area-code string to int and convert the phone number string to long.  Both the 
    area code and the phone number should be printed.
    */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main()
    {
      char phoneNum[ 15 ] = "(404) 993-2241";
      char *areaCode;
      char *mainOne;
      char *mainTwo;
    
      //Set '\0' after area code
      strtok( phoneNum, " " );
      //Set '\0' after first three digits of the number
      strtok( NULL, "-" );
    
      areaCode = phoneNum;
      mainOne = &phoneNum[ 6 ];
      mainTwo = &phoneNum[ 11 ];
    
      // What is an elegant way to deal with the "( )" in the area code?
      int areaCodeAlpha = atoi( areaCode );
      printf( "&#37;d\n", areaCodeAlpha );
    
      return 0;
    }

  2. #2
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    strtoke returns a pointer to the first character of the part of the string that was delimited by '\0'.
    The elegant way is to use that pointer.
    And as ( and ) are concerend, the elegant way is strchr, and strrchr.
    Code:
    char *c;
    c = strchr(yourString, '(');
    yourString = c;
    c = strrchr(yourString, ')');
    *c = '\0';
    yourString should now not have any left and right parentheses.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    182
    That is elegant, thanks.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    strtok can take multiple delimiters.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
       char phoneNum[] = "(404) 993-2241";
       char *str = phoneNum;
       char *token;
       while ( (token = strtok ( str, " ()-" )) )
       {
          puts(token);
          str = 0;
       }
       return 0;
    }
    
    /* my output
    404
    993
    2241
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    182
    Nice. Would that be considered good coding or is it more of a hack?

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    58
    It's not good coding if you only want the format "(ddd) ddd-dddd". strtok allows stuff like "-ddddd-d(ddd)". I don't think strtok is the best function for an exact format. sscanf would work better.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char input[] = "(404) 993-2241";
        char area[4];
        char phone[8];
    
        sscanf(input, "(%3s) %3s-%4s", area, phone, &phone[3]);
        printf("Area code: %d\nPhone Number: %ld\n",
            atoi(area), strtol(phone, NULL, 0));
    
        return 0;
    }

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    But if you REALLY want to verify a telephone number, it's probably better to write a piece of code that checks that EACH portion is entirely correct, with the right number of digits, separators in the right place etc. As a side-effect, it may split the number into areacode and phone number. For REAL checking, you should also consider checking that the area code is valid [I beleive there is a simple method by checking that the second digit is a 0 or a 1, but I could have that wrong].

    Edit: At least the task is easier with US phone numbers than with many european countries, where phone numbers vary in length depending on the area code, and sometimes even within an area [based on the first digit after the area code, in general]. I wrote a verifier for Swedish telephone numbers once.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    It comes to a point when the phrase Regular Expressions might be a good hint towards a good solution, if the input is to be 100&#37; verified.
    Code:
    #include <regex.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
            /* Regular expression to match a US phone number */
            char phonePattern[] = "[(]([0-9]{3})[)] ([0-9]{3})-([0-9]{4})";
            char testS[] = "For more information call (345) 123-4567.";
            regmatch_t *found;
            regex_t regx;
    
            /* Compile the expression in phonePattern to a regex_t */
            regcomp(&regx, phonePattern, REG_EXTENDED);
    
            /* Allocate memory for the bracketed parts of the expression */
            found = malloc( (regx.re_nsub+1) * sizeof(*found) );
            if( regexec(&regx, testS, regx.re_nsub + 1, found, 0) == 0 )
            {
                    int i;
                    /* At found[0] the indices for the entire match are stored 
                     * so, if we don't need it we better start of found[1] 
                     */
                    for(i = 1; i <= regx.re_nsub; i++)
                    {
                            printf("Piece of phone #%d: <", i);
                            fwrite(testS+found[i].rm_so, 1, found[i].rm_eo - found[i].rm_so, stdout);
                            printf(">\n");
                    }
            }
            free(found);
    
            return 0;
    }
    The non standard POSIX compliant <regex.h> header usually comes with a typical installation of gcc.
    For a Regular Expression library that is free and ported for Windows, one can always get it from:
    http://www.pcre.org/
    Last edited by xuftugulus; 03-09-2008 at 01:34 PM.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    #include <regex.h>
    For nonstandard stuff, could you please mention the additional things that are necessary to the code work?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    182
    Thanks guys. I understand what I'm working with is far from complete. Structured input and output is the next chapter I'm doing, I'll make sure to keep this information in mind.

Popular pages Recent additions subscribe to a feed