Thread: Normalizing a string

  1. #1
    Registered User
    Join Date
    Aug 2009
    Posts
    9

    Normalizing a string

    Good time of day, everyone!

    In my program, I have encountered the necessity of normalizing strings so I could pass them to the execvp() method.

    I want my routine to proceed the string in the following way: it must remove all the spaces, tabulations and newline characters that precede and follow the string; if the substring is put in the quotation marks, the method must remove them and leave their content as is. The last character is set to null.

    That means that I want the function to return the same string for all of the following input cases:

    Code:
    ls
    ls		                
       	   ls  
    "ls"
    	"ls"
    If I simply print out the results and their lengths by calling printf(), everything seems all right (they coincide). But the issue is, if I invoke execvp(), it works only for the two first strings (in the second one ls is followed by tabs and spaces) and throws "No such file or directory" for other cases.

    This is just a sketch but nonetheless:

    Code:
    #define TRUE 1
    #define FALSE 0
    
    void set_format(char *str) {
      int i, flag; // flag means we encountered quatation marks
    
      printf("\nBefore formatting\n|%s|\n", str);
    
      for (i = 0, flag = TRUE;
           strchr(" \t\n\"", str[i]) != NULL;
           i++ ) {
        if (str[i]=='\"') {
          flag = FALSE;
          break;
        }    
      }
    
      if (flag) str+=i;
      else str+=i+1;
    
      for (i = strlen(str)-1;
           strchr(" \t\n\"", str[i])!=NULL;
           i-- ) {
        if (str[i]=='\"') {
          if (!flag) break;
          else puts("Invalid input");
        }    
      }
    
      str[i]=(char)NULL;
    
      printf("\nAfter formatting\n|%s|\nSize: %d\n", str, strlen(str));
    
    }
    I'm probably missing something obvious...
    Thanks in advance!
    Last edited by Krusty; 09-08-2009 at 12:34 PM.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I think my approach with this would be to go thru the string once, beginning to end, using switch/case on the value of each character:
    Code:
    int len = strlen(string);
    for (i=0;i<len;i++) {
         switch (string[i]) {
                 case(' '):  remove_char(string,i);
                 case('"'):  remove_char(string,i);
                 default: continue;
    If all you ever want to do is remove the character, so the cases are all the same, then you just need a single long if ( || || ) instead of the switch/case, I guess.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Aug 2009
    Posts
    9
    Thank you for a quick response!

    The problem is that the following input is possible
    Code:
      "  command  "
    And then the routine is supposed to save the substring in between the quitation marks, returning

    Code:
      command
    And catch the case when we have unclosed quatation mark.

    But it's not even the case. What I don't understand is that the function DOES normalize the string, at least this is how printf() makes it seem. I don't understand what's wrong with the strings execvp() doesn't accept.
    Last edited by Krusty; 09-08-2009 at 01:06 PM.

  4. #4
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    Here is a function that trims whitespace off ends of a string. Not the it requires #include <string.h>

    Code:
    void trim_string(char* str)
    {
    	int i = 0;
    	while((str[i] == ' ' || str[i] == '\n' || str[i] == '\r' || str[i] == '\t') && str[i] != '\0') i++;
    	if(str[i] != '\0') {
    		memmove(str, str+i, (strlen(str)+1-i)*sizeof(char));
    		i = strlen(str)-1;
    		while(str[i] == ' ' || str[i] == '\n' || str[i] == '\r' || str[i] == '\t') i--;
    		str[i+1] = '\0';
    	} else {
    		str[0] = '\0';
    	}
    }
    This function keeps whitespace enclosed in non-whitespace characters intact.

    P.S. I thought that "Trim" means do like the function above and "Normalize" means trim and then turn any enclosed whitespace into single spaces, right?

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You can always just pass all this to a shell (/bin/sh, for example) and let it remove the quotes etc properly. For example, you could use system() or exec*() a command like
    Code:
    /bin/sh -c /bin/ls "where"
    I think the shell will do the proper thing in that case.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    How are you calling execvp()? What arguments are you passing it? Can you post that here?

  7. #7
    Registered User
    Join Date
    Aug 2009
    Posts
    9
    MTK, loads of thanks to you for that code! It worked just fine for me, I believe it won't be any problem to add quatations.
    No, you're right, trimming is what I needed, I'm not really good at terminology.

    Quote Originally Posted by dwks View Post
    You can always just pass all this to a shell (/bin/sh, for example) and let it remove the quotes etc properly. For example, you could use system() or exec*() a command like
    Code:
    /bin/sh -c /bin/ls "where"
    I think the shell will do the proper thing in that case.
    Mini-shell is what I'm attempting to write, this is a part of a coveyor processing

    Quote Originally Posted by itCbitC View Post
    How are you calling execvp()? What arguments are you passing it? Can you post that here?
    Seems like the issue was with my routine...

    Thank you, everyone!

  8. #8
    Registered User
    Join Date
    Mar 2009
    Posts
    30
    Have you tried strtok() ?

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    30
    You might use strtok for this


    Code:
    #include <stdio.h>
    #include <string.h>
    #define LENGTH 64
    
    int main()
    {
            char input[LENGTH] ;
            char *ptr ;
    
            printf("Input string: ") ;
            fgets(input,LENGTH,stdin) ;
    
            ptr = strtok(input,"\040\t\n") ;
    
            printf("[%s]\n", ptr) ;
            return 0;
    }
    
    
    /* OUTPUT
    
    [voltron@shiryu3 forum01]$ ./a.out
    Input string: stringOne
    [stringOne]
    [voltron@shiryu3 forum01]$ ./a.out
    Input string:    strongTwo
    [strongTwo]
    [voltron@shiryu3 forum01]$ ./a.out
    Input string:                   stringThree
    [stringThree]
    
    */

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. compare structures
    By lazyme in forum C++ Programming
    Replies: 15
    Last Post: 05-28-2009, 02:40 AM
  2. OOP Question DB Access Wrapper Classes
    By digioz in forum C# Programming
    Replies: 2
    Last Post: 09-07-2008, 04:30 PM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM