比较两个向量<structs>的字符串元素

时间:2017-03-28 00:18:14

标签: c++ string function vector struct

点击我之前的问题:

Accessing local variables from void functions

我已经能够获得所需的数据,现在我正在尝试比较传递给函数的每个string name元素的struct属性。

这是我目前的代码:

#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>

using namespace std;

struct Nutrient {
    string name, units;
    double amount, calories;
};

struct Recipe {
    string title;
    double servings;
};

struct Ingredient {
    string name, units;
    double amount;
};

vector<Nutrient> readNutrients(istream& fin) {

    vector<Nutrient> nutrients;

    /**ifstream in(input_file.c_str());*/

    string line;

    while (getline(fin, line)) {

        Nutrient n;

        int pos = line.find(';');
        n.name = line.substr(0, pos);
        line = line.substr(pos + 1);

        istringstream iss(line);

        iss >> n.amount >> n.units >> n.calories;
        nutrients.push_back(n);
    }

    return nutrients;

}

Recipe readRecipe(istream& fin) {

    Recipe recipe;

    string line;

    int lineCount = 0;

    while (getline(fin, line)) {

        lineCount++;
        istringstream iss(line);

        if (lineCount == 1) {
            iss >> recipe.title;
        }
        else if (lineCount == 2) {
            iss >> recipe.servings;
        }
    }
    return recipe;
}

vector<Ingredient> readIngredients(istream& fin) {

    vector<Ingredient> ingredients;

    string line;
    string title; // Just grabs, doesnt return
    double servings; // Just grabs, doesnt return

    int lineCount = 0;


    while (getline(fin, line)) {

        Ingredient g;

        lineCount++;
        istringstream iss(line);

        if (lineCount == 1) {
            iss >> title;
        }
        else if (lineCount == 2) {
            iss >> servings;
        }
        else {
            iss >> g.amount >> g.units >> ws;
            getline(iss, g.name, '\n');
            cout << g.name << "\n";
            ingredients.push_back(g);
        }
    }
    return ingredients;
}

bool itemsMatch(vector<Nutrient>& nut, vector<Ingredient>& ing) {
    int matchCount = 0;

    for (int i = 0; i < nut.size(); i++) {
        for (int j = 0; j < ing.size(); j++) {
            if (nut[i].name == ing[j].name) {
                cout << nut[i].name << " matched " << ing[j].name << endl;
                cout << "\n";
            }
            else {
                cout << nut[i].name << " didnt match " << ing[j].name << endl;
            }
        }
    }
    return true;
}

int main(int argc, char** argv) {
    vector<Nutrient> nutri;
    vector<Ingredient> ingri;
    Recipe rec;
    bool match;

    ifstream finNutr(argv[1]);
    ifstream finIngr(argv[2]);
    ifstream finReci(argv[2]);

    nutri = readNutrients(finNutr);
    ingri = readIngredients(finIngr);
    rec = readRecipe(finReci);

    match = itemsMatch(nutri, ingri);

    return 0;
}

bool itemsMatch()是造成麻烦的原因。这是最后一个输出:

graham crackers
milk chocolate
marshmallows
graham crackers didnt match graham crackers
graham crackers didnt match milk chocolate
graham crackers didnt match marshmallows
milk chocolate didnt match graham crackers
milk chocolate didnt match milk chocolate
milk chocolate didnt match marshmallows
cheese, swiss didnt match graham crackers
cheese, swiss didnt match milk chocolate
cheese, swiss didnt match marshmallows
marshmallows didnt match graham crackers
marshmallows didnt match milk chocolate
marshmallows matched marshmallows

可见,有几个字符串匹配,但由于某种原因,它说它们没有,我不知道为什么。

arg1内容

graham crackers; 2 squares 59
milk chocolate; 1 bar 235
cheese, swiss; 1 oz 108
marshmallows; 1 cup 159

arg2内容

S'mores
2
4 squares graham crackers
1 bar milk chocolate
2 large marshmallows

3 个答案:

答案 0 :(得分:1)

您发布的比较代码罚款。当然,你的函数总是会返回true,这没有意义,但这不是问题。

问题在于结构的数据,因此数据(例如您从中读取的文件)或用于将数据读取到结构的代码都存在缺陷。

打印结构以确认它们包含您认为它们的确切内容(当然是打印矢量的大小)或使用调试器,例如 gdb

专业提示:这里不是问题,但考虑更改原型:

bool itemsMatch(vector<Nutrient> nut, vector<Ingredient> ing)

到此:

bool itemsMatch(vector<Nutrient>& nut, vector<Ingredient>& ing)

因此,不是复制整个向量,而是只传递对它们的引用,对于大向量来说要快得多! =)

答案 1 :(得分:1)

我的猜测是你的输入文件有DOS行结尾,它是两个字符的序列:"\r\n"

当您使用getline时,它会读取\n,因此\r会包含在您从文件中读取的字符串中。这意味着从第二个文件中读取的成分是这些字符串:

S'mores\r
2\r
4 squares graham crackers\r
1 bar milk chocolate\r
2 large marshmallows

请注意,在最后一行之后没有"\r\n",因此“marshmallows”会被读取而没有\r回车符。

在另一个文件中,成分不在行的末尾,因此\r回车字符不会被读入name字符串中的营养素。这意味着当您比较要比较的字符串时:

"graham crackers" == "graham crackers\r" -> false
"milk chocolate" == "milk chocolate\r" -> false
"marshmallows" == "marshmallows" -> true

解决方案是手动剥离\r回车符,或转换输入文件以删除回车符(或停止使用Windows,这有愚蠢的约定并为初学者带来无穷无尽的问题)。

要删除\r个字符,您可以在每个getline之后执行此操作:

while (getline(fin, line)) {
    if (!line.empty() && line.back() == '\r')
        line.pop_back();

如果它存在,这将从行尾删除\r

或者如果你遇到过去并且无法使用C ++ 11:

while (getline(fin, line)) {
    if (!line.empty() && line[line.length()-1] == '\r')
        line.resize(line.length()-1);

答案 2 :(得分:-2)

您应该更改这样的代码然后测试,检查我的代码的语法我没有测试:)

auto itring = ing.begin();

for (auto itrnut = nut.begin(); itrnut != nut.end(); itrnut++, itring++ ) {
            if (itrnut->name == itring->name) {
                cout << itrnut->name << " matched " << itring->name << endl;
                cout << "\n";
        }
    }
相关问题