c ++处理来自输入文件的数据会创建无限循环

Posted

技术标签:

【中文标题】c ++处理来自输入文件的数据会创建无限循环【英文标题】:c++ treating data from input file creates infinite loop 【发布时间】:2016-07-14 02:18:25 【问题描述】:

我是 C++ 的初学者,正在做一个(据说很简单的)作业,但这让我头疼...

我熟悉 C# 和 Java,其中允许使用动态数组,并且存在诸如 foreach 循环之类的其他简洁事物...

该程序包括从如下所示的文件中读取数据:

5 约翰逊 5000 磨坊主 4000 达菲 6000 罗宾逊 2500 阿什顿 1800

第一行始终是“候选人”的数量,然后是该候选人的重复姓名/票数(分别为以下每一行)。 该程序有 20 个候选者的限制——我认为这是因为不允许使用动态数组,所以我们必须创建固定大小的数组来保存每种类型的数据。

我基本上希望读取第一行,将其存储在一个变量中,该变量将用作我的循环迭代限制,并将所有名称存储在一个数组中,然后将所有数字存储在第二个数组中以处理它们。

这是我在尝试读取文件时所做的一个小测试 sn-p。它可以工作,但会生成一个无限循环:(

int main() 
    string candidateNames[21];
    double votesReceivedPerCandidate[21];
    ifstream infile("votedata.txt");

    while (!infile.eof()) 
        string firstLine;
        int numberofCandidates;
        getline(infile, firstLine);
        numberofCandidates = atoi(firstLine.c_str());

        for (int x = 0; x < numberofCandidates; x++) 
            cout << "hello!";
        
    

我现在睡眠不足,甚至不确定我是否以正确的方式思考这个问题。

我的问题是:

    使用 C++,您将如何只读取第一行,然后将该行中的数字用作for 循环中的条件? (另外 - for 循环是最好的选择吗?你将如何设置它?)

    您将如何设置上述循环来读取文件并将一个条目存储到一个数组中,将下一个条目存储到第二个数组中,然后成对重复该过程? (就像你给两个人发牌一样)?

【问题讨论】:

while (!infile.eof())is always a bug。关于您的实际问题,have you tried talking to your rubber duck, yet? 对可调整大小的数组使用 std::vector。如果您不知道它会持续多久,只需使用 push_back。注意 ifstream::operator>> 读取一个单词。您可以考虑使用它代替 getline。一半的时间是一个单词,一半​​的时间是一个数字。 【参考方案1】:

C++ 有动态数组(通过std::vector)和foreach 循环(通过std::for_each()、range-based for loops 等)。

试试这样的:

#include <vector>
#include <string>
#include <fstream>
#include <limits>

struct candidate

    std::string name;
    double votes;
;

int main()

    std::vector<candidate> candidates;

    std::ifstream infile("votedata.txt");

    int numberofCandidates;
    if (infile >> numberofCandidates)
    
        infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        for (int x = 0; x < numberofCandidates; x++)
        
            candidate c;
            if (!std::getline(infile, c.name)) break;
            if (!(infile >> c.votes)) break;
            infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            candidates.push_back(c);
        
    

    // use candidates as needed...

    return 0;


如果你真的想变得棘手,你可以让 STL 为你循环文件,通过使用 std::copy()std::copy_n()std::istream_iteratorstd::back_inserter 作为输入/输出迭代器:

#include <vector>
#include <string>
#include <fstream>
#include <algorithm>

struct candidate

    std::string name;
    double votes;
;

std::istream& operator>>(std::istream &in, candidate &c)

    if (std::getline(in, c.name))
    
        if (in >> c.votes)
            in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    
    return in;


int main()

    std::vector<candidate> candidates;

    std::ifstream infile("votedata.txt");

    int numberofCandidates;
    if (infile >> numberofCandidates)
    
        infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        // using std::copy()...

        // ignoring numberofCandidates, read until EOF...
        std::copy(std::istream_iterator<candidate>(infile),
                 std::istream_iterator<candidate>(),
                 std::back_inserter(candidates));

        // using std::copy_n()...

        std::copy_n(std::istream_iterator<candidate>(infile),
                 numberofCandidates,
                 std::back_inserter(candidates));
    

    // use candidates as needed...

    return 0;


考虑到您还没有涵盖std::vector,您可能还没有涵盖STL算法,所以上面看起来更像是使用手动循环和2个固定数组而不是std::vector

#include <string>
#include <fstream>
#include <limits>

const int cMaxCandidates = 20;

int main()

    std::string candidateNames[cMaxCandidates];
    double candidateVotes[cMaxCandidates];
    int numberofCandidates = 0;

    std::ifstream infile("votedata.txt");

    int numberofCandidatesInFile;
    if (infile >> numberofCandidatesInFile)
    
        infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        for (int x = 0; (x < numberofCandidatesInFile) && (x < cMaxCandidates); x++)
        
            if (!std::getline(infile, candidateNames[x])) break;
            if (!(infile >> candidateVotes[x])) break;
            infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            ++numberofCandidates;
        
    

    // use candidateNames[] and candidateVotes[] up to max
    // numberofCandidates of elements as needed...

    return 0;

或者,使用动态分配的数组:

#include <string>
#include <fstream>
#include <limits>

int main()

    std::string *candidateNames = NULL;
    double *candidateVotes = NULL;
    int numberofCandidates = 0;

    std::ifstream infile("votedata.txt");

    int numberofCandidatesInFile;
    if (infile >> numberofCandidatesInFile)
    
        infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        candidateNames = new std::string[numberofCandidatesInFile];
        candidateVotes = new double[numberofCandidatesInFile];

        for (int x = 0; x < numberofCandidatesInFile; x++)
        
            if (!std::getline(infile, candidateNames[x])) break;
            if (!(infile >> candidateVotes[x])) break;
            infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            ++numberofCandidates;
        
    

    // use candidateNames[] and candidateVotes[] up to max
    // numberofCandidates of elements as needed...

    delete[] candidateNames;
    delete[] candidateVotes;

    return 0;

【讨论】:

哇 - 这么多的帮助!这超出了我的预期!!非常感谢 - 我会尝试这样做,看看它是否有效......感谢你向我展示了 c++ 中的向量是什么,但我们还没有涵盖它......说明需要 2 个数组,我必须通过那些数组也变成了函数......我对这些都没有问题我完全知道该怎么做但是你如何通过循环读取文件来创建2个数组?我将其描述为好像您正在向 2 个人发牌哈哈不确定您是否理解我的意思...谢谢您的所有帮助! 向量是数组的封装,你应该尽早学习它。但无论如何,我已经更新了我的答案,以展示如何将文件读入 2 个数组的示例。 谢谢哇!解决了... !!还有什么其他方式可以让我在其他任何地方投票给你吗?您刚刚为我的线性代数考试提供了几个小时的额外学习时间! :D 在您发布我的回复后,我在 5 分钟内完成了整个项目,如果您有兴趣查看整个项目,我很乐意向您展示结果。【参考方案2】:
#include <bits/stdc++.h>
using namespace std;

int main() 

        string candidateNames[21];
        double votesReceivedPerCandidate[21];
        ifstream infile("in.txt");

        int numberofCandidates;
        infile >> numberofCandidates;
        infile.get();

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

            getline(infile, candidateNames[i]);
            infile >> votesReceivedPerCandidate[i];

            for (int x = 0; x < numberofCandidates; x++) 
                cout << "hello!" << endl;
            
            cout << endl;
        
        return 0;
 

首先获取候选者的数量,然后使用 for 循环运行到此数量的候选者。对于每个数量的候选人,以这种方式取名字和选票。为了确保一切正常,我打印了 "hello" numberofcandidates * numberofcandidates 次。 希望这会有所帮助。

【讨论】:

使用infile.get() 丢弃第一行代码异味后的换行符,改用std::getline()。而且您不会在每次计票后阅读换行符。而且您没有验证文件包含不超过 21 个候选者,或者根本没有进行任何错误处理。你真的想为 每个 被读取的候选人输出hello X 次吗?那个输出循环不应该在阅读循环之外吗? 谢谢 Remy - YEP 应该在外面(现在要去喝咖啡了!!)

以上是关于c ++处理来自输入文件的数据会创建无限循环的主要内容,如果未能解决你的问题,请参考以下文章

c语言中怎样输入多组数据 每组数据个数不确定 每组数据占一行

C中具有共享队列的线程安全生产者/消费者

.nginx第一次的启动的时候会创建哪些文件

C语言中,如何实现从文件中读取数据(大量的数据)后,在循环体中使用,每次传递3个值到数组。

即使数据存在,Camel readLockMinLength = 0也会创建一个0长度的文件

C语言文件的概念和文件指针