简体   繁体   English

字符串中单词的反向顺序

[英]Reverse order of words in string

I am preparing for an entry-level job interview. 我正准备参加入门级面试。 I am trying to reverse the order of words in a string, but my output is a bunch of junk that makes no sense. 我试图扭转字符串中单词的顺序,但我的输出是一堆没有意义的垃圾。 I think the problem may be because I'm using "char*" for my functions? 我认为问题可能是因为我正在使用“char *”作为我的功能? Anyways, heres my code 无论如何,继承人我的代码

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

char* reverse(char* str, int a, int b); 
char* reversewords(char* str); 

int main()
{
    char str[] = "The interview is";
    cout<<"Reverse is: "<<reversewords(str); 
    cin.ignore();
    return 0;
}


char* reverse(char* str, int a, int b)
{
    int length = a-b;

    for (int i=a; i<b+1; i++)
    {
        char c =str[length-i-1];
        str[length-i-1]=str[i];
        str[i] = c;
    }
    return str;
}

char* reversewords(char* str)
{
    int length = strlen(str);
    int a=0;
    int b=0;
    while (b<length)
    {
        if (str[b]==' ' || b==length-1)
        {
                b=b-1;
            reverse(str, a, b);
            a=b+2;
            b=a;
        }
        b++;
    }
    return str;
}

I would like to reiterate what WeaselFox said about not reinventing the wheel, try to learn the C++ STL, in the long run that will be a lot more helpful. 我想重申WeaselFox所说的不重新发明轮子,尝试学习C ++ STL,从长远来看会更有帮助。

Having said that let me suggest an approach as well. 话虽如此,我也建议采用一种方法。 Whenever you come across problems like reversing order of chars in a string OR reversing words in a string, interviewers are really trying to test your knowledge of data structures, and in this case, specifically the "stack" data structure. 每当遇到诸如在字符串中反转字符顺序或在字符串中反转字样等问题时,访调员就会尝试测试您对数据结构的了解,在这种情况下,特别是“堆栈”数据结构。

Consider what happens if you parse words in a string and place them all into an array one at a time: "I AM A STRING" --> {"I", "AM", "A", "STRING"} 考虑如果你在一个字符串中解析单词并将它们全部放入一个数组中会发生什么:“我是一个字符串” - > {“我”,“AM”,“A”,“STRING”}

Now do the same thing for a stack: 现在对堆栈做同样的事情:

"I AM A STRING" --> {"STRING", "A", "AM", "I"} “我很棒” - > {“STRING”,“A”,“AM”,“我”}

Do you see why a stack would be useful ? 你明白为什么堆栈会有用吗? It's better if you reason it out yourself than I provide source code, the reason being that your approach is incorrect regardless of whether or not it yields the correct answer. 如果你自己推理出来比我提供源代码更好,原因是你的方法不正确,无论它是否产生正确的答案。

I hope this helps! 我希望这有帮助!

If you're wanting a C-like solution, you can do it with only pointers and a temp variable of type char if you need to define your own reverse function to reverse a string between two pointers. 如果你想要一个类似C的解决方案,如果需要定义自己的reverse函数来反转两个指针之间的字符串,你可以只使用指针和char类型的临时变量。 The code below simply reverses the entire string it receives (it could be modified to reverse only the string in a range [iterA, iterB)) and reverses the letters in each of the word is that string. 下面的代码简单地反转它接收的整个字符串(它可以被修改为仅反转范围[iterA,iterB)中的字符串)并且反转每个单词中的字母是该字符串。 For example, reversing hello world! 例如,逆转hello world! first results in !dlrow olleh inside reverse_words , which is corrected to world! hello 首先导致!dlrow olleh里面的reverse_words ,这是纠正到world! hello world! hello . world! hello

#include <cstring>
#include <cctype>
using std::isspace;
using std::strlen;

void reverse(char *start, char *end)
{
    for (char c; --end - start > 0; ++start) {
        c = *start;
        *start = *end;
        *end = c;
    }
}

void reverse_words(char *s)
{
    char *end = s + strlen(s);
    char *delimp;

    // Don't reverse any leading/trailing space (e.g. a newline).
    while (isspace(*s))
        ++s;
    while ((isspace(*end) || !*end) && end - s > 0)
        --end;

    // Reverse the remaining string.
    reverse(s, ++end);

    // Reverse each word.
    while (end - s > 0) {

        // Skip leading space characters.
        while (isspace(*s))
            ++s;

        // Find the next space character.
        delimp = s;
        while (!isspace(*delimp) && *delimp)
            ++delimp;

        // Reverse the word.
        reverse(s, delimp);

        // Point to the next space character (or the end of the string).
        s = delimp;
    } //while(end - s > 0)
} //void reverse_words(...)

You could substitute std::reverse in the library for the reverse function defined above. 您可以在库中替换std::reverse以获取上面定义的reverse函数。 I included an implementation nonetheless. 尽管如此,我还是包含了一个实现。 An implementation of reverse_words working on a range could be potentially more useful and shouldn't be difficult to implement with the above code. 在范围上工作的reverse_words的实现可能更有用,并且应该不难用上面的代码实现。 It is left as an exercise to the reader. 它留给读者练习。

