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

Comparing string elements of two vector<Structs>

本文关键字:lt Structs gt 元素 字符串 向量 两个 比较      更新时间:2023-10-16

接着我之前的问题:

从 void 函数访问局部变量

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

这是我当前的代码:

#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

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

参数 1 内容

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

参数2

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

我的猜测是您的输入文件具有 DOS 行尾,这是两个字符的序列:"rn"

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

S'moresr
2r
4 squares graham crackersr
1 bar milk chocolater
2 large marshmallows

请注意,这在最后一行之后没有"rn",因此读取"棉花糖"时没有r回车符。

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

"graham crackers" == "graham crackersr" -> false
"milk chocolate" == "milk chocolater" -> 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);

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

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

要么打印你的结构,确认它们完全包含你认为它们的作用(当然打印你的向量的大小),要么使用调试器,例如gdb


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

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

对此:

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

这样,您就不必复制整个向量,而只需传递对它们的引用,这对于大向量来说要快得多! =)

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

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";
}
}