问题 旧的(类C)fscanf方法的现代等价(C ++)样式是什么?


如果我想在使用分号分隔符读取文件时将旧C代码“升级”为更新的C ++,那么最佳选择是什么:

/* reading in from file C-like: */
fscanf(tFile, "%d", &mypost.nr); /*delimiter ; */
fscanf(tFile, " ;%[^;];", mypost.aftername);/* delimiter ; */
fscanf(tFile, " %[^;]", mypost.forename);   /*delimiter ; */
fscanf(tFile, " ;%[^;];", mypost.dept);/*delimiter ; */
fscanf(tFile, " %[^;];", mypost.position);/* delimiter ; */
fscanf(tFile, "%d", &mypost.nr2);

//eqivalent best C++ method achieving the same thing?

7341
2018-03-29 11:32


起源

我想知道fscanf有多严格?如果您在带有forename的行上读取分号的所有字符,下一行怎么能在分号前读取空格? - 另外, fscanf 如果您还可以指定要在某处读取的最大字符数,那可能不会那么糟糕。 - UncleBens


答案:


你可以为你的struct重载istream上的右移运算符,所以:

std::istream& operator>>(std::istream& is, mypost_struct& mps) {
    is >> mps.nr;
    is.ignore(1, ';');
    is.getline(mps.forename, 255, ';');
    is.getline(mps.aftername, 255, ';');
    is >> mps.dept;
    is.ignore(1, ';');
    is >> mps.position;
    is.ignore(1, ';');
    is >> mps.nr2;

    return is;
}

随后,输入就像 is >> mypost;,哪里 is 是您打开的文件。

编辑:@UncleBens感谢您指出这一点,我忘了考虑空间。我已经更新了答案,假设forename和aftername可能包含空格。关于分隔符的双重引用,这有点令人尴尬......

我只是使用结构定义检查它,如下所示:

struct mypost_struct {
    int nr;
    char forename[255], aftername[255];
    int dept, position, nr2;
};

..结果如预期。


11
2018-03-29 11:49



我想知道所有的赞成是什么。提供超载的想法 >> 很好,但实施(怎么样 读取分隔输入)完全被打破。 ignore 没有这种形式,即使你修复它,也不会改变它的行为 istream.operator>> 并使用“;”作为分隔符。如果输入也用空格分隔并且没有字符串包含多个单词,那么它将起作用。 - UncleBens
感谢您指出了这一点 :) - susmits


正如@susmits所说,但你也可以使用返回的流作为条件,如:

if (is >> mps.nr && is.ignore(1, ";") && is >> mps.aftername && ...) {
   // all is well ...
} else {
   // bad input format
}

甚至:

if (is >> mps.nr >> ignore(";") >> mps.aftername >> ...) {
    // all is well ...
} else {
    // bad input format
}

3
2018-03-29 11:59





如果我愿意,最好的选择是什么   “升级”旧的C代码到更新的C ++ ......?

恕我直言,这样做的最好方法是逐行读取文件并使用 用于解析的正则表达式


1
2018-03-29 17:54