views:

55

answers:

2

Is there a better/easier way to create a \w+ string from an existing string?

 char *FixName(char *name)
 {
     char *ptr, tmp;
     char *new = malloc(strlen(name)+1);
     sprintf(new, "str_");
     for (ptr = name + 4; *ptr; ptr++)
     {
         if ((*ptr >= '0' && *ptr <= '9') ||
             (*ptr >= 'A' && *ptr <= 'Z') ||
             (*ptr >= 'a' && *ptr <= 'z') ||
             *ptr == '_')
         {
             tmp = *(ptr+1);
             *(ptr+1) = '\0';
             strcat(new, ptr);
             *(ptr+1) = tmp;
         }
     }
     free(name);
     return new;
 }

 // USAGE:
 //char *j = strdup("str_[](1.00)");
 //printf("J: %s\n", j);
 //j = FixName(j);
 //printf("J: %s\n", j);
 //free(j);
 // OUTPUT:
 //J: str_[](1.00)
 //J: str_100

Thanks for comments, new function:

  void FixName(char *name)
  {
      char *ptr;
      unsigned short count = strlen("str_");
      for (ptr = name + count; *ptr; ptr++)
      {
          if ((*ptr >= '0' && *ptr <= '9') ||
              (*ptr >= 'A' && *ptr <= 'Z') ||
              (*ptr >= 'a' && *ptr <= 'z') ||
              *ptr == '_')
          {
              *(name+count) = *ptr;
              count++;
          }
      }
      *(name+count) = '\0';
  }
+5  A: 

One thing you could do to immediately make your code much clearer is to use character literals:

if ((*ptr >= '0' && *ptr <= '9') ||
    (*ptr >= 'A' && *ptr <= 'Z') ||
    (*ptr >= 'a' && *ptr <= 'z') ||
    *ptr == '_')

A better solution is to use isalnum.

if (isalnum(*ptr) || *ptr == '_')

Be aware that different locales may consider different characters to be alphanumeric.

A few more issues with your code:

  • You could work out the size of the string you need before allocating the memory for it, to avoid overallocating.
  • You can build the result without using strcat by keeping a pointer to where you have reached so far.
  • I don't like that call to free inside the function. You can't be sure that the string passed in as a parameter was allocated using malloc.
Mark Byers
+1  A: 

Adding to Mark's answer:

sprintf returns the number of char it wrote. You can make use of this as:

    count = sprintf(new, "str_");
    for (ptr = name + 4; *ptr; ptr++) {

            if ((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'A' && *ptr <= 'Z') ||
                (*ptr >= 'a' && *ptr <= 'z') || *ptr == '_')
            {
                    *(new+count) = *ptr;
                    count++;
            }
    }
    *(new+count) = 0; // terminating null char
codaddict