Thread: Different way of doing things

  1. #1
    Registered User
    Join Date
    May 2005
    Posts
    11

    Different way of doing things

    I began working out a problem and ran into a brain freeze and I eventually solved it, but it doesn't look like what I originially had in mind. The results are perfect, I will keep the code, but for some reason, I thought the code would look slightly different...but only in the part where I take the value of 500.

    Is there a "better" way of doing this? I'm sure it's obvious, but basically I want to separate the values city and id from the string, "new york (500)".


    Appreciate all the help!

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    
    {
    
    
            int offset; 
         	char *position; 
         	char *str = "New York (500)";
         	char *search_str = "(" ;
    	char city[110];
    	char id[110]; // this represents the 500 number
                    int IDSIZE = 3;
    
    
                   position = (char *)strstr(str, search_str);
    
                   offset = (int)(position - str);
    
                   position = (char *)strncpy(city, str, offset);
    		
                   printf("String is %s , Offset = %d , City is: %s", str, 
                   offset, city);
    		       
                   str = (str + (offset + 1));
                   
                   position = (char *)strncpy(id, str, IDSIZE);		           
                   printf("Branch id is:  %s", id);
                       
                   return 0;
    
    }

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Well, you could do it like this:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define IDSIZE 3
    
    int main(void)
    {
      char *str = "New York (500)";
      char city[110];
      char id[IDSIZE + 1];
      char *p;
    
      p = strchr(str, '(');
    
      strncpy(city, str, p - str);
      city[p - str] = '\0';
    
      strncpy(id, p + 1, IDSIZE);
      id[IDSIZE] = '\0';
    
      printf("City: %s, Branch ID: %s\n", city, id);
    
      return 0;
    }
    itsme@itsme:~/C$ ./cityid
    City: New York , Branch ID: 500
    But it makes some dangerous assumptions and the city string has a trailing space. It also isn't very strict on what the original string needs to look like. It limits the ID to 3 digits and doesn't even care if the string is in the format "city (id)".

    This one is a lot better I think:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
      char *str = "New York (500)";
      char city[110];
      char id[110];
      char *p, *q;
      int tocopy;
    
      if(!(p = strchr(str, '(')))
      {
        puts("String syntax validation failed -- Expected '('");
        return 1;
      }
    
      // Get rid of space(s) between city name and ID field
      for(q = p - 1;q >= str && *q == ' ';--q)
        ;
      q++;
    
      // Don't forget bounds checking
      tocopy = q - str >= sizeof(city) ? sizeof(city) : q - str;
      strncpy(city, str, tocopy);
      city[tocopy] = '\0';
    
      for(++p, q = id;q - id < sizeof(id) && *p != ')';++p, ++q)
        *q = *p;
      *q = '\0';
    
      if(*p != ')')
      {
        puts("String syntax validation failed -- Expected ')'");
        return 1;
      }
    
      printf("City: %s, Branch ID: %s\n", city, id);
    
      return 0;
    }
    itsme@itsme:~/C$ ./cityid2
    City: New York, Branch ID: 500
    If you understand what you're doing, you're not learning anything.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Yet another possible way to do this.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
       static const char *line[] = {"New York (500)","Los Angeles(400)"};
       char city[32];
       int id;
       size_t i;
       for ( i = 0; i < sizeof line / sizeof *line; ++i )
       {
          if ( sscanf(line[i], "%31[^(](%d)", city, &id) == 2 )
          {
             size_t last = strlen(city) - 1;
             if ( city[last] == ' ' )
             {
                city[last] = '\0';
             }
             printf("city = \"%s\", id = %d\n", city, id);
          }
       }
       return 0;
    }
    
    /* my output
    city = "New York", id = 500
    city = "Los Angeles", id = 400
    */
    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.*

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    And another (well, not really).
    Code:
    #include <stdio.h>
    
    int main(void)
    {
       static const char *line[] = {"New York  (500)","Los Angeles(400)","Dullsville (300)"};
       char city[32];
       int id, last;
       size_t i;
       for ( i = 0; i < sizeof line / sizeof *line; ++i )
       {
          if ( sscanf(line[i], "%31[^(]%n(%d)", city, &last, &id) == 2 )
          {
             while ( city[--last] == ' ' )
             {
                city[last] = '\0';
             }
             printf("city = \"%s\", id = %d\n", city, id);
          }
       }
       return 0;
    }

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    [edit=much later]The following is not true.

    It's subtle, but there is UB on this line.
    Code:
    if ( sscanf(line[i], "%31[^(]%n(%d)", city, &last, &id) == 2 )
    [edit2]C99 has the following sentence in its description of the n directive.
    If the conversion specification includes an assignment suppressing character or a field width, the behavior is undefined.
    And apparently C89 does not have that same sentence.
    Last edited by Dave_Sinkula; 07-29-2005 at 08:12 PM.
    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.*

  6. #6
    Registered User
    Join Date
    May 2005
    Posts
    11
    It'sMe, Dave, Anonymouse:

    Thanks a bunch, gentlemen (and ladies if I've made a sexist assumption)! I appreciate it. As I said, I'm just picking up the language, and it helps to see things done differently. I really do appreciate it!

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >C99 has the following sentence in its description of the n directive.
    Okay, that doesn't explain your statement about undefined behavior though. %n is a valid conversion specification.
    My best code is written with the delete key.

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Prelude
    >C99 has the following sentence in its description of the n directive.
    Okay, that doesn't explain your statement about undefined behavior though. %n is a valid conversion specification.
    Hm. Perhaps I've been reading that wrong. I read it as, "If you've got an assignment suppression or a field width" -- in this case the field width for the string -- "and you also use the %n to determine the number of characters consumed, then the behavior is undefined". Should it be read, "You can't do "%*n" or "%5n"?"
    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.*

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Should it be read, "You can't do "%*n" or "%5n"?"
    Yes. The other interpretation is unnecessarily restrictive.
    My best code is written with the delete key.

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I guess the question is: where is the assignment suppressing character or field width? Because I don't see either, but then again, my eyes aren't that good.

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >where is the assignment suppressing character or field width?
    That's the misinterpretation. Dave was looking at the field width here:
    Code:
    sscanf(line[i], "%31[^(]%n(%d)", city, &last, &id)
    But the standard only talks about undefined behavior when there's a field width here:
    Code:
    sscanf(line[i], "%31[^(]%n(%d)", city, &last, &id)
    My best code is written with the delete key.

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Prelude
    >Should it be read, "You can't do "%*n" or "%5n"?"
    Yes. The other interpretation is unnecessarily restrictive.
    My bad. And cool -- I liked it that way better!

    Whatever day I had been Groups Googling, I thought it was saying that if you are discarding characters, or limiting the field width, that counting them was an issue. Anyways, thanks for the clarification.
    Last edited by Dave_Sinkula; 07-29-2005 at 08:02 PM. Reason: Removed mention of link to code in need of changing.
    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.*

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I thought it was saying that if you are discarding characters, or
    >limiting the field width, that counting them was an issue.
    Discarding characters would be a minor issue, but assignment suppression doesn't discard, it simply fails to assign a matched specification with a variable. Limiting the field width also wouldn't cause a problem because in the end that doesn't affect the character count, it just limits the number of characters from the stream that can be counted.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Suggestions for things to study
    By Mastadex in forum Windows Programming
    Replies: 5
    Last Post: 08-18-2008, 09:23 AM
  2. Plants that eat things
    By StinkyRyan in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 07-05-2004, 03:41 PM
  3. How are things looking
    By cyberCLoWn in forum C++ Programming
    Replies: 8
    Last Post: 01-15-2004, 02:53 PM
  4. Selecting things on the canvas
    By Barjor in forum Windows Programming
    Replies: 0
    Last Post: 08-30-2001, 02:10 PM
  5. Help with these three things...
    By face_master in forum C++ Programming
    Replies: 2
    Last Post: 08-26-2001, 07:05 AM