从换行符和逗号

时间:2015-12-22 03:40:30

标签: c++ file

我正在尝试从txt文件中读取信息,但有些东西没有用。我需要读取每一行并将其保存在属于 Bilhete 类的变量中。

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

这是我的txt。

这代表一张票(葡萄牙语中的bilhete): - 所有者的名称 - 到期日 - 我可以参加的比赛。每个数字代表比赛的ID。我的项目中有一个竞赛班,但我不认为这个问题非常重要

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
            }


        }
    }

}

如何正确保存这些值?

祝你好运

2 个答案:

答案 0 :(得分: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可以为简单的文件流分离提供可选的分隔符。

答案 1 :(得分:0)

我首先要为2 4 8 16 32 64 128 256 512 1024 类重载operator>>,这样主体才能读取单个票证。然后我使用该运算符从流中读取票证。

标准已经定义了一个ticket(和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