开发者

c++: I am trying to reverse the order of words in string (not the whole string)

开发者 https://www.devze.com 2023-03-12 22:32 出处:网络
#include <iostream> #include <vector> using namespace std; void RevStr (char *str) { if(*str !=0)
#include <iostream>
#include <vector>
using namespace std;

void RevStr (char *str)
{   
    if(*str !=0)
    {
        vector<char> v1;

        while((*str != ' ')&&(*str !=0))
            v1.push_back(*str++);
        // trying to not add space in the last word of string
        if(*str !=0)
        {
            v1.push_back(' ');
            str++;
        }
        RevStr(str);
        cout<<*str;
    }


}
int开发者_开发知识库 main()
{
    RevStr("hello world!");
    cout<<endl;

}

I want to change the order of words in the string for example " how are you" => "you are how"

I am having some problem, its not printing correctly (print only w), please help me and tell me what i did wrong. However i know that I should not call "cout<<*str; " since i am inserting the "array of char" in stack (recurssion) but i dont know what i need to do.


C++ makes it simple:

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

std::string reverse(std::string const& text)
{
    std::stringstream           inStream(text);
    std::stringstream           outStream;
    std::vector<std::string>    words;

    std::copy(std::istream_iterator<std::string>(inStream), std::istream_iterator<std::string>(), std::back_inserter(words));
    std::copy(words.rbegin(), words.rend(), std::ostream_iterator<std::string>(outStream, " "));
    return outStream.str();
}


int main()
{
    std::cout << reverse("Hello World") << "\n";
}


A common approach to do this is to reverse the entire string first, then for each word, reverse the letters in the word. So no recursion is necessary. You might find it easier to give this a try (yes, I know this isn't exactly an answer to your question :) ).


Use cout << str, not cout << *str to print a string. There's an operator<< overload for char *. But maybe that's not what you're trying to do; I can't quite follow your logic, in any event.


You're losing the "hello" part.

The algorithm you seem to go for does this:

  1. each call to RevStr isolates the first word in the string it is passed as a parameter
  2. calls RevStr with the remaining of the string
  3. prints the word it isolated at step 1 as the stack unwinds

Basically, you should be printing the v1 data.


I would strongly advise making using some of the functionality exposed via std::string as a place to start.

One way you might do this would look like this:

std::string ReverseString(std::string s)
{
    std::stack<std::string > stack;
    std::string tmpstr = "";
    std::string newstr = "";
    size_t strsize = s.size();
    size_t pos  = 0;   size_t tmppos = 0;
    size_t i = 0;      size_t stacksize = 0;
    while( pos < strsize )
    {
        tmppos = s.find(" ", pos, 1);    // starting as pos, look for " "
        if (tmppos == std::string::npos) // std::string::npos => reached end
        {
            tmppos = strsize;            // don't forget the last item.
        }     
        tmpstr = s.substr(pos, tmppos-pos); // split the string.
        stack.push(tmpstr);                 // push said string onto the stack
        pos = tmppos+1;
    }
    stacksize = stack.size();
    for ( i = 0; i < stacksize; i++ )
    {
        tmpstr = stack.top();              // grab string from top of the stack
        stack.pop();                       // stacks being LIFO, we're getting 
        if ( i != 0 )                      // everything backwards.
        {
            newstr.append(" ");            // add preceding whitespace.
        }
        newstr.append(tmpstr);             // append word.
    }
    return newstr;
}

It's by no means the best or fastest way to achieve this; there are many other ways you could do it (Jerry Coffin mentions using std::vector with an iterator, for example), but as you have the power of C++ there, to me it would make sense to use it.

I've done it this way so you could use a different delimiter if you wanted to.

In case you're interested, you can now use this with:

int main(int argc, char** argv)
{
    std::string s = "In Soviet Russia String Format You";
    std::string t = ReverseString(s);
    std::cout << t << std::endl;
}


given that its a char*, this reverses it inplace (ie, doesn't require more memory proportional to the incoming 'str'). This avoids converting it to a std::string ( not that its a bad idea to, just because it's a char* to start with.)

void reverse_words(char* str)
{
    char* last = strlen(str) + str;
    char *s, *e;
    std::reverse(str,last);
    for(s=e=str; e != last; e++)
    {
        if(*e == ' ') 
        {
            std::reverse(s,e);
            s = e+1;
        }
    }
    std::reverse(s,e);  
}


void Reverse(const string& text)
{
    list<string> words;
    string temp;
    for ( auto cur = text.begin(); cur != text.end(); ++cur)
    {
        if (*cur == ' ')
        {
            words.push_front(temp);
            temp.clear();
        }
        else
        {
            temp += *cur;
        }
    }
    if (! temp.empty())
    {
        words.push_front(temp);
    }

    for_each(words.begin(), words.end(), [](const string& word) { cout << word << " "; });
    cout << endl;
}


void swap(char* c1, char* c2) {
    char tmp = *c1;
    *c1 = *c2;
    *c2 = tmp;
}

void reverse(char* s, char* e) {
     if (s == NULL || e == NULL)
        return;
     while(s < e)
      swap(s++, e--);
}

void reverse_words(char* line) {
  if (line == NULL)
    return; 
  reverse(line, line+strlen(line)-1);
  char *s = line;
  char *e;
  while (*s != '\0') {
    e = s;
    while (*e != ' ' && *e != '\0') ++e;
    --e;
    reverse(s,e);
    s = e+2;
  }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消