C ++中的简单句子逆转

时间:2011-11-09 20:45:56

标签: c++

我正在尝试建立一个程序来解决我最近购买的教科书中的一个问题,这只会让我发疯。

我必须构建一个句子反转器,所以我得到以下内容:

输入=“做或不做,没有尝试。” 输出=“尝试。没有没有,做或做”

这是我到目前为止所得到的:

void ReverseString::reversalOperation(char str[]) {
    char* buffer;
    int stringReadPos, wordReadPos, writePos = 0;

    // Position of the last character is length -1
    stringReadPos = strlen(str) - 1;
    buffer = new char[stringReadPos+1];

    while (stringReadPos >= 0) {
        if (str[stringReadPos] == ' ') {
            wordReadPos = stringReadPos + 1;
            buffer[writePos++] = str[stringReadPos--];
            while (str[wordReadPos] != ' ') {
                buffer[writePos] = str[wordReadPos];
                writePos++;
                wordReadPos++;
            }
        } else {
            stringReadPos--;
        }
    }

    cout << str << endl;
    cout << buffer << endl;
}

我确信我是在正确的轨道上,但我得到的所有输出都是第一个字(“尝试”。)我一直盯着这段代码,所以我无法取得任何进展。最初我正在检查内部,同时寻找'/ 0'字符,但它似乎不喜欢,所以我把它拿出来。

7 个答案:

答案 0 :(得分:5)

除非你感到受虐待,否则请抛弃现有代码,并从std::vectorstd::string开始(最好是std::vector<std::string>)。使用向量的std::copyrbegin添加rend,您就已经完成了。

答案 1 :(得分:5)

在C ++中,在标准库的帮助下,这非常简单:

std::vector< std::string > sentence;
std::istringstream input( str );

// copy each word from input to sentence
std::copy(
    (std::istream_iterator< std::string >( input )), std::istream_iterator< std::string >()
  , std::back_inserter( sentence )
);
// print to cout sentence in reverse order, separated by space
std::copy(
    sentence.rbegin(), sentence.rend()
  , (std::ostream_iterator< std::string >( std::cout, " " ))
);

答案 2 :(得分:2)

我在您的代码中看到以下错误:

  • 缓冲区的最后一个char未设置为0(这将导致cout失败&lt;
  • 在内循环中你必须检查str[wordReadPos] != ' ' && str[wordReadPos] != 0否则在扫描第一个单词时它永远不会找到终止空间

答案 3 :(得分:2)

为了科学,我试图让你的代码按原样运行。是的,它不是真正的C ++做事方式,但仍具有指导意义。

当然,这只是完成工作的百万种方法之一。我将把它留作练习,以删除此代码在输出中留下的尾随空格;)

我用“编辑”评论了我的更改。

char* buffer;
int stringReadPos, wordReadPos, writePos = 0;

// Position of the last character is length -1
stringReadPos = strlen(str) - 1;
buffer = new char[stringReadPos+1];

while (stringReadPos >= 0) {
    if ((str[stringReadPos] == ' ') 
            || (stringReadPos == 0)) // EDIT: Need to check for hitting the beginning of the string
            {
        wordReadPos = stringReadPos + (stringReadPos ? 1 : 0); // EDIT: In the case we hit the beginning of the string, don't skip past the space

        //buffer[writePos++] = str[stringReadPos--]; // EDIT: This is just to grab the space - don't need it here
        while ((str[wordReadPos] != ' ')
               && (str[wordReadPos] != '\0'))  // EDIT: Need to check for hitting the end of the string
               {
            buffer[writePos] = str[wordReadPos];
            writePos++;
            wordReadPos++;
        }
        buffer[writePos++] = ' '; // EDIT: Add a space after words
    }

    stringReadPos--; // EDIT: Decrement the read pos every time        
}
buffer[writePos] = '\0'; // EDIT: nul-terminate the string

cout << str << endl;
cout << buffer << endl;

答案 4 :(得分:1)

由于您使用的是char数组,因此可以使用C字符串库。如果你使用strtok:http://www.cplusplus.com/reference/clibrary/cstring/strtok/

会更容易

它需要指针使用,但它会让你的生活更轻松。你的分隔符将是“”。

答案 5 :(得分:1)

您的代码出现问题以及cplusplusish做什么方式的内容尚未写好。但是,我想补充说明方法

  • 编写一个函数/程序来实现算法;
  • 看看它是否有效;
  • 如果没有,请查看代码,直到问题出现

效率不高。什么可以帮助您解决此问题,以及将来的许多其他问题是调试器(和穷人的调试器printf)。它将使您能够看到程序在步骤中的实际工作方式,数据发生的情况等等。换句话说,您将能够看到它的哪些部分按预期工作,哪些部分的行为方式不同。如果您使用的是* nix,请不要犹豫,尝试使用gdb。

答案 6 :(得分:0)

这是一个更多的C ++版本。虽然我认为在这种情况下简单性比风格更重要。基本算法很简单,反转单词然后反转整个字符串。

您可以编写与C ++版本一样明显的C代码。我认为在这里编写非夸张的C ++代码并不一定是错的。

void word_reverse(std::string &val) {
    size_t b = 0;
    for (size_t i = 0; i < val.size(); i++) {
        if (val[i] == ' ') {
            std::reverse(&val[b], &val[b]+(i - b));
            b = ++i;
        }
    }
    std::reverse(&val[b], &val[b]+(val.size() - b));
    std::reverse(&val[0], &val[0]+val.size());
}

TEST(basic) {
    std::string o = "Do or do not, there is no try.";
    std::string e = "try. no is there not, do or Do";
    std::string a = o;
    word_reverse(a);
    CHECK_EQUAL( e , a );
}

具有多个,前导或尾随空格可能是退化情况,具体取决于您实际希望它们的行为方式。