当我比较两个向量中的元素时出现错误 - 我做错了什么

Getting errors when I compare elements in two vectors - am I doing something wrong?

本文关键字:错误 什么 错了 元素 比较 向量 两个      更新时间:2023-10-16

任务非常简单:创建一个程序,告诉用户他或她输入的句子是否前后相同(就使用的单词而言,而不是拼写而言)。例如,"I am that am I"(请忽略这在语法上是多么荒谬)。所以我决定创建两个字符串向量 - 一个存储原始句子,另一个是颠倒的句子。每个向量的元素将是包含句子单词的字符串,例如["I", "am", "that", "am", I"],不包括字符串中的任何空格。

我陷入了解决这个问题的初步状态 - 比较这两个向量的元素。这是我下面的代码(注意句子是第一个向量,reverseString是第二个向量,包含相反顺序的元素):

        for (int i = 0; i < sentence.size(); i++) {
            // The below output is for debugging purposes
            cout << "The index is " << i
                 << " and the original string at this location is " << sentence[i]
                 << " and the reverse string is " << reverseString[i] << endl;
            if (sentence[i] == reverseString[i]) {
                cout << reverseString[i] << "---" << sentence[i] <<  endl;
                cout << "A match!" << endl;
            } else {
                cout << reverseString[i] << "---" << sentence[i] << endl;
                cout << "Not a match!" << endl;
            }
        }

奇怪的是,上面的代码似乎可以准确地处理索引 1 到 vector.size()-2 中的元素(请记住,c++ 向量中的索引开始和零)。但是索引 0 或 vector.size()-1 - 即每个向量的第一个和最后一个元素 - 总是产生一个"Not a match!",无论句子是什么。两者之间的一切都被准确地比较了,但这两个位置不是。

这是一个非常奇怪的错误。也许我的错误在于创建第二个向量?这是我使用的代码:

    int t = sentence.size() - 1;
    for (int i = 0; i < sentence.size(); i++) {
        reverseString[i] = sentence[t];
        t--;
    }
我是否无意中

改变了第一个和最后一个元素不应该成为的东西,以一种我不太清楚的方式?我的逻辑有缺陷吗?请让我知道你的想法:)

编辑:我在下面发布了我的代码的最小,完整和可验证的示例

#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
    string input;
    cout << "Please input a sentence - no preceding or trailing spaces."
            " It will be analyzed accordingly: ";
    getline(cin, input);
    string secondString = "";
    secondString[0] = input[0];
    int i = 0; 
    for (i = 0; i <= input.length(); i++) {
        // the below strips a string of punctuation if there is any, 
        // as these characters would mess up the comparison.
        if (input[i] == ',' || input[i] == ';' || input[i] == ':' ||
            input[i] == '.' || input[i] == '?' || input[i] == '!') {
        } else {
            secondString = secondString + input[i];
        }
    }
    // now stuff the individual words in the string into a vector
    vector<string> sentence;
    // now we are going to stuff each word into a vector
    string word;
    stringstream ss(secondString);
    while (getline(ss, word, ' ')) {
        sentence.push_back(word);
    }
    // now for Task 1 - we will create a second vector that is reversed.
    // Then compare both vectors - if identical, note it. 
    vector<string> reverseString;
    reverseString = sentence; 
    int t = sentence.size() - 1;
    for (int i = 0; i < sentence.size(); i++) {
        reverseString[i] = sentence[t];
        t--;
    }
    for (int i = 0; i < sentence.size(); i++) {
        cout << "The index is " << i
             << " and the original string at this location is " << sentence[i]
             << " and the reverse string is " << reverseString[i] << endl;
        if (sentence[i] == reverseString[i]) {
            cout << reverseString[i] << "---" << sentence[i] <<  endl;
            cout << "A match!" << endl;
        } else {
            cout << reverseString[i] << "---" << sentence[i] << endl;
            cout << "Not a match!" << endl;
        }
    }
    return 0;
}

由于此行中的比较,您有未定义的行为

for (i = 0; i <= input.length(); i++)

一旦循环体尝试访问input[i],而i等于input.length(),就会发生未定义的行为。来得及:

for (i = 0; i < input.length(); i++)

只是程序没有崩溃是运气不好,否则您可能已经注意到了错误。

当我尝试时,发生在我身上的是,一个多余的空格字符被附加到secondString,这最终导致sentence中的最后一个元素在末尾有一个额外的空格,所以第一个和最后一个单词永远不会相等。


还要注意的是,句子比较代码本身太复杂了,因为你可以用std::equal更简单的方式实现你的目标,std::vector 的反向迭代器由 rbegin() 成员函数获得,并将范围分成两半,如以下示例所示:

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
bool compare(std::vector<std::string> const& sentence)
{
    // returns true if the range from the first to the middle element
    // is equal to the range from the last to the middle element
    return std::equal(
        sentence.begin(),
        sentence.begin() + sentence.size() / 2,
        sentence.rbegin()
    );
}
int main()
{
    std::vector<std::string> const sentence1 = { "I", "am", "that", "am", "I" };
    std::vector<std::string> const sentence2 = { "am", "that", "am", "I" };
    std::vector<std::string> const sentence3 = { };
    std::vector<std::string> const sentence4 = { "I", "am", "that", "that", "am", "I" };
    std::vector<std::string> const sentence5 = { "I" };
    std::cout << compare(sentence1) << "n"; // true
    std::cout << compare(sentence2) << "n"; // false
    std::cout << compare(sentence3) << "n"; // true
    std::cout << compare(sentence4) << "n"; // true
    std::cout << compare(sentence5) << "n"; // true
}

此解决方案只需要一个std::vector并且不会执行不必要的比较;当到达句子的中间元素时,结果已经知道。

相比之下,您的原始代码不必要地迭代整个句子:

for (int i = 0; i < sentence.size(); i++) {

首先,secondString[0] = input[0];当 secondString 无效时无效 为空。同样,对于 (i = 0; i <= input.length(); 应该在之前停止 到达输入长度()。– 博佩尔松 12分钟前

Bo Persson的评论解决了你的问题。

相关文章: