0

Using if and while/do-while, my job is to print following user's inputs (string value) in reverse order.

For example:

input string value : "You are American" output in reverse order : "American are You"

Is there any way to do this?

I have tried

string a;
cout << "enter a string: ";
getline(cin, a);
a = string ( a.rbegin(), a.rend() );
cout << a << endl;
return 0;

...but this would reverse the order of the words and spelling while spelling is not what I'm going for.

I also should be adding in if and while statements but do not have a clue how.

johnsyweb
  • 136,902
  • 23
  • 188
  • 247
user1940749
  • 19
  • 1
  • 1
  • 3
  • string a; cout << "enter a string: "; getline(cin, a); a = string ( a.rbegin(), a.rend() ); cout << a << endl; return 0; this reverses the ENTIRE thing.. the order and the spelling, but i dont want spelling. i donot know how i will be adding in if and while statements.. – user1940749 Jan 01 '13 at 09:05
  • It would help if you post your attempted code in the question itself? It's a classical problem, have you tried searching it as well? – Srinivas Jan 01 '13 at 09:07
  • Add that to your post instead of the comments for better formatting. – Rapptz Jan 01 '13 at 09:07
  • Reverse the whole string, like you're doing, then reverse each word. It would be extremely easy and efficient if you used a class like [llvm::StringRef](http://llvm.org/docs/doxygen/html/classllvm_1_1StringRef.html). – Benjamin Lindley Jan 01 '13 at 09:09
  • i have but i am not so experienced in programming. and yes i have tried searching :( – user1940749 Jan 01 '13 at 09:10
  • Often the key to solving these problems is to describe the algorithm in words without thinking of C++ (or any other programming language). If you could describe to an elderly relative how to do this with a pen and paper, converting this description to your programming language of choice is a lot easier. – johnsyweb Jan 01 '13 at 09:13
  • 1
    You could be [splitting the string into a vector](http://stackoverflow.com/questions/236129/splitting-a-string-in-c) then iterate through the vector from the end to the beginning. –  Jan 01 '13 at 09:14

6 Answers6

5

The algorithm is:

  1. Reverse the whole string
  2. Reverse the individual words
#include<iostream>
#include<algorithm>
using namespace std;

string reverseWords(string a)
{ 
    reverse(a.begin(), a.end());
    int s = 0;
    int i = 0;
    while(i < a.length())
    {
        if(a[i] == ' ')
        {
             reverse(a.begin() + s, a.begin() + i);
             s = i + 1;
        }
        i++;
    }
    if(a[a.length() - 1] != ' ')  
    {
        reverse(a.begin() + s, a.end());           
    }
    return a; 
}
Lorenzo Polidori
  • 10,332
  • 10
  • 51
  • 60
Aravind
  • 3,169
  • 3
  • 23
  • 37
  • Why so many copies of the `string`? Also, this isn't using while/do-while loops as the question states. – johnsyweb Jan 01 '13 at 09:41
  • There is only one copy of the string which is b which is manipulated to return the result.And you can easily convert the for into a while or do-while. – Aravind Jan 01 '13 at 10:06
  • 1
    You're also passing in `a` *by value* (one copy) and returning a `string` (another copy). – johnsyweb Jan 01 '13 at 10:09
  • Okay then I will alter it to use the given string copy itself, thanks. – Aravind Jan 01 '13 at 10:10
1

Here is a C-based approach that will compile with a C++ compiler, which uses the stack to minimize creation of char * strings. With minimal work, this can be adapted to use C++ classes, as well as trivially replacing the various for loops with a do-while or while block.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 1000
#define MAX_WORD_LENGTH 80

void rev(char *str) 
{
    size_t str_length = strlen(str);
    int str_idx;
    char word_buffer[MAX_WORD_LENGTH] = {0};
    int word_buffer_idx = 0;

    for (str_idx = str_length - 1; str_idx >= 0; str_idx--)
        word_buffer[word_buffer_idx++] = str[str_idx];

    memcpy(str, word_buffer, word_buffer_idx);
    str[word_buffer_idx] = '\0';
}

int main(int argc, char **argv) 
{
    char *line = NULL;
    size_t line_length;
    int line_idx;
    char word_buffer[MAX_WORD_LENGTH] = {0};
    int word_buffer_idx;

    /* set up line buffer - we cast the result of malloc() because we're using C++ */

    line = (char *) malloc (MAX_LINE_LENGTH + 1);
    if (!line) {
        fprintf(stderr, "ERROR: Could not allocate space for line buffer!\n");
        return EXIT_FAILURE;
    }

    /* read in a line of characters from standard input */

    getline(&line, &line_length, stdin);

    /* replace newline with NUL character to correctly terminate 'line' */

    for (line_idx = 0; line_idx < (int) line_length; line_idx++) {
        if (line[line_idx] == '\n') {
            line[line_idx] = '\0';
            line_length = line_idx; 
            break;
        }
    }

    /* put the reverse of a word into a buffer, else print the reverse of the word buffer if we encounter a space */

    for (line_idx = line_length - 1, word_buffer_idx = 0; line_idx >= -1; line_idx--) {
        if (line_idx == -1) 
            word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s\n", word_buffer);
        else if (line[line_idx] == ' ')
            word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s ", word_buffer), word_buffer_idx = 0;
        else
            word_buffer[word_buffer_idx++] = line[line_idx];
    }

    /* cleanup memory, to avoid leaks */

    free(line);

    return EXIT_SUCCESS;
}

To compile with a C++ compiler, and then use:

$ g++ -Wall test.c -o test
$ ./test
foo bar baz
baz bar foo
Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
1

This example unpacks the input string one word at a time, and builds an output string by concatenating in reverse order. `

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
  string inp_str("I am British");
  string out_str("");
  string word_str;
  istringstream iss( inp_str );


  while (iss >> word_str) {
    out_str = word_str + " " + out_str;
  } // while (my_iss >> my_word) 

  cout << out_str << endl;

  return 0;
} // main

`

0

You might try this solution in getting a vector of string's using the ' ' (single space) character as a delimiter.

The next step would be to iterate over this vector backwards to generate the reverse string.

Here's what it might look like (split is the string splitting function from that post):

Edit 2: If you don't like vectors for whatever reason, you can use arrays (note that pointers can act as arrays). This example allocates a fixed size array on the heap, you may want to change this to say, double the size when the current word amount has reached a certain value.

Solution using an array instead of a vector:

#include <iostream>
#include <string>
using namespace std;

int getWords(string input, string ** output)
{
    *output = new string[256];  // Assumes there will be a max of 256 words (can make this more dynamic if you want)
    string currentWord;
    int currentWordIndex = 0;
    for(int i = 0; i <= input.length(); i++)
    {
        if(i == input.length() || input[i] == ' ')  // We've found a space, so we've reached a new word
        {
            if(currentWord.length() > 0)
            {
                (*output)[currentWordIndex] = currentWord;
                currentWordIndex++;
            }
            currentWord.clear();
        }
        else
        {
            currentWord.push_back(input[i]);    // Add this character to the current word
        }
    }
    return currentWordIndex;    // returns the number of words
}

int main ()
{
    std::string original, reverse;
    std::getline(std::cin, original);  // Get the input string
    string * arrWords;
    int size = getWords(original, &arrWords);  // pass in the address of the arrWords array
    int index = size - 1;
    while(index >= 0)
    {
       reverse.append(arrWords[index]);
       reverse.append(" ");
       index--;
    }
    std::cout << reverse << std::endl;
    return 0;
}

Edit: Added includes, main function, while loop format

#include <vector>
#include <string>
#include <iostream>
#include <sstream>


// From the post
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
   std::stringstream ss(s);
   std::string item;
   while(std::getline(ss, item, delim)) {
       elems.push_back(item);
   }
   return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

int main ()
{
    std::string original, reverse;
    std::cout << "Input a string: " << std::endl;
    std::getline(std::cin, original);  // Get the input string

    std::vector<std::string> words = split(original, ' ');

    std::vector<std::string>::reverse_iterator rit = words.rbegin();

    while(rit != words.rend())
    {
       reverse.append(*rit);
       reverse.append(" "); // add a space
       rit++;
    }
    std::cout << reverse << std::endl;
    return 0;
}
Community
  • 1
  • 1
funseiki
  • 9,167
  • 9
  • 36
  • 59
0

This uses exactly one each of if and while.

#include <string>
#include <iostream>
#include <sstream>


void backwards(std::istream& in, std::ostream& out)
{
   std::string word;
   if (in >> word)   // Read the frontmost word
   {
      backwards(in, out);  // Output the rest of the input backwards...
      out << word << " ";  // ... and output the frontmost word at the back
   }
}

int main()
{
   std::string line;
   while (getline(std::cin, line))
   {
      std::istringstream input(line);
      backwards(input, std::cout);
      std::cout << std::endl;
   }
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

This code here uses string libraries to detect the blanks in the input stream and rewrite the output sentence accordingly

The algorithm is 1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero. 2. Look for the first space in the input stream 3. If no space is found, the input stream is the output 4. Else, get the position of the first blank after pos1, i.e. pos2. 5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence. 6. Pos1 is now at the first char after the blank. 7. Repeat 4, 5 and 6 untill no spaces left. 8. Add the last sub-string to at the beginning of the newSentence. –

#include <iostream> 
#include <string> 

  using namespace std; 

int main ()
{ 
    string sentence; 
    string newSentence;
    string::size_type pos1; 
    string::size_type pos2; 

    string::size_type len; 

    cout << "This sentence rewrites a sentence backward word by word\n"
            "Hello world => world Hello"<<endl;

    getline(cin, sentence); 
    pos1 = 0; 
    len = sentence.length();
    pos2 = sentence.find(' ',pos1); 
    while (pos2 != string::npos)
        {
            newSentence = sentence.substr(pos1, pos2-pos1+1) + newSentence; 
            pos1 = pos2 + 1;
            pos2 = sentence.find(' ',pos1);       
        }
    newSentence = sentence.substr(pos1, len-pos1+1) + " "  + newSentence;
    cout << endl << newSentence  <<endl; 

    return 0;

}
  • Perhaps you could break it down and explain what the code is doing. – phuzi Jun 08 '15 at 09:21
  • The algorithm is 1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero. 2. Look for the first space in the input stream 3. If no space is found, the input stream is the output 4. Else, get the position of the first blank after pos1, i.e. pos2. 5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence. 6. Pos1 is now at the first char after the blank. 7. Repeat 4, 5 and 6 untill no spaces left. 8. Add the last sub-string to at the beginning of the newSentence. – Hammam Orabi Jun 09 '15 at 09:57