Rohan Bojja
Rohan Bojja

Reputation: 675

Reverse words of a sentence in c++, Asked on Google Code jam

How to solve this? https://code.google.com/codejam/contest/351101/dashboard#s=p1?

The code I ended up with is below, but it can only reverse strings up to one space because it was code keeping the literal logic in mind, Reverse the whole string, reverse the words, and done. The spaces are slightly messed up and when I tried a loop to detect number of spaces and act accordingly it failed. Please help! Code:

#include <iostream>
#include <string>

using namespace std;


int main()
{

    char revwrd[100];
    char revstr[100];
    string str;
    getline(cin, str);
    cout<<str;
    int sps[10];

    int len,y=0;
    len = str.length();
    cout<<"\n"<<"The Length of the string is:"<<len;
    for(int x=len-1;x>-1;x--)
    {
        revstr[x] = str[y];
        y++;

    }
    cout<<"\n"<<"The inverse of the string is:"<<"\n";
    for(int z = 0;z<len;z++)
    {
        cout<<revstr[z];
    }
    cout<<"\n";

    int no=0;
    int spaces=0;
    for(int a=0;a<len;a++)
    {
        if(revstr[a]== ' ')
        {
            sps[no]=a;
            no++;
            spaces++;
        }
    }

    int rinc=0;
    int spinc;
    cout<<"\n";
    spinc=sps[0];

    int spinc2 = sps[0]+1;
    int lend;
    for(rinc=0;rinc<sps[0]+1;rinc++)
    {

        revwrd[rinc] = revstr[spinc];
        spinc--;
    }


    for(lend=len;lend>sps[0];lend--)
    {
        revwrd[spinc2] = revstr[lend];
        spinc2++;
    }
    cout<<"Spaces in the string:"<<spaces<<"\n";
    cout<<"The words inversed are:"<<"\n";
    for(int inc=1;inc<len+1;inc++)
    {
        cout<<revwrd[inc];
    }

    return 0;
}

Upvotes: 1

Views: 2884

Answers (6)

moldovean
moldovean

Reputation: 3261

I went for the brute force, and I badly wanted to use pointers!

  1. get the sentence
  2. detect every word and put them in a container.
  3. read backwards the container.

This is it:

#include <iostream>
#include <string>
#include <vector>
int main()
{
char *s1 = new char[100];
std::cin.getline(s1, 100);

std::vector<std::string> container;
char* temp = new char[100];
char *p1, *p0;

p1 =p0 = s1;
int i;
do{
    if (*p1==' ' || *p1=='\0'){
        //std::cout<<p1-p0<<' ';
        for(i=0;i<p1-p0;++i) temp[i]=p0[i]; temp[i]='\0';
        p0 = p1+1;
        container.push_back(temp);
        std::cout<<temp;
    }
    p1++;
}while(*(p1-1)!='\0');

std::cout<<std::endl;
for(int i=container.size()-1;i>=0;i--) std::cout<<container[i]<<' ';

return 0;
}

Upvotes: 0

Amit Thakur
Amit Thakur

Reputation: 31

Just few loops and if's:

// Reverse Words 
#include <iostream>
#include <string>

using namespace std;

int main() {
    int tc; cin >> tc; cin.get();
    for(int t = 0; t < tc; t++) {
        string s, k; getline(cin, s);   
        for(int i = (s.length()- 1); i >= 0; i--) {
            if(s[i] == ' ' || (i == 0)) {
                    if(i == 0) k += ' ';
                for(int j = i; j < s.length(); j++) {
                    k += s[j];
                    if(s[j+1] == ' ' ) break;
                }
            } 
        }
        cout << "Case #" << t + 1 << " " << k << endl;
    }   

    return 0;
}

Upvotes: 1

user2370656
user2370656

Reputation: 1

This problem is really made for recursion:

void reverse()
{
    string str;
    cin >> str;
    if (cin.peek() != '\n' || cin.eof()) {
        str = " " + str;
        reverse();
    }
    cout << str;
}

int main(int argc, const char * argv[])
{
    int count = 0;
    cin >> count;
    for (int i = 0; i < count; i++) {
        cout << "Case #" << (i + 1) << ": ";
        reverse();
        cout << endl;
    }
    return 0;
}

So I read word by word and add one space in front of the word until end of line or file is reached. Once end of line is reached the recursion unwraps and prints the read strings in reversed order.

Upvotes: 0

John Bode
John Bode

Reputation: 123458

The conditions of the challenge are that there is only a single space between words, and that spaces don't appear at the beginning or the end of the line, so for this particular exercise you don't have to worry about preserving spacing; as long as you write the output with a single space between each word, you're good.

With that in mind, you can read each word using regular formatted input:

std::string word;
...
while ( stream >> word )
  // do something with word

You don't have to worry about buffer size, you don't have to worry about detecting spaces, etc. You do have to worry about detecting the newline character, but that's easily done using the peek method:

while ( stream >> word )
{
  // do something with word;
  if ( stream.peek() == '\n' )
    break;
}

The above loop will read individual words from the input stream stream until it sees a newline character (there's probably a better way to do that, but it works).

Now, in order to reverse each line of input, you obviously need to store the strings somewhere as you read them. The easiest thing to do is store them to a vector:

std::vector< std::string > strings;
...
while ( stream >> word )
{
  strings.push_back( word );
  if ( stream.peek() == '\n' )
    break;
}

So now you have a vector containing all the strings in the line, you just have to print them out in reverse order. You can use a reverse iterator to walk through the vector:

std::vector< std::string >::reverse_iterator it;
for ( it = strings.rbegin(); it != strings.rend(); ++it )
{
  std::cout << *it << " ";
}
std::cout << std::endl;

The rbegin() method returns an iterator that points to the last element in the vector; the rend() method returns an iterator that points to an element before the first element of the vector; ++it advances the iterator to point to the next item in the vector, going back to front; and *it gives the string that the iterator points to. You can get a little more esoteric and use the copy template function:

std::copy( strings.rbegin(), 
           strings.rend(), 
           std::ostream_iterator<std::string>( std::cout, " " )
         );

That single method call replaces the loop above. It creates a new ostream_iterator that will write strings to cout, separated by a single space character.

For the conditions of this particular exercise, this is more than adequate. If you were required to preserve spacing, or to account for punctuation or capitalization, then you'd have to do something a bit lower-level.

Upvotes: 1

birubisht
birubisht

Reputation: 908

you can follow this method :

step 1 : just check for spaces in input array store their index number in an integer array.

step 2 : now iterate through this integer array from end

step a : make a string by copying characters from this index to previous index .
      note : since for first element there is no previous element in that case you will   copy   from this index to end of the input string .  

step b : step a will give you a word from end of input string now add these word with a space to make your output string .  

I hope this will help you .

Upvotes: 0

fatihk
fatihk

Reputation: 7919

This might handle multi spaces:

std::string ReverseSentence(std::string in)
{
   std::vector<string> words;
   std::string temp = "";
   bool isSpace = false;
   for(int i=0; in.size(); i++)
   {
      if(in[i]!=' ')
      {
         if(isSpace)
         {
            words.push_back(temp);
            temp = "";
            isSpace = false;
         }
         temp+=in[i];
      }
      else
      {
         if(!isSpace)
         {
            words.push_back(temp);
            temp = "";
            isSpace = true;
         }
         temp +=  " ";
      }
   }
   std::reverse(words.begin(),words.end());
   std::string out = "";
   for(int i=0; i<words.size(); i++)
   {
      out+=words[i];
   }
 return out;
}

Upvotes: 0

Related Questions