Как прочитать день рождения с символами "/" и ":" из файла .txt? - PullRequest
0 голосов
/ 27 марта 2011

Я пишу программу на c ++ и должен прочитать некоторые данные из файла .txt. Формат выглядит следующим образом: "name gender DD/MM/YYYY HH:MM:SS"

Я знаю, как читать файл .txtи процитирую слова одно за другим, но я не знаю, как обращаться с символами «/» или «:».
Я должен сравнить возраст двух человек.помощь!

Ответы [ 5 ]

2 голосов
/ 27 марта 2011

Это одна из тех задач, которая действительно намного проще с чем-то вроде sscanf:

sscanf(input_string, 
       "%s %s %d/%d/%d %d:%d:%d", 
       name, gender, &day, &month, &year, &hour, &minute, &second);

Вы можете использовать iostreams, но не так легко.У вас есть пара основных вариантов.Одним из них является использование locale с ':' и '/', определенными в качестве пробела, что позволит вам просто передавать значения в потоковом режиме и игнорировать разделители (но не будет предупреждать вас о некоторых типах неправильного форматирования, таких какзамена '/' вместо ':' или наоборот.

Другая возможность - явно прочитать эти символы и (если вы выберете) проверить их, сравнив каждый разделитель с тем, что вы ожидаете.действительно серьезно относимся к тому, чтобы гарантировать, что данные находятся в ожидаемом формате, это, вероятно, путь.

1 голос
/ 27 марта 2011

В C вы бы использовали sscanf () или, более точно, fscanf (), но эти функции считаются плохим стилем в C ++.

Я бы предложил что-то вроде этого:

struct SData 
{
    std::string sName;
    std::string sGender;
    int nDay;
    int nMon;
    int nYear;
    int nHour;
    int nMin;
    int nSec;
};

bool ReadRecord(std::istream &istr, SData &data)
{
    istr >> data.sName
         >> data.sGender
         >> data.nDay;
    istr.ignore(1);       // '/'
    istr >> data.nMon;
    istr.ignore(1);       // '/'
    istr >> data.nYear
         >> data.nHour;
    istr.ignore(1);       // ':'
    istr >> data.nMin;
    istr.ignore(1);       // ':'
    istr >> data.nSec;

    return istr.good();
}

Обновление

Следующий пример упрощает использование, исключая структуру

#include <iostream>
#include <fstream>
#include <string>

bool ReadRecord(std::istream &istr, 
                std::string &sName,
                std::string &sGender,
                int &nDay,
                int &nMon,
                int &nYear,
                int &nHour,
                int &nMin,
                int &nSec)
{
    istr >> sName
         >> sGender
         >> nDay;
    istr.ignore(1); // '/'
    istr >> nMon;
    istr.ignore(1); // '/'
    istr >> nYear
         >> nHour;
    istr.ignore(1); // ':'
    istr >> nMin;
    istr.ignore(1); // ':'
    istr >> nSec;

    return istr.good();
}

int main()
{
    std::string sName0, sGender0, sName1, sGender1;
    int nDay0, nMon0, nYear0, nDay1, nMon1, nYear1;
    int nHour0, nMin0, nSec0, nHour1, nMin1, nSec1;
    const char szFileName[] = "MyData.txt";

    std::ifstream istr(szFileName);
    if (!istr.is_open())
    {
        std::cerr << "Cannot open file\n";
        return 1;
    }
    if (!ReadRecord(istr, sName0, sGender0, nDay0, nMon0, nYear0, nHour0, nMin0, nSec0))
    {
        std::cerr << "Cannot read file\n";
        return 1;
    }
    if (!ReadRecord(istr, sName1, sGender1, nDay1, nMon1, nYear1, nHour1, nMin1, nSec1))
    {
        std::cerr << "Cannot read file\n";
        return 1;
    }
    std::string sYounger;

    if (nYear0 == nYear1)
    {
        if (nMon0 == nMon1)
        {
            if (nDay0 == nDay1)
            {
                if (nHour0 == nHour1)
                {
                    if (nMin0 == nMin1)
                    {
                        if (nSec0 > nSec1)
                        {
                            sYounger = sName0;
                        }
                        else if (nSec0 < nSec1)
                        {
                            sYounger = sName1;
                        }
                    } 
                    else if (nMin0 > nMin1)
                    {
                        sYounger = sName0;
                    }
                    else if (nMin0 < nMin1)
                    {
                        sYounger = sName1;
                    }
                }
                else if (nHour0 > nHour1)
                {
                    sYounger = sName0;
                }
                else if (nHour0 < nHour1)
                {
                    sYounger = sName1;
                }
            }
            else if (nDay0 > nDay1)
            {
                sYounger = sName0;
            }
            else if (nDay0 < nDay1)
            {
                sYounger = sName1;
            }
        }
        else if (nMon0 > nMon1)
        {
            sYounger = sName0;
        }
        else if (nMon0 < nMon1)
        {
            sYounger = sName1;
        }
    }
    else if (nYear0 > nYear1)
    {
        sYounger = sName0;
    }
    else if (nYear0 < nYear1)
    {
        sYounger = sName1;
    }

    if (sYounger.empty())
    {
        std::cout << "The ages are the same\n";
    }
    else
    {
        std::cout << sYounger << "is younger\n";
    }

    return 0;
}
1 голос
/ 27 марта 2011

Посмотрите на следующую ссылку.Это решит вашу проблему.

0 голосов
/ 27 марта 2011

Вдохновленный Как разбить строку? Я решил сделать снимок.

Учитывая данные ниже:

Файл: date.txt

james male 01/02/1987 04:01:02
jerry male 11/06/1965 08:03:04
jon male 21/10/1977 12:05:06

Следующее приложение анализирует каждую строку файла и сохраняет информацию во временном объекте с именем dude , а затем добавляет ее в people_list . Синтаксический анализ даты / времени выполняется через strtok , что является хорошей функцией для разделения строки на токены. В конце мы перебираем найденную векторную печать.

#include <iostream>
#include <string>
#include <fstream>
#include <iterator>
#include <sstream>
#include <vector>
#include <algorithm>
#include <string.h>

using namespace std;

typedef struct _time
{
    int h; // hour
    int m; // minute
    int s; // seconds
} Time;

typedef struct _date
{
    int y; // year
    int m; // month
    int d; // day
} Date;

class Person
{
public:
    string name;
    string gender;
    Time time;
    Date date;
};


int main()
{
    ifstream in("dates.txt");

    vector<Person> people_list;

    string line;
    while (getline(in,line))
    {
        if (line.empty())
        {
            continue;
        }

        vector<string> tmp;
        istringstream iss(line);

        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tmp));

        // Parsing name and gender (easy)
        Person dude;
        dude.name = tmp[0];
        dude.gender = tmp[1];

        // Date
        char delim_slash[] = "/";
        char* result = NULL;
        result = strtok(const_cast<char*>(tmp[2].c_str()), delim_slash);
        dude.date.d = atoi(result);
        result = strtok(NULL, delim_slash);
        dude.date.m = atoi(result);
        result = strtok(NULL, delim_slash);
        dude.date.y = atoi(result);

        // Time
        char delim_colon[] = ":";
        result = strtok(const_cast<char*>(tmp[3].c_str()), delim_colon);
        dude.time.h = atoi(result);
        result = strtok(NULL, delim_colon);
        dude.time.m = atoi(result);
        result = strtok(NULL, delim_colon);
        dude.time.s = atoi(result);

        people_list.push_back(dude);
    }

    for (int i = 0; i < people_list.size(); i++)
    {
        cout << "Name: " << people_list[i].name << endl;
        cout << "Gender: " << people_list[i].gender << endl;
        cout << "Date: " << people_list[i].date.d << "/" <<
                            people_list[i].date.m << "/" <<
                            people_list[i].date.y << endl;

        cout << "Time: " << people_list[i].time.h << ":" <<
                            people_list[i].time.m << ":" <<
                            people_list[i].time.s << endl << endl;
    }
}

Выходы:

Name: james
Gender: male
Date: 1/2/1987
Time: 4:1:2

Name: jerry
Gender: male
Date: 11/6/1965
Time: 8:3:4

Name: jon
Gender: male
Date: 21/10/1977
Time: 12:5:6
0 голосов
/ 27 марта 2011

Помимо самого простого способа с sscanf, как Джерри описывает , это также возможно с iostreams.Просто прочитайте нужные вам данные из файла, пока не попадете в разделитель, и выбросьте их в пустышку char:

char dummy;
myfile >> first_name >> last_name >> day >> dummy >> month >> dummy ... // and so on.
...