• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

如何从文件中读取列表与子列表?

c/c++ 来源:Povylas 7次浏览

的结构非常简单:如何从文件中读取列表与子列表?

  1. 要领
    1. 列表项 – 5
    2. 列表项 – 6
  2. 要领
    1. 名单item – 2
    2. 列表项 – 3

为了便于阅读我增加了一些分隔符,这是实际的文件:

>Point one 
item 1  | 150 
item 2  | 20 
>Point two 
item 1  | 150 
item 2  | 10 

而且我写了一个C++函数应该读它。但我用自己的逻辑纠缠在某个地方,犯了一个错误。能找到我吗?

ifstream fileR("file.txt"); 

    int i = 0; 
    getline(fileR, sTemp); 
    do { 
    if(!sTemp.empty() && sTemp[0]==DELIM){ 
     R[0][i] = sTemp.substr(1); 
     i++; 
    }else{ 
     j = 0; 
     do { 
      if(!sTemp.empty() && sTemp[0] != DELIM){ 
       string::const_iterator pos = find(sTemp.begin(), sTemp.end(), '|'); 
       string name(sTemp.begin(), pos); 
       string a_raw(pos + 1, sTemp.end()); 
       a_raw = trim(a_raw); 
       double amount(atof(a_raw.c_str())); 
       R[j+1][i].set(trim(name), amount); 
       j++; 
      }else{ 
       break; 
      } 
     }while(getline(fileR, sTemp)); 
    } 
    }while(getline(fileR, sTemp)); 

凡读值都交给并不重要,因为我试图简化这一功能,因为它实际上是一些容器与动态数组。我测试了他们,他们工作得很好。所以阅读有问题。它接缝读取第一个值很好,但之后它会造成一些混乱。
如果你认为我的尝试是一场完全灾难,我会欢迎提示如何使一个真正的工作功能。

编辑:
我有一个良好的夜间睡眠,我已经修好了。这里是一个wokrking版本:

bool read = true; 
    for(int i = 0; i<n; i++) { 
    if(read){getline(fileR, sTemp);}else{ read = true; } 
    if(!sTemp.empty() && sTemp[0]==DELIM){ 
     R[i].setName(sTemp.substr(1)); 
     i--; 
    }else{ 
     R[i].toFirstSubpoint(); 
     do { 
      if(!sTemp.empty() && sTemp[0] != DELIM){ 
       string::const_iterator pos = find(sTemp.begin(), sTemp.end(), '|'); 
       string name(sTemp.begin(), pos); 
       string a_raw(pos + 1, sTemp.end()); 
       a_raw = trim(a_raw); 
       double amount(atof(a_raw.c_str())); 
       R[i].setSubpoint(trim(name), amount); 
       R[i].toNextSubpoint(); 
      }else{ 
       read = false; 
       break; 
      } 
     }while(getline(fileR, sTemp)); 
    } 

我的最重要的错误是,我忘了,如果被选中状态,再循环进入下一个索引,并且不执行它的其他(否则)条件。

下面的答案实际上是更好的方法来做到这一点更简单,更容易理解,但这次我不能使用矢量,我猜测我的脚本应该快一点,因为它不使用它们。无论如何,下次我会遇到类似的情况,我将使用下面的解决方案。

===========解决方案如下:

你或许应该考虑使用解析库类似的boost ::精神,但是如果文件格式是可选的有很多的事情可以做,以使其更容易没有这些措施的分析,

考虑以下日期布局

MainPoint1 iname1 ivalue1 iname2 ivalue2 iname3 ivalue3 
MainPoint2 iname1 ivalue1 iname2 ivalue2 

这可以很容易地加载以下内容。

struct item{ 
    std::string name; 
    double value; 
}; 

std::ostream& operator<<(std::ostream& os, const item& i) 
{ 
    return os << i.name << " " << i.value; 
} 

std::istream& operator>>(std::istream& is, const item& i) 
{ 
    return is >> i.name >> i.value; 
} 

struct point{ 
    std::string value; 
    std::vector<item> items; 
}; 


std::istream& operator>>(std::istream& is, point& p) 
{ 
    std::string line; 
    std::getline(is, line); 
    std::stringstream ss(line); 
    ss >> p.value; 
    p.assign(
     std::istream_iterator<item>(ss), 
     std::istream_iterator<item>()); 
    return is; 
} 


std::ostream& operator<<(std::istream& os, const point& p) 
{ 
    os << p.value << " "; 
    std::copy(p.item.begin(), p.items.end(), 
     std::ostream_iterator<item>(os, " "), 
    return os; 
} 

int main() 
{ 
    /* 
    ** Deserailise 
    */ 
    std::ifstream in_file("infile.dat"); 
    std::vector<point> points(
     std::istream_iterator<point>(in_file), 
     std::istream_iterator<point>()); 


    /* 
    ** Serailise 
    */ 
    std::ofstream out_file("outfile.dat"); 
    std::copy(points.begin(), points.end() 
     std::ostream_iterator<points>(out_file, "\n")); 
} 

这是未经测试和未编译的,但在概念上它应该工作。

编辑:代码更改为符合名称和值的项目。


版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)