【问题标题】:C++ Cannot return all Variables that have been added to a Vector ListC ++无法返回已添加到向量列表中的所有变量
【发布时间】:2020-07-28 02:00:36
【问题描述】:

在我当前编写的程序中,我到了需要使用已通过文件读取的数据的阶段。其中一些数据包含数字元素,因此已经进行了适当的转换,以便将它们存储在字符串类型的向量中。到目前为止有效。

我有一个名为 robotsComplexity 的函数,它根据文件中的其他值计算一个值,这些值已经添加到向量列表中(所有代码都将在下面发布)。文本文件包含以下数据。

A:Head:1:2:15.
B:Torso:0:6:5.
C:Leg:0:4:6.
D:Arm:0:4:8.
E:Tail:0:6:2.

如下面的代码所示,该文件已被冒号和句号处的分隔符分隔,以首先分隔变量,然后是记录。变量已存储在它们各自的持有者中,如代码所示。名为 robotsComplexity 的函数包含一个 for 循环

for(std::size_t i=0; i< partsVector.size(); ++i) { 
 if(partsVector[i] == userChoice) {
   cout << userChoice << stoi(stringMaximum) << endl;
   }

我的代码的问题源于这个 for 循环。该程序能够遍历文件并重新识别相应值 A、B、C、D、E 的第一个变量 partCode(转换为 newChar)。因此,例如,当用户输入 A 它返回 A,输入 B 返回 B 等。现在我的问题来自于尝试打印存储在向量中的其他变量。在 cout

我在问是否有人可以创建/修复我的 for 循环,以便当 cout

例如,如果用户输入 A 作为零件代码,则输出应为

代码

cout << userChoice << partName << stringMaximum  << stringMinimum << stringComplexity << endl;

输出

A 
Head 
1 
2 
15

包含函数的文件

struct Part {
char partCode;
std::string partName;
int maximum;
int minimum;
int complexity;
} myPart;

std::vector<string> partsVector;
std::ifstream partsList("Parts.txt");

std::string outputFile = "output.txt";
std::string input;

std::string newChar;
std::stringstream convertChar;

std::string stringMaximum = std::to_string(myPart.maximum);
std::string stringMinimum = std::to_string(myPart.minimum);
std::string stringComplexity = std::to_string(myPart.complexity);

void readFile() //function to read Builders, Customers and Parts text file
{
 std::string line;

while (std::getline(partsList, line)) {
    line.pop_back();//removing '.' at end of line
    std::string token;
    std::istringstream ss(line);

    convertChar << myPart.partCode;
    convertChar >> newChar;

    // then read each element by delimiter
    int counter = 0;//number of elements you read
    while (std::getline(ss, token, ':')) {//spilt into different records
      switch (counter) {//put into appropriate value-field according to element-count

      case 0:
        newChar = token; //convert partCode from a char to a string 
        break;
      case 1:
        myPart.partName = token;
        break;
      case 2: 
      myPart.maximum =stoi(token);
        break;
      case 3: 
      myPart.minimum = stoi(token);
        break;
        case 4:
         myPart.complexity = stoi(token);
        break;
      default:
        break;
      }
      counter++;//increasing counter
    }

partsVector.push_back(newChar);
partsVector.push_back(myPart.partName);
partsVector.push_back(stringMaximum);
partsVector.push_back(stringMinimum);
partsVector.push_back(stringComplexity);

   } 
}

double robotComplexity() { 

double complexity;
string userChoice;

cout << "Enter a part code A ,B ,C ,D or E" << endl;
cin >> userChoice;

for(std::size_t i=0; i< partsVector.size(); ++i) { 
 if(partsVector[i] == userChoice) {
   cout << userChoice << stoi(stringMaximum) << endl;
   }
} 
} 

感谢您提供的任何帮助。如果需要任何进一步的解释,请随时询问。 PS 我知道全局变量不是最好用的,但是一旦我的函数正确运行,我将使用局部变量清理代码。

【问题讨论】:

  • minimal reproducible example 会让其他人帮助您。这个 sn-p 太长了,帮不上忙。
  • @LouisGo 提供的代码是程序运行和人们理解问题所需的最少代码量。
  • 你的 main 调用了 4 个函数。您的问题是否存在于所有 4 个功能中?如果答案是否定的,那么你的问题不是最小的。即使答案是肯定的,也只显示一个功能。我们不需要了解您的完整用例,只需了解代码 sn-p 中的特定用例即可。
  • @LouisGo 我会删除 main 并在有人询问时提供
  • 从我可以从您的代码中收集到的信息,我猜测您用于输出值的变量与您从文件中读取值的变量不同(例如,在最后一个代码中“sn- p",在将任何值读入myPart 之前,您从myPart.maximum 设置stringMaximum。这可以解释它,因为某些系统默认初始化 ints 为 0(虽然不是你想要依赖的东西)。

标签: c++ arrays file vector


【解决方案1】:

这里有几个问题,但你的主要问题是

std::string stringMaximum = std::to_string(myPart.maximum);
std::string stringMinimum = std::to_string(myPart.minimum);
std::string stringComplexity = std::to_string(myPart.complexity);

是全局变量,不是函数。它们只会在您的程序开始时被评估一次。所以你的readFile 已经在你给我们的代码中被破坏了。我要做的第一件事是删除全局状态(即删除所有全局变量)并修复不再编译的代码。

你会的

partsVector.push_back(stringMaximum);
partsVector.push_back(stringMinimum);

readFile 中无需设置这两个变量,因此您始终在向量中推送相同的值。

下一个问题是,为什么要使用字符串向量而不是 Part 向量?您已经将文件解析为 Part 对象,所以只需使用它们。此外,您希望通过查询Part.partCode 的用户输入来访问这些部分,因此我们可以使用以partCode 作为键的查找表(在本例中为std::unordered_map&lt;char, Part&gt;)。

总而言之,这将如下所示(readFile 中的内部 while 循环也是一场噩梦,所以我也删除了它):

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

struct Part
{
    char partCode = 0;
    std::string partName;
    int maximum = 0;
    int minimum = 0;
    int complexity = 0;
};

std::stringstream partsList(
    R"(A:Head:1:2:15.
B:Torso:0:6:5.
C:Leg:0:4:6.
D:Arm:0:4:8.
E:Tail:0:6:2.)");

std::string outputFile = "output.txt";
std::string input;

std::unordered_map<char, Part> readFile() //function to read Builders, Customers and Parts text file
{
    std::unordered_map<char, Part> parts;
    std::string line;

    while (std::getline(partsList, line))
    {
        line.pop_back(); //removing '.' at end of line
        std::string token;
        std::istringstream ss(line);
        Part part;

        std::getline(ss, token, ':');
        part.partCode = token[0];
        std::getline(ss, part.partName, ':');
        std::getline(ss, token, ':');
        part.maximum = std::stoi(token);
        std::getline(ss, token, ':');
        part.minimum = std::stoi(token);
        std::getline(ss, token, ':');
        part.complexity = std::stoi(token);

        parts.emplace(part.partCode, std::move(part));
    }

    return parts;
}

double robotComplexity(std::unordered_map<char, Part> const& parts)
{
    double complexity = 10;
    char partCode;

    std::cout << "Enter a part code A ,B ,C ,D or E" << std::endl;
    std::cin >> partCode;

    auto const& part = parts.at(partCode);
    std::cout << part.maximum;

    if (complexity > 100)
    {
        complexity = 100;
    }

    std::cout << "\nThe Robot Complexity is: " << complexity << std::endl;
    return complexity;
}

void writeFile() //writes to a file output.txt the end calculations.
{
}

int main()
{
    auto parts = readFile();
    writeFile();
    robotComplexity(parts);
    return 0;
}

【讨论】:

  • 是否需要包含文本文件内容的stringStream?
  • @DavidLing 不,您可以像以前一样用文件流替换它。事实上,任何流都可以。
  • 我讨厌痛苦,但是否可以使用矢量而不是地图来完成上述操作?我刚发现我不能使用地图
  • @DavidLing 当然。只需将parts.emplace 替换为parts.push_back(std::move(part)) 并将parts.at(partCode); 替换为*std::find_if(parts.begin(), parts.end(), [&amp;](auto&amp;&amp; p) { return p.partCode == partCode; });。它有点冗长,但行为(几乎)相同。
  • 你能举个例子吗?有点难以理解
猜你喜欢
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 2021-09-22
相关资源
最近更新 更多