如果格式总是每行一个数字,您可以使用:
fscanf(fpin, "%d%*[^\n]", &var);
将%*[^\n]
吞噬所有字符直到换行符。*
是抑制,表示除换行符之外的^\n
所有字符都是扫描集的一部分。
但是,如果换行符紧跟在数字后面,这将在您的旧样式输入中失败。更健壮的方法是先将整行读入缓冲区,然后使用sscanf()
or解析缓冲区strtol()
。
char buf[MAX_LINE_LENGTH];
if (fgets(buf, sizeof(buf), fpin) != 0) {
if (sscanf(buf, "%d", &var) == 1) {
/* ... */
} else {
/* ...handle parse error */
}
} else {
/* ...handle file read error */
}
在 C++ 中,可以使用getline()
和类似地完成istringstream
。
std::string line;
std::istringstream iss;
if (std::getline(std::cin, line)) {
iss.str(line);
if (iss >> var) {
//...
} else {
//...handle scan error
}
} else {
//...handle read error
}
在评论中,你问:
如何将每个 cin 分配给不同的参数?
如果每个注释都描述了值所代表的内容,则可以使用 amap<string, int>
创建名称与值的关联。由于注释不遵循常规格式,因此您必须在解析时变得棘手。
C 版本使用数组来存储关联。然后,您可以稍后对其进行排序(使用qsort()
)并在需要查找时对其执行二进制搜索(使用bsearch()
)。
struct value_item {
char name[MAX_NAME_SIZE];
int value;
};
struct value_item value_map[MAX_VALUE_MAP];
size_t value_map_size = 0;
while (fgets(buf, sizeof(buf), fpin) != 0) {
const char *slash2 = strstr(buf, "//");
if (slash2 && slash2[2] != '\0') {
sscanf(buf, "%d", &value_map[value_map_size].value);
sscanf(slash2+2, "%s", value_map[value_map_size].name);
++value_map_size;
} else {
/* ...handle parse error */
}
}
C++ 版本看起来很相似。C++ 提供了map
,您可以使用它轻松地创建关联。
std::map<std::string, int> value_map;
while (std::getline(std::cin, line)) {
std::string::size_type n = line.find("//");
if (n != std::string::npos && line.size() > (n+2)) {
int value;
std::string name;
iss.str(line);
iss >> value;
iss.str(line.substr(n+2));
iss >> name;
value_map[name] = value;
} else {
//...handle parse error
}
}
我是在脑海中写下这个,所以可能会有错误,还有更好的方法来做到这一点。但是,这应该给你一个大致的想法。