1

私がやろうとしているのは、この形式に従って日付を入力することですWednesday 7:05 PM。次に、それをトークンに分割して、私が持っている構造体に入れます。私の主な問題は、私が使用している stringstream オブジェクトが既に入力された文字列を入力バッファから削除しないことです. これを修正するにはどうすればよいですか? また、コードのクリーンアップに関するアドバイスがあれば、よろしくお願いします。

struct Time{
        //  always in [0, 6]:
        //  0 means Sunday, 1 means Monday, ... , 6 means Saturday
    unsigned day;
        //  false means at or after midnight, and before the following noon (AM)
        //  true means at or after noon, and before the following midnight (PM)
    bool pm;
    unsigned hour;      //  in [1, 12], e.g. 12 for 12 o’clock
    unsigned minute;    //  in [0, 59]
};  //  struct Time

const string dayar[]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void input( Time & time ){
    string str, day, pm;
    unsigned hr, min;
    getline(cin,str);
    istringstream sin(str);
    cout<<str.length();
    for(unsigned i=0; i<str.length(); i++){
        if(str[i]==':')
            str[i]=' ';
    }
    if(!(sin>>day)){
        die("AHHHHH!!! WHERE'S THE INPUT?!?!?!");
    }else{
        for(unsigned i=0; i<7; i++){
            if(day==dayar[i]){
                time.day=i;
            }
        }
    }
    if(!(sin>>hr)){
        die("AHHHHH!!! WHERE'S THE INPUT?!?!?!");
    }else{
        if(hr<1 || hr>12){
            die("THAT NUMBER AIN'T A REAL HOUR!!");
        }else{
            time.hour=hr;
        }
    }
    if(!(sin>>min)){
        die("AHHHHH!!! WHERE'S THE INPUT?!?!?!");
    }else{
        if(min<0 || min>59){
            die("THAT NUMBER AIN'T A REAL HOUR!!");
        }else{
            time.minute=min;
        }
    }
    if(!(sin>>pm)){
        die("AHHHHH!!! WHERE'S THE INPUT?!?!?!");
    }else{
        if(pm!="PM" || pm!="AM"){
            die("THAT NUMBER AIN'T A REAL HOUR!!");
        }else{
            pm=="PM"?time.pm=true:time.pm=false;
        }
    }
}

bool die(const char *msg){
    cout<<msg;
    exit(EXIT_FAILURE);
}
4

2 に答える 2

3

コロンをスペースに変更すると、文字列は問題なく変更されますが、入力ストリームによってバッファリングされたものは変更されません。

入力ストリームを宣言するにコロンを変更してください。

std::transformまた、たとえば:を使用して、これを行うためのより優れた「C++風」の方法があります。

#include <algorithm>

// ...

std::transform(str.begin(), str.end(), str.begin(),
    [](const char c){ return (c == ':' ? ' ' : c); });
于 2012-09-20T05:09:01.940 に答える
1

I don't see why you wouldn't read the values in one statement. Something like this:

// Map day names to day number
map<string,unsigned> days;
for( unsigned i = 0; i < 7; i++ ) days[dayar[i]] = i;

bool ParseTime( const string& str, Time& time )
{
    bool valid = false;
    istringstream sin(str);

    string day, pm;
    unsigned hour, minute;  // Because unsigned, we don't bother to test >= 0
    char colon;

    if( sin >> day >> hour >> colon >> minute >> pm )
    {
        // Sanity test...
        valid = (days.find(day) != days.end())
             && (hour >= 1 && hour <= 12)
             && (colon == ':')
             && (minute < 60)
             && (pm == 'AM' || pm == 'PM');
    }

    if( !valid ) return false;

    time.day = days[day];
    time.hour = hour;
    time.minute = minute;
    time.pm = (pm == 'PM');

    return true;
}

I mean, if you wanna squawk about every conceivable date parsing error then go ahead! =) But it just makes for cluttered code that's hard to follow.

于 2012-09-20T05:51:43.107 に答える