我尝试使用fscanf()从txt文件输入参数。 这是我的代码:
fpin = fopen("parameter_file.txt","r");
fscanf(fpin,"%d\n", &code_value);
fscanf(fpin,"%d\n", &origin_x);
fscanf(fpin,"%d\n", &origin_y);
fscanf(fpin,"%d\n", &dpi);
fscanf(fpin,"%d\n", &width);
fscanf(fpin,"%d\n", &height);
并且parameter_file.txt是(例如):
333
123
123
800
6
8
我想在每一行之后添加一些注释。例如:
333 //code_value
或123 //origin_x
我的问题是,当我添加一些字符时,fscanf()无法正常工作,因为我希望读取连续参数。
我试过了fscanf(fpin,"%[^a-z]%d\n", &code_value);
另一个问题是输入文件如下,我的代码怎么实现?
333 //code_value_1
123 //origin_x_1
123 //origin_y_1
800 //dpi_1
6 //width_1
8 //height_1
12 // code_value_2
10 //origin_x_2
20 //origin_y_2
800 //dpi_2
10 //width_2
10 //height_2
.
.
.
20 // code_value_n
10 //origin_x_n
20 //origin_y_n
800 //dpi_n
30 //width_n
30 //height_n
答案 0 :(得分:5)
如果格式总是每行一个数字,您可以使用:
fscanf(fpin, "%d%*[^\n]", &var);
%*[^\n]
将吞下所有字符直到换行符。 *
是抑制,^\n
表示除换行符之外的所有字符都是扫描集的一部分。
但是,如果新行紧跟在该号码后面,则旧样式输入将失败。更健壮的方法是首先将整行读入缓冲区,然后使用sscanf()
或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分配给不同的参数?
如果每个注释都描述了值所代表的含义,则可以使用map<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
}
}
我正在写这篇文章,所以可能会有错误,以及更好的方法。但是,这应该给你一般的想法。