2012-03-13 74 views
1

的結構非常簡單:如何從文件中讀取列表與子列表?

  1. 要領
    1. 列表項 - 5
    2. 列表項 - 6
    3. ...
  2. 要領
    1. 名單item - 2
    2. 列表項 - 3
    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)); 
    } 

我的最重要的錯誤是,我忘了,如果被選中狀態,再循環進入下一個索引,並且不執行它的其他(否則)條件。

下面的答案實際上是更好的方法來做到這一點更簡單,更容易理解,但這次我不能使用矢量,我猜測我的腳本應該快一點,因爲它不使用它們。無論如何,下次我會遇到類似的情況,我將使用下面的解決方案。

回答

2

你或許應該考慮使用解析庫類似的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

感謝您的迴應,但每個子列表項都由兩個值組成一個名稱和一個雙變量。 – Povylas 2012-03-14 00:47:12

+0

@Povylas只是申請我遞交給你的東西,而不是一個項目是一個std :: string使它自己的結構與它自己的操作<<。我試試並證明,現在 – 111111 2012-03-14 16:46:58

+0

@Povylas請參閱推薦的代碼。 – 111111 2012-03-14 16:51:43