【问题标题】:C++ Reading text file with delimiter into struct arrayC ++将带有分隔符的文本文件读入结构数组
【发布时间】:2017-06-09 23:38:29
【问题描述】:

我正在尝试从格式与此类似的文本文件中读取数据:

knife, object, 0
bag, object, 15
kitchen, room, 400

放入由结构组成的数组。这是我目前所拥有的,但它只读取第一个元素然后返回垃圾。

#include <iostream>
#include <fstream>
#include <string>


using namespace std;

struct itemlist
{
  string type;
  string selltype;
  int price;
  int diditsell=0;
};

int main()
{
  string filename;
  cout << "Please enter a file name. " << endl;
  cin >> filename;

  ifstream in(filename);
  itemlist c[100];
  for (int i=0;i<100;i++)
  {
      in >> c[i].type >> c[i].selltype >> c[i].price;
      cout << c[i].type << endl;
      cout << c[i].selltype << endl;
      cout << c[i].price << endl;
  }
}

我试图找到特别适合我正在尝试做的示例,但实施它们并没有解决问题。任何帮助将不胜感激。

【问题讨论】:

  • 检查读取是否成功:if (in &gt;&gt; c[i].type &gt;&gt; c[i].selltype &gt;&gt; c[i].price) { print stuff; } else { handle error; }
  • 哦,等一下!您需要解析逗号和空格吗?呸。这需要 std::getline (in, c[i].type, ','); 和一些额外的代码来分割空间。
  • 如果文件中的文件少于 100,您不想全部读取 100。你可以使用std::vector吗?
  • @user4581301 我被指示创建一个 100 的大小。使用 std::vector 似乎没有任何问题,但我的 C++ 技能不是很熟练。

标签: c++ arrays struct


【解决方案1】:

可见问题的症结在于

 for (int i=0;i<100;i++)

无论文件中是否有数据要加载到数组中,都会打印出整个 100 个元素的数组。

这可能是最简单的方法is with a std::vector。这是一个动态大小的数组。当你添加它时,它会变得更大,所以你不必担心它会溢出。我们会在最后回到它。

接下来您要做的是确保您正在成功读取文件。 Streams can be tested to see if they are valid

if (in)
{
    cout << "in is good!" << endl;
}

并且&gt;&gt; 运算符返回对流的引用,以便您可以

if (in >> data)
{
    cout << "data is good!" << endl;
}

如果读取数据后流仍然良好,则您知道文件至少将某些内容读入了正确类型的数据或可以转换为正确类型的数据。您有责任在读入后检查读取的值,以确保用户没有拼写错误或故意使程序崩溃。如果你想遍历很多东西,比如一个文件,你会得到这样的东西:

while (in >> c[i].type >> c[i].selltype >> c[i].price)

如果任何读取失败,则流将在测试时返回 false 并且循环将退出。

查看您的源数据,您需要处理空格和逗号。 &gt;&gt; 只知道如何处理空格,除非你要做很多额外的工作。你会读到的是

knife,
object,
0

我们不想要逗号。幸运的是,它是最后一个字符,所以处理它很容易。 C++11 std::string can be used like a stack,你可以直接弹出不需要的字符:

c[i].type.pop_back();
c[i].selltype.pop_back();

总而言之,这给了我们一个看起来像这样的循环

ifstream in(filename);
itemlist c[100];
int i = 0;
while (in >> c[i].type >> c[i].selltype >> c[i].price)
{
    c[i].type.pop_back();
    c[i].selltype.pop_back();
    cout << c[i].type << endl;
    cout << c[i].selltype << endl;
    cout << c[i].price << endl;
    i++;
}

但这可能会超出 100 元素数组的末尾,因此我们需要稍微更改 while 循环:

while (i < 100 && in >> c[i].type >> c[i].selltype >> c[i].price )

如果i 大于或等于100,则i &lt; 100 案例失败并且循环退出,甚至不尝试in &gt;&gt; c[i].type &gt;&gt; c[i].selltype &gt;&gt; c[i].price 并写入不存在的数组槽。

请记住保留i 的值,因为数组是愚蠢的。他们不知道自己有多饱。

但是使用vector,您不需要i 来计算或跟踪它的填充程度,并且您无需担心数组溢出,直到您的计算机内存不足。我们需要的是一个可以读取的临时变量,然后我们就可以开始了。

vector<itemlist> c;
itemlist temp;
while (in >> temp.type >> temp.selltype >> temp.price)
{
    temp.type.pop_back();
    temp.selltype.pop_back();
    cout << temp.type << endl;
    cout << temp.selltype << endl;
    cout << temp.price << endl;
    c.push_back(temp);
}

【讨论】:

  • 我非常感谢您的所有帮助。不过,我对这段代码有疑问。我注意到代码编译并运行后,程序窗口中没有显示任何内容。由于正在使用 cout,它不应该显示一些东西吗?对这个数组的调用将如何工作?当我简单地调用:'cout
  • @NickBearns 除了给您的开发环境的调试软件一个破解之外,没有任何建议。非常方便的工具,调试器。它应该在程序崩溃时停止并允许您检查程序的状态。这将为您提供更多信息,您可以使用它来解决问题或提出一个非常好的、有针对性的新问题。
  • 我似乎找到了错误。我的文件中的一个条目显示:水,而不是物体,0 问题源于第二个元素中的单词之间的空格。这会导致稍后出现问题,因为使用 in >> temp.type >> temp.selltype >> temp.price 似乎将价格保存为单词“object”,但由于它不是整数,因此无法正确存储.
  • @NickBearns 老鼠。如果您控制数据文件格式,则可以禁止使用空格,但最好切换到 std::getline,这样您就可以正确处理双手剑。今晚出现了一个类似的问题,你应该能够适应。 stackoverflow.com/a/41844212/4581301
【解决方案2】:

我遇到了同样的问题。 调试表明它正在读取第一个数组元素但跳到第二个元素并输出信息。从第一个元素。 通过使其读取第一个元素两次来解决此问题。 例如见下文。

我在播放器的数组中也有其他输入。 添加该行之后,一切都很好。 我必须对我读取的每个数组都这样做。 我查看了它正在读取的文本文件,果然 每个数组的开始前都有一个空行。 我不知道为什么编写文件的程序会这样做。 我没有在数组之前放置一个空行。 注意:不是让它读取第一个数组元素两次, 你也许可以让它读一个空行。

 for (int i = 0; i < PLAYER; i++)
    {
    getline(teamRosterIn, playerName[i]);
    cout << playerName[i] << endl;
    getline(teamRosterIn, playerName[i]);
    cout << playerName[i] << endl;
    }

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多