Thread: Different way of doing things

Hybrid View

Previous Post Previous Post   Next Post Next Post
  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
    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.*

  11. #11
    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.

  12. #12
    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.

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