AFAIK,没有什么可以开箱即用。但是您拥有自己构建它的所有工具
C 方式
您将这些行读入一个 char *(带有cin.getline()),然后使用 strtok 和 strcpy
getline方式
getline 函数接受第三个参数来指定分隔符。您可以利用它通过istringstream 分割线路。类似的东西:
int main() {
std::string line, temp;
std::ifstream myfile("file.txt");
std::getline(myfile, line);
while (myfile.good()) {
empdata data;
std::getline(myfile, line);
if (myfile.eof()) {
break;
}
std::istringstream istr(line);
std::getline(istr, temp, '|');
data.sl = ::strtol(temp.c_str(), NULL, 10);
std::getline(istr, temp, '|');
data.empNO = ::strtol(temp.c_str(), NULL, 10);
istr.getline(data.name, sizeof(data.name), '|');
istr.getline(data.department, sizeof(data.department), '|');
istr.getline(data.band, sizeof(data.band), '|');
istr.getline(data.location, sizeof(data.location), '|');
}
return 0;
}
这是上一个的C++版本
寻找途径
您将这些行读入一个字符串(就像您目前所做的那样)并使用string::find(char sep, size_t pos) 查找下一次出现的分隔符并将数据(从 string::c_str() )复制到子字符串开头和分隔符之间的字段到您的字段
手动方式
你只是迭代字符串。如果字符是分隔符,则将 NULL 放在当前字段的末尾并传递到下一个字段。否则,您只需在当前字段的当前位置写入字符即可。
选择哪个?
如果你更习惯其中之一,坚持下去。
以下只是我的意见。
getline 方式将是最简单的编码和维护方式。
寻找方式是中等水平。还是比较高的,避免使用istringstream。
手动方式将非常低级,因此您应该对其进行结构化以使其可维护。例如,您可以将行明确描述为具有最大大小和当前位置的字段数组。由于您同时拥有 int 和 char[] 字段,因此会很棘手。但是您可以轻松地以您想要的方式配置它。例如,您的代码只允许 department 字段使用 20 个字符,而第 2 行中的 Research and Development 更长。如果不进行特殊处理,getline 方式会使istringstream 处于不良状态,不会再读取任何内容。而且就算你清空了状态,你也会处于不利的地位。所以你应该先读入std::string,然后将开头复制到char *字段中。
这是一个工作手册实现:
class Field {
public:
virtual void reset() = 0;
virtual void add(empdata& data, char c) = 0;
};
class IField: public Field {
private:
int (empdata::*data_field);
bool ok;
public:
IField(int (empdata::*field)): data_field(field) {
ok = true;
reset();
}
void reset() { ok = true; }
void add(empdata& data, char c);
};
void IField::add(empdata& data, char c) {
if (ok) {
if ((c >= '0') && (c <= '9')) {
data.*data_field = data.*data_field * 10 + (c - '0');
}
else {
ok = false;
}
}
}
class CField: public Field {
private:
char (empdata::*data_field);
size_t current_pos;
size_t size;
public:
CField(char (empdata::*field), size_t size): data_field(field), size(size) {
reset();
}
void reset() { current_pos = 0; }
void add(empdata& data, char c);
};
void CField::add(empdata& data, char c) {
if (current_pos < size) {
char *ix = &(data.*data_field);
ix[current_pos ++] = c;
if (current_pos == size) {
ix[size -1] = '\0';
current_pos +=1;
}
}
}
int main() {
std::string line, temp;
std::ifstream myfile("file.txt");
Field* fields[] = {
new IField(&empdata::sl),
new IField(&empdata::empNO),
new CField(reinterpret_cast<char empdata::*>(&empdata::name), 20),
new CField(reinterpret_cast<char empdata::*>(&empdata::department), 20),
new CField(reinterpret_cast<char empdata::*>(&empdata::band), 3),
new CField(reinterpret_cast<char empdata::*>(&empdata::location), 20),
NULL
};
std::getline(myfile, line);
while (myfile.good()) {
Field** f = fields;
empdata data = {0};
std::getline(myfile, line);
if (myfile.eof()) {
break;
}
for (std::string::const_iterator it = line.begin(); it != line.end(); it++) {
char c;
c = *it;
if (c == '|') {
f += 1;
if (*f == NULL) {
continue;
}
(*f)->reset();
}
else {
(*f)->add(data, c);
}
}
// do something with data ...
}
for(Field** f = fields; *f != NULL; f++) {
free(*f);
}
return 0;
}
它直接健壮,高效且可维护:添加字段很容易,并且可以容忍输入文件中的错误。但它比其他的要宽松得多,并且需要更多的测试。所以我不建议在没有特殊原因的情况下使用它(需要接受多个分隔符、可选字段和动态顺序,...)