0

我正在尝试编写一个从文本文件中读取单行的函数。每行有两列或三列。我想知道最优雅/干净的方法。我需要使用不同分隔符的功能(\t,\n,' ',',',';')

我的方法工作正常,除了不同的分隔符。

例如输入:

6
0 0
1 1
2 2
3 3
4 4
5 5
10 
0 1 0.47
2 0 0.67
3 0 0.98
4 0 0.12
2 1 0.94
3 1 0.05
4 1 0.22
3 2 0.24
4 2 0.36
4 3 0.69

模式输入:

[total number of vertices]
[id-vertex][\separetor][name-vertex]
...
[total number of edges]
[id-vertex][\separator][id-neighbor][\separetor][weight]
...
*\separetor=\t|\n|' '|','|';'

我的做法:

void readStream(istream& is, const char separator) {
    uint n, m;
    is >> n;
    cout << n << endl;
    string name;
    uint vertexId, neighborId;
    float weight;
    while(!is.eof()) {
        for(uint i = 0; i < n; i++) {
            is >> vertexId >> name;
            cout << vertexId;
            cout << " " << name << endl;
        }
        is >> m;
        cout << m << endl;
        for(uint j = 0; j < n; j++) {
            is >> vertexId >> neighborId >> weight;
            cout << vertexId;
            cout << " " << neighborId;
            cout << " " << weight << endl;
        }
        break;
    }
}

概述:

  1. 问题:不同的分隔符。

  2. 其他优雅的解决方案:一般来说,有人对这个问题有其他优雅/干净的解决方案吗?

4

5 回答 5

1

您可以使用boost split它可以在您可以指定的多个分隔符上拆分字符串。

std::string = line;
std::vector<std::string> parts;

boost::split(parts, line, boost::is_any_of("\t\n,; "));
于 2013-09-18T18:58:42.303 回答
0

您可以使用(考虑到您的文件将始终采用上述格式)

fstream file;
file.open("abc.txt",ios::in);
int numOfVertices;
string line;
getline(file, line);
numOfVertices = stoi(line);
vector<int> xCoord;
vector<int> yCoord;
while((--numOfVertices)>=0) 
{
    string line;
    getline(file, line);
    std::size_t prev = 0, pos;
    pos = line.find_first_of(" ';", prev);
    xCoord.push_back(stoi(line.substr(prev, pos-prev)));
    prev = pos+1;
    pos = line.find_first_of(" ';", prev);    //considering some of the delimiters
    yCoord.push_back(stoi(line.substr(prev, pos-prev)));
}

这是添加顶点。同样,您也可以提取边缘。

于 2013-09-18T16:29:00.283 回答
0

如果您确定分隔符不是空格,您可以将它们扔进垃圾字符串中(例如以下情况下的分隔符)

is >> vertexId >> separator >> neighborId >> separator >> weight;
于 2013-09-18T16:33:07.103 回答
0

以下代码可能有用:

int t1,t2;
double t3;//global variables...
void parse_Vertex_Line(char *str)
{
     int tmp=0;
     char *p=str;
     //extract the vertex-id
     while(*p >='0' && *p <='9')
        tmp = tmp*10 + *(p++) -'0';
     t1=tmp;
     tmp=0;
     p++;
     //now extract the vertex-name..
     while(*p >='0' && *p <='9')
        tmp = tmp*10 + *(p++) -'0';
     t2=tmp;
     return;
}

void parse_Edge_Line(char *str)
{
     //extracting the first two numbers is just the same...
     int tmp=0;
     char *p=str;
     //extract the first vertex-id
     while(*p >='0' && *p <='9')
        tmp = tmp*10 + *(p++) -'0';
     t1=tmp;
     tmp=0;
     p++;
     //now extract the second vertex-id..
     while(*p >='0' && *p <='9')
        tmp = tmp*10 + *(p++) -'0';
     t2=tmp; 
     p++;
     //but extracting a double value is a bit different...
     //extract the weight...
     int before_decimal=0, after_decimal=0;
     while(*p!='.')
         before_decimal = before_decimal*10 + *(p++) -'0';
     p++;
     int no_of_digits=0;
     while(*p>='0' && *p<='9')
     {
         after_decimal = after_decimal*10 + *(p++) -'0';
         no_of_digits++;
     }
     //assign it to the global double variable...
     t3 = before_decimal + (after_decimal/pow(10.0, no_of_digits));
}

现在你要做的是首先获得number of vertices(n). 接下来阅读每一n行。parse_Vertex_Line每次调用该函数。然后每次阅读number of edges并类似地调用。parse_Edge_Line提取值并存储它们。

此代码适用于几乎所有分隔符。希望这对你来说看起来很优雅。

于 2013-09-18T16:39:14.707 回答
0

我针对这种情况修改了我的其他帖子:覆盖 istream 运算符 >> 并修改分隔符(对此的解释是此处接受的解决方案的第一个变体,用于可能的实现)。

通常,您可以处理不需要的分隔符的一种方法是将它们变成空格!

我的方法允许对来自 istream 的操作“>>”使用新的分隔符:

struct delimiterIsSpace : ctype<char> {
    delimiterIsSpace() : ctype<char>(get_table()) {}
    static mask const* get_table() {
        static mask rc[table_size];
        rc[';'] = ctype_base::space;
        rc[','] = ctype_base::space;
        rc[' '] = ctype_base::space;
        rc['\t'] = ctype_base::space;
        rc['\n'] = ctype_base::space;
        return &rc[0];
    }
};

如何使用:

cin.imbue(locale(cin.getloc(), new delimiterIsSpace));

for (int a, b; cin >> a >> b; ) {
    cout << "a=" << a << " b=" << b << "\n";
}
于 2013-09-20T14:23:59.757 回答