let me recommend a different approach. 让我推荐一种不同的方法。 If youre using char pointers: 如果你使用char指针:

  1. split the string using strtok into an array of char* s. 使用strtok将字符串拆分为char* s数组。
  2. iterate over this array of words from the end backwards and reassemble the string. 从末尾向后迭代这个单词数组并重新组合字符串。

If you opt to use strings and STL containers, refer to this question as for splitting the string to tokens, and reassembling them nicely: 如果您选择使用字符串和STL容器,请参阅此问题,以便将字符串拆分为标记,并将其重新组合得很好:

Split a string in C++? 用C ++拆分一个字符串?

Its always a better idea not to reinvent the wheel. 不重新发明轮子总是一个更好的主意。 Use library functions, dont manipulate the chars yourself. 使用库函数,不要自己操纵字符。

// Maybe just take the words out of the string and put them back in reverse 
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

int main() {

string a("This is my string to try and reverse");

// Reverse word order
vector<string> words;
string::size_type pos = 1;
while(pos != string::npos) {
    pos = a.find(" ");
    if(pos != string::npos) {
        words.push_back(string(a.begin(),a.begin()+pos));
        a.erase(a.begin(),a.begin()+pos+1);
    }
    else {
        words.push_back(string(a.begin(),a.end()));
        a.erase(a.begin(),a.end());
    }
}
reverse(words.begin(), words.end());
for(int i=0; i<words.size(); i++) a.append(words[i].append(" "));
cout << a << endl;
return 0;
}

Change int length = ab; 改变int length = ab; to int length = b-a+1; to int length = b-a+1; in reverse() . reverse()

Also you need to loop till middle, otherwise it will be reversed twice, giving the original output. 你需要循环到中间,否则它将被反转两次,给出原始输出。

for (int i=a; i<=a+(b-a)/2; i++)
{
    char c =str[a+length-i-1];
    str[a+length-i-1]=str[i];
    str[i] = c;
}
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

void split(string &str, vector<string> &v, char ch);

int main() {

string str;
std::getline(std::cin, str);

vector <string> stringVec;

split(str, stringVec, ' ');

vector <string>::reverse_iterator it;

for (auto it = stringVec.rbegin(); it != stringVec.rend(); 
++it)
{
    cout << *it << " ";
}

return 0;
}

void split(string &str, vector<string> &v, char ch)
{
size_t pos = str.find(" ");
size_t initialpos = 0;
v.clear();

while (pos != string::npos)
{
    v.push_back(str.substr(initialpos, pos - initialpos));
    initialpos = pos + 1;
    pos = str.find(ch,initialpos);
}
v.push_back(str.substr(initialpos, (std::min(pos, str.size()) - 
initialpos + 1)));
}

Just to give you headsup for how to reverse a string using RECURSION, I modified your code that is given below. 为了让您了解如何使用RECURSION反转字符串,我修改了下面给出的代码。 Learn and feel the power of recursion. 学习并感受递归的力量。

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

char * reverse_s(char *, char*, int,int);

int main()
{
    char str[] = "The interview is";
    char* rev_str = new char[strlen(str)];
    cout<<"\n\nFinal Reverse of '" << str << "' is -->"<< reverse_s(str, rev_str, 0, strlen(str)) << endl;
    cin.ignore();
    delete rev_str;
    return 0;
}

char* reverse_s(char* str, char* rev_str, int str_index, int rev_index ) {

if(strlen(str) == str_index )
        return rev_str;

str_index += 1;
rev_index -=1;

rev_str = reverse_s(str, rev_str, str_index, rev_index);

cout << "\n Now the str value is " << str[str_index-1] << " -- Index " << str_index-1;
rev_str[rev_index] = str[str_index-1];

cout << "\nReversed Value: " << rev_str << endl;

return rev_str;
}

here is my version 这是我的版本

#include <iostream>
#include <vector> // template for list
#include <algorithm> // copy algorithm or revers
#include <sstream> //sstringstream
#include <iterator>// iterator
#include <fstream>
using namespace std;

/*    overloading ostream operator operator */
ostream &operator<<(ostream&out, const vector<string> a){
static int i = 1;
out << "Case #" << i++ << ": ";

for (vector<string> ::const_iterator v = a.begin(); v != a.end(); v++)
    out << *v;
return out;
}

void showElemnts(vector<string> vec, int line){
cout << "Case #" << line << " " << vec; // overloading operator for output vector
}

vector<string> reversWord(string &s){
istringstream processWordByWord(s); // store string in processWordByWord and store in events
vector<string> events; // store events here
string input;

while (processWordByWord >> input){
    events.push_back(input);
    events.push_back(" ");
}


events.pop_back(); // delete space
reverse(events.begin(), events.end());
return events;
}





int main(){
vector<string> a;
string Line;
ifstream dataInput("B-small-practice.in", ios::in);
ofstream dataOut("out.out");
int  number;

getline(dataInput, Line); // skip first line
getline(dataInput, Line); // skip first line

while (!dataInput.eof())
{
    dataOut << reversWord(Line)<<endl;
    getline(dataInput, Line);


}
dataInput.close();
dataOut.close();

return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM