对字符串进行标记

时间:2012-09-20 04:46:14

标签: c++ string struct stream token

我要做的是输入一个遵循这种格式的日期Wednesday 7:05 PM然后将它分成令牌以放入我拥有的结构中。我的主要问题是我正在使用的stringstream对象没有从输入缓冲区中删除已经输入的字符串,所以在我第二次检查它失败的几小时,因为它输入了char类型的东西到unsigned。我该如何解决?此外,如果您对我清理代码有任何建议,我会很感激。

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);
}

2 个答案:

答案 0 :(得分:3)

当您将冒号更改为空格时,您可以更改字符串,但不能更改输入流缓冲的内容。

在声明输入流之前更改冒号

此外,还有更好更多的C ++ - ish&#34;使用例如方法std::transform

#include <algorithm>

// ...

std::transform(str.begin(), str.end(), str.begin(),
    [](const char c){ return (c == ':' ? ' ' : c); });

答案 1 :(得分:1)

我不明白为什么你不会在一个陈述中读取这些值。像这样:

// 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;
}

我的意思是,如果您想要解决每个可以想象的日期解析错误,那么请继续! =)但它只会造成难以理解的混乱代码。