1

我在从一个文件中读取我真的不应该在家庭作业中使用的输入时遇到了一些问题。在之前的分配中,我使用了非常相似的代码(唯一改变的是值被推到的地方)。我收到了一个带有以下输入的文本文件:

10
3 6 4 9 0 7 8
8 5 3 7 3 4 -2
5 10 2 8 1 4 1
2 6 -3 1 3 7 1
1 10 -1 2 2 4 -2
10 9 -3 1 3 7 2 5 1
7 3 0 10 1 2 1 8 2
9 6 6 3 4 10 7
4 8 5 1 9 5 6
6 2 4 3 0 9 0

第一行是上图中存在的顶点数。在之后的每一行中,第一个数字是它用于哪个顶点,下一个数字是它连接到哪个顶点,后面的一个是该边的权重。该行重复顶点、权重直到行尾(即,第一行用于顶点 3,它的边为 6,权重为 4,边为 9,权重为 0,等等)。我使用一维向量来表示使用行主要符号的矩阵。我遇到的问题是我的行变量似乎根本没有更新。目前,我从 while 循环中的最后一行获得以下输出,该循环实际上将数据插入向量中。

3:  6: 4
3:  9: 0
3:  7: 8
3:  8: 5
3:  3: 7
3:  3: 4
3:  -2: 5
3:  10: 2
3:  8: 1
3:  4: 1
3:  2: 6
3:  -3: 1
3:  3: 7
3:  1: 1
3:  10: -1
3:  2: 2
3:  4: -2
3:  10: 9
3:  -3: 1
3:  3: 7
3:  2: 5
3:  1: 7
3:  3: 0
3:  10: 1
3:  2: 1
3:  8: 2
3:  9: 6
3:  6: 3
3:  4: 10
3:  7: 4
3:  8: 5
3:  1: 9
3:  5: 6
3:  6: 2
3:  4: 3
3:  0: 9
3:  0: 9

我的行变量似乎卡在了 3 中,就像 input.peek() 一样,while 循环的条件永远不会看到换行符。真正令人困惑的部分是,在类似的任务中,这段代码可以很好地遍历输入文件并将内容填充到它们应该去的地方。我很困惑,所以如果有人能指出我正确的方向,我会非常感激。如果我过于冗长,我提前道歉。

我的代码如下。

if(input.is_open()) // making sure the input is open
{
    input >> nodeCount; //Grabbing the number of nodes from the first value of the file

    for(int i = 1; i < nodeCount*nodeCount; i++)
    {
        edgeList.push_back(graphNode());
        edgeList[i].value = infinity;
        edgeList[i].isInfinity = true;
        edgeList[i].pred = -1;
    }

    //Putting data from the file into the vector array
    while(!input.eof())
    {
        input >> row; //For each cycle through the list, we grab the first number on the line to get which x value (start vertex) we're working with
        while(input.peek() != '\n' && !input.eof())
        {
            input >> col;
            input >> edgeList[((row-1)*nodeCount)+(col-1)].value;
            edgeList[((row-1)*nodeCount)+(col-1)].isInfinity = false;
            edgeList[((row-1)*nodeCount)+(col-1)].pred = row;
            cout << row << ": " << " " << col << ": " << edgeList[((row-1)*nodeCount)+(col-1)].value << endl;
        }

    }
    input.close(); //Closing our input file since we don't need it anymore
}
4

2 回答 2

2

通过查看您吐出的数字,很明显这种情况在文件结束之前永远不会评估为假:

input.peek() != '\n' && !input.eof()

我的问题是 - 你使用的是 windows 风格、unix 风格还是 mac 风格的行尾?是否有更好的方法来确定不依赖于假设它们采用某个 ASCII 值的行结束位置?

于 2013-04-16T04:30:07.327 回答
0

The best way to read a line is to actually read the line.

std::string  line;
std::getline(input, line);

You can then parse the numbers out of the line.

std::stringstream linestream(line);
int node;
linestream >> node;

int dst, weight;
while(linestream >> dst >> weight)
{
    // Do Stuff
}

You should be careful:

while(!input.eof())

This is an anti-pattern. You have to be careful as if the stream goes into an error state the test will never become true and thus potentially leaving you in an infinite loop.

So your code should look like this:

int linesToRead;
input >> linesToRead;    

std::string  line;
for(;std::getline(input, line) && linesToRead;--linesToRead)
{
    // If there is a chance of an empty line
    // you may want to check here.

    std::stringstream linestream(line);
    int node;
    linestream >> node;

    int dst, weight;
    while(linestream >> dst >> weight)
    {
        // Do Stuff
    }
}

Manually closing the file is not good practice.

input.close();

Potentially the streams can be set to throw on error. What happens if you call close() and it throws? Even if you are in normal mode and it just generates an error on close(). What are you planning on doing? Best to let the destructor close the file and handle the error conditions for you. see here

于 2013-04-16T08:29:28.517 回答