2015-12-22 113 views
0

我想从txt文件中读取信息,但有些东西没有解决。我需要读取每行并将其保存在属于类Bilhete的变量中。阅读由换行符和逗号分隔的txt文件

Alexandre 
20/12/2015 
1,2,3,4 
Luis 
30/10/1990 
3,4,5,6 

这是我的txt。

这代表票(bilhete葡萄牙): - 所有者 的名字 - expirity日期 - 我有机会获得比赛。每个数字代表比赛的编号。在我的项目中有一个竞赛类,但我不认为这是非常重要的这个问题

void Campeonato::readFileBilhetes(string filename) { 


    ifstream ficheiro_leitura(filename.c_str()); 

    vector<Prova*> vecprovas = calendario->getProvas(); 
    vector <int> indices; //vector with competitions id 

    if(!ficheiro_leitura) 
     throw ErroNoFicheiro(filename); 
    else{ 
     string dono, data, provasNoBilhete, vendido; //owner, date, competitions in the ticket, 

     while (!ficheiro_leitura.eof()){ 

      getline(ficheiro_leitura, dono); 
      getline(ficheiro_leitura, data); 
      getline(ficheiro_leitura, provasNoBilhete); 


      stringstream dataSs; 
      date d; 
      dataSs << data; 
      int dia, mes, ano; //day, month, //year 
      char tmp; 
      dataSs >> dia >> tmp >> mes >> tmp >> ano; 

      if(dia < 1 || dia > 31|| mes < 1 || mes > 12 || ano < 1 || (dia > 28 && mes == 2) || (dia > 30 && mes == 4) || (dia > 30 && mes == 6) || (dia > 30 && mes == 9) || (dia > 30 && mes == 11)){ 
       cout << "Data invalida!"; 
      } 
      else{ 
       d.dia = dia; //day 
       d.mes = mes; //month 
       d.ano = ano; //year 
      } 



      string s1 = ""; 
      string s2= ""; 



      stringstream provasS; 
      int i = 0; 
      while (provasNoBilhete[i] != '\n' && provasNoBilhete[i] != '\0'){ 

       if(provasNoBilhete[i] == ','){ 
        int indice; 
        provasS.clear(); 
        provasS.str(""); 
        provasS.str(s2); 
        provasS >> indice; 
        indices.push_back(indice); 





       } 
       else 
        provasS << provasNoBilhete[i]; 


       ++i; 
       Bilhete *bi1 = new Bilhete(d, dono, indices); 
       inserirBilhete(*bi1); //insert 
      } 


     } 
    } 

} 

如何正确保存这些值?

问候

+1

你能澄清你遇到的问题吗? – badfilms

+0

[你不应该使用while(!ifstream.eof()'。](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong),这可能是你问题的根源。 – Beta

回答

0

我不知道在你的文件中读取当你有问题,但这里是展示了如何在你试图获取值的示例读取什么值。这将在名称中正确读入字符串,将日期写入单独的整数,并将竞争ID写入整数向量中。我发现使用iss.peek方法对调试stringstream非常有帮助。在这里,您可以看到我正在使用此方法来确保我正在读取有效文件。

此外,正如Beta所言,我会建议不要使用file.eof()。在条件循环中尝试使用getline

fstream infile(file); 
string linha, dono; 
int dia, mes, ano; 
vector<int> campeonatoIds; 

while (getline(infile, dono)) // get name and check status file stream 
{ 
    cout << dono << endl; 
    // read in date 
    getline(infile, linha); 
    int tmp; 
    istringstream iss (linha); 
    iss >> dia; 
    if (iss.peek() != '/') 
    { 
     cerr << "incorrectly formatted file" << endl; 
     exit(EXIT_FAILURE); 
    } 
    iss.ignore(); 
    iss >> mes; 
    if (iss.peek() != '/') 
    { 
     cerr << "incorrectly formatted file" << endl; 
     exit(EXIT_FAILURE); 
    } 
    iss.ignore(); 
    iss >> ano; 


    cout << dia << "/" << mes << "/" << ano << endl; 

    // read in competition ids 
    getline(infile, linha); 
    istringstream iss2(linha); 
    while (iss2.peek() != ',' && iss2.good()) 
    { 
     iss2 >> tmp; 
     cout << tmp << ","; 
     campeonatoIds.push_back(tmp); 
     iss2.ignore(); 
    } 
    cout << endl; 
} 

然而,我个人的事情,使用getline比在这种情况下使用stringstream更容易和更清洁。以下是使用getline重构的相同代码。

fstream infile(file); 
string linha, dono; 
int dia, mes, ano; 
vector<int> campeonatoIds; 

while (getline(infile, dono)) // get name and check status file stream 
{ 
    cout << dono << endl; 
    // read in date 
    getline(infile, linha); 
    istringstream iss (linha); 
    string tmpstr1; 
    getline(iss, tmpstr1, '/'); 
    dia = atoi(tmpstr1.c_str()); 

    getline(iss, tmpstr1, '/'); 
    mes = atoi(tmpstr1.c_str()); 

    getline(iss, tmpstr1, '/'); 
    ano = atoi(tmpstr1.c_str()); 

    cout << dia << "/" << mes << "/" << ano << endl; 

    // read in competition ids 
    getline(infile, linha); 
    istringstream iss2(linha); 
    string tmpstr2; 
    while (getline(iss2, tmpstr2, ',')) 
    { 
     campeonatoIds.push_back(atoi(tmpstr2.c_str())); 
    } 

    for (auto it : campeonatoIds) 
    { 
     cout << it << ",";  
    } 
    cout << endl; 
    campeonatoIds.clear(); 
} 

正如你所看到的,我在没有while循环,它可以让你检查文件的有效性,使用getline。另外,我认为使用getline可以让你提供一个可选的分隔符来简单分离文件流。

0

我会从operator>>中为ticket类重载012,因此它有正文读取单个票据。然后,我会使用该运算符从流中读取票据。

该标准已定义了get_tgime(和put_time)机械手来读取流的时间为struct tm,所以我们还不如用这些。

代码可能是这个样子:

friend std::istream &operator>>(std::istream &is, ticket &t) { 
    std::getline(is, t.name); 

    is >> std::get_time(&t.date, " %d/%m/%Y "); 

    std::string temp; 
    std::getline(is, temp); 

    t.events = parse_list<int>(temp); 
    return is; 
} 

parse_list会是这样这一般顺序:

template <class T> 
std::vector<T> parse_list(std::string const &in) { 
    T temp; 
    std::vector<T> ret; 

    std::istringstream buf(in); 

    while (buf >> temp) { 
     ret.push_back(temp); 
     buf.ignore(1); 
    } 
    return ret; 
} 

有了这些规定,读满ticket数据的文件,并把它所有成vector看起来像这样:

std::vector<ticket> tickets { std::istream_iterator<ticket>(input), 
    std::istream_iterator<ticket>() };