1

我只需要一点文件解析方面的帮助。我们必须解析一个每行有 6 个字符串条目的文件,格式如下:

“字符串 1”、“字符串 2”、“字符串 3”、“字符串 4”、“字符串 5”、“字符串 6”

我的导师最近给了我们一小段代码作为“提示”,我应该使用它。不幸的是,我不知道如何让它工作。这是我的文件解析功能。

void parseData(ifstream &myFile, Book bookPtr[])
{

    string bookInfo;
    int start, end;
    string bookData[6];

    getline(myFile, bookInfo);
    start = -2;

    myFile.open("Book List.txt");

    for (int j = 0; j < 6; j++)
    {
        start += 3;
        end = bookInfo.find('"', start);
        bookData[j] = bookInfo.substr(start, end-start);
        start = end;
    }



}

所以我试图将 6 个字符串读入一个字符串数组。有人可以帮我完成整个过程吗?

4

2 回答 2

1
start = -2;
for (int j = 0; j < 6; j++)
{
    start += 3;
    end = bookInfo.find('"', start);
    bookData[j] = bookInfo.substr(start, end-start);
    start = end;
}

", "四个字符也是如此。前导结束引号在开始结束引号后面 3 个字符。

在循环入口处start指向最后一个结束引号。(在第一次进入循环时,它被伪造为-2指向虚构的“-1th”元素的右引号。)

所以我们从最后一个结束报价前进到下面的开始报价:

    start += 3;

然后我们使用 std::string::find 来查找结束引号:

    end = bookInfo.find('"', start);

偏移量告诉它忽略直到并包括该位置的所有字符。

然后我们有两个引号位置,start..end所以我们substr用来提取字符串:

    bookData[j] = bookInfo.substr(start, end-start);

然后我们将下一个循环的 start 更新为最后一个结束引号:

    start = end
于 2013-04-27T16:54:57.940 回答
0

为了您自己,请创建一个最小的示例。这以您作为示例给出的行的字符串开头,并以数组中的不同部分结尾。暂时不要从文件中加载, getline() 似乎对您有用,还是?然后,不要在函数开头声明您可能想要使用的每个变量。这不是古老的 C,你只需要这样做或引入额外的{}块。还有一件事很奇怪,那就是Book bookPtr[]. 这确实只是一个Book* bookPtr,即您没有将数组传递给函数,而只是一个指针。不要相信这种误导性的语法,这是一个谎言!无论如何,您似乎并没有使用指向未知类型对象的指针。

关于将行拆分为字符串,一种方法是定位双引号对。中间的一切都是弦之一,没有的一切都是无关紧要的。string 类有一个 find() 函数,它可以选择一个起始位置。起始位置总是在先前找到的位置之后。

您上面的代码似乎假设只有一个双引号、一个逗号、一个空格和另一个分隔两个字符串的双引号。这不是 100% 清楚的,我也会准备好处理多个空格或根本没有空格。另外,逗号有保证吗?双引号有保证吗?无论如何,保持简单。除非您对输入有更好的规范,否则只需假设只有引号之间的部分有所不同。

那么,究竟什么有效,什么无效?您需要提出更具体的问题并提供更详细的信息。上面的代码本身看起来并没有损坏,尽管有些地方有点不对劲。例如,您通常不会将 ifstreams 传递给函数,而是使用 istream 基类。在您的情况下,您从该文件中读取一行,然后使用相同的 fstream 对象打开另一个文件,这对我来说没有意义,因为在那之后您不再使用它。如果您只在本地需要该流,您将在那里创建并打开它(当然要处理错误!)并仅将文件名作为参数传递。

于 2013-04-27T17:02:22.697 回答