Thread: reversing a string

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    21

    reversing a string

    Hi, all--
    I'm writing a program to reverse a string word by word, e.g. "some words" becomes "words some", and I'm having some trouble getting it to ignore the null portion of the array. Here's my code:

    Code:
    int main()
    {
    	char *wordptr[81], s1[81], s2[81];
    	int i = 0;
    	printf("Input: ");
    	fgets(s1, 80, stdin);
    	wordptr[i] = strtok(s1," \n");
    	i++;
    	
    	while(strtok(NULL, " \n") != NULL)
    	{
    		wordptr[i] = strtok(NULL, " \n");
    		i++;
    	}//break string into tokens
    	
    	printf("Reversed: ");
    	
    	for(i = i; i >= 0; i--)
    	{
    		printf("%s ", wordptr[i]);
    	}//print words marked by pointers in wordptr in reverse
    	
    	printf("\n");
    	
    	return 0;
    
    }//main
    And here's the output I'm getting:

    Code:
    teyla:~ quasigreat$ ~quasigreat/a.out
    Input: bibbity boppity boo
    Reversed:  boo bibbity 
    teyla:~ quasigreat$ ~quasigreat/a.out
    Input: birds and bees
    Reversed:  bees birds
    teyla:~ quasigreat$ ~quasigreat/a.out
    Input: now is the time for all good men to come to the aid of their country
    Reversed:  (null) their aid to to good for the now
    I'm not sure why it seems to be skipping every other word. Help is much appreciated.
    Last edited by quasigreat; 05-21-2008 at 07:41 PM. Reason: fixed original issue; now there's a new problem

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by quasigreat
    I'm not sure why it seems to be skipping every other word. Help is much appreciated.
    Because you're calling strtok twice each time through the loop.
    Code:
    while(strtok(NULL, " \n") != NULL)
    {
        wordptr[i] = strtok(NULL, " \n");
        i++;
    }
    Quote Originally Posted by quasigreat
    I'm having some trouble getting it to ignore the null portion of the array.
    I'm guessing you mean this:
    Code:
    Reversed:  (null) their aid to to good for the now
    Just decrement i by one in the initialization step of the for loop:
    Code:
    for(i = i - 1; i >= 0; i--)
    {
        printf("%s ", wordptr[i]);
    }
    Last edited by hk_mp5kpdw; 05-21-2008 at 08:02 PM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    May 2008
    Posts
    21
    OK, thank you, that makes sense. I've changed it back to:

    Code:
    while(wordptr[i] != NULL)
    	{
    		wordptr[i] = strtok(NULL, " \n");
    		i++;
    	}
    And the output is as follows:

    Code:
    teyla:~ quasigreat$ ~quasigreat/a.out
    Input: bees and birds
    Reversed: (null) (null) (null) (null) (null) (null) (null) (null) (null) birds and bees
    How do I keep it from picking up the nulls at the end?

    ETA: Ah, hadn't seen your edit when I replied. That seems like it should work, but I'm still getting the output above (with one less "null") after changing it. I thought "while(wordptr[i] != NULL)" would keep it from creating pointers to the null portion--was I wrong, or am I screwing up somewhere else?
    Last edited by quasigreat; 05-21-2008 at 08:14 PM.

  4. #4
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Try something like this, works for me:
    Code:
    /* strtok example */
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	char *wordptr[81], s1[81], s2[81];
    	int i = 0;
    	printf("Input: ");
    	fgets(s1, 80, stdin);
    	//wordptr[i] = strtok(s1," \n");
    	
       char *result = NULL;
       result = strtok( s1, " \n");
       printf("Reversed: ");
       while(result != NULL) {
           wordptr[i] = result;
           result = strtok( NULL, " \n");
           i++;
       }
    	
    	for(i = i-1; i >= 0; i--)
    	{
    		printf("%s ", wordptr[i]);
    	}//print words marked by pointers in wordptr in reverse
    	
    	printf("\n");
    
      return 0;
    }
    Also have a look at Elisia's strtok function, I haven't used it yet, but u might like it more.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I did it too.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main ( void )
    {
        char test[] = "this is a short message\n";
        size_t idx = 0;
        char * parts[5];
        
        char * q = test;
        while ( ( q = strtok( q, "\n " ) ) != NULL )
        {
            parts[idx] = q;
            q = NULL;
            idx++;
        }
        while ( idx-- > 0 )
        {
            printf( "%s ", parts[idx] );
        }
        printf( "\n" );
    
        return 0;
    }
    It can be hard to figure out how many pointers you would need, but you can figure that out with some preprocessing.

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    21
    Thank you all very much for the help and your patience. It's working perfectly now. I probably sound like a bit of an idiot--that's because the course I'm currently taking is pretty much my first formal training in C. The while(status) (or in this case, while(result)) solution was just beginning to dawn on me when P4R4N01D posted.

  7. #7
    abyss - deep C
    Join Date
    Oct 2007
    Posts
    46
    Well....here's my version, but I am not using strtok and storing the words in a string array, instead the original string is indeed reversed with the last word appearing first, last but one second and so on...

    Code:
    #include <string.h>
    
    void reverseSentence(char *str)
    {
        int i,j,len;
        char ch;
    
        for(i=0,j=len=strlen(str)-1; i<j; i++,j--){
            ch = str[i];
            str[i] = str[j];
            str[j] = ch;
        }
    
        i=j=0;
        while(j<=len){
            int t;
    
            while(str[j] == ' ' || str[j] == '\t' || str[j] == '\n')
                j++;
            i = j;
    
            while(str[j] != ' ' && str[j] != '\t' && str[j] != '\n' && str[j] != '\0')
                j++;
            t = j - 1;
    
            while(i < t){
                ch = str[i];
                str[i++] = str[t];
                str[t--] = ch;
            }
        }
    }
    cheers
    maverix

  8. #8
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    don't use i, j and t. It makes the code that much harder to read and understand on first viewing. Descriptive names are ever so useful

    QuantumPete

    Edit: Interestingly, I remember someone putting this problem to me the other day: whether it's possible to reverse the order of words in a string in linear time. I'm pretty sure you can, but I've not given it a lot of thought yet.
    Last edited by QuantumPete; 05-22-2008 at 04:58 AM. Reason: Memory's like a sieve
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  9. #9
    abyss - deep C
    Join Date
    Oct 2007
    Posts
    46
    Quote Originally Posted by QuantumPete View Post
    don't use i, j and t. It makes the code that much harder to read and understand on first viewing. Descriptive names are ever so useful
    Agreed
    but i thought having large variable names for loop index would make the lines too long.

  10. #10
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by maverix View Post
    Agreed
    but i thought having large variable names for loop index would make the lines too long.
    Generally that's a good rule of thumb. However, when you have nested loops and those nested loops use the index of the parent loop to compute something, it just becomes confusing and readability wins over line-length. Something like word_idx and letter_idx are short enough still, I think. I'm not saying your indices should be named something like: this_is_the_index_to_the_letter_of_the_current_wor d_that_i_m_parsing

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  11. #11
    abyss - deep C
    Join Date
    Oct 2007
    Posts
    46
    Quote Originally Posted by QuantumPete View Post
    I'm not saying your indices should be named something like: this_is_the_index_to_the_letter_of_the_current_wor d_that_i_m_parsing

    QuantumPete
    That was a good one

  12. #12
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > but i thought having large variable names for loop index would make the lines too long.
    Yes but, they're used as counters in mathematics -- why not use them here? (ie, j, k, n, i, etc);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. String Class
    By BKurosawa in forum C++ Programming
    Replies: 117
    Last Post: 08-09-2007, 01:02 AM
  2. Program using classes - keeps crashing
    By webren in forum C++ Programming
    Replies: 4
    Last Post: 09-16-2005, 03:58 PM
  3. Calculator + LinkedList
    By maro009 in forum C++ Programming
    Replies: 20
    Last Post: 05-17-2005, 12:56 PM
  4. problems with overloaded '+' again
    By Brain Cell in forum C++ Programming
    Replies: 9
    Last Post: 04-14-2005, 05:13 PM
  5. Reversing a String
    By ToasterPas in forum C++ Programming
    Replies: 10
    Last Post: 08-14-2001, 12:20 PM