4

私は、std ライブラリしか使用できない学校用の C++ コードを書いているので、ブーストはありません。「14:30」のような文字列を解析して、次のように解析する必要があります。

unsigned char hour;
unsigned char min;

文字列を c++ 文字列として取得するため、直接ポインターはありません。このコードのすべてのバリエーションを試しました:

sscanf(hour.c_str(), "%hhd[:]%hhd", &hours, &mins);

しかし、私は間違ったデータを取得し続けます。私は何を間違っていますか。

4

6 に答える 6

2

他の誰もが言及したように、%d指定された形式(または%u)を使用する必要があります。別のアプローチについては、私は「C++ には機能 XX があるため、使用する必要がある」という大ファンではなく、C レベルの関数に頼ることがよくあります。scanf()独自の問題があるため、のようなものは使用しませんが。そうは言っても、strtol()エラーチェックを使用して文字列を解析する方法は次のとおりです。

#include <cstdio>
#include <cstdlib>

int main()
{
    unsigned char hour;
    unsigned char min;

    const char data[] = "12:30";
    char *ep;

    hour = (unsigned char)strtol(data, &ep, 10);
    if (!ep || *ep != ':') {
        fprintf(stderr, "cannot parse hour: '%s' - wrong format\n", data);
        return EXIT_FAILURE;
    }

    min = (unsigned char)strtol(ep+1, &ep, 10);
    if (!ep || *ep != '\0') {
        fprintf(stderr, "cannot parse minutes: '%s' - wrong format\n", data);
        return EXIT_FAILURE;
    }

    printf("Hours: %u, Minutes: %u\n", hour, min);
}

それが役に立てば幸い。

于 2012-11-19T16:06:41.513 に答える
2

あなたの問題は、もちろん、あなたが使用していることですsscanf。の代わりに、時間と分に非常に特別なタイプを使用していることintisdigit正確に 5 文字の文字列を解析しているため、最も簡単な解決策は、文字 0、1、3、および 4 を使用して':'、文字 2と比較して、すべての文字がその位置で有効であることを確認することです。std::istringstream文字列から を作成し、 に入力するのは簡単ですint, a char(後で無視します) と 2 番目のint. 入力をより柔軟にしたい場合、たとえば次のようなことも許可する場合は、最初のチェックをスキップして、 、 、および"9:45"に入力するだけで、intcharintcharを含む':' (および 2 つintが範囲内にある)。

sscanfあなたが失敗している理由については、 のようなものと一致するように求めていますが"12[:]34"、これはあなたが与えているものではありません。を使用しようとしているかどうか"%hhd:%hhd"、または何らかの理由で本当に文字クラスが必要な場合は[、変換指定子として使用してから入力を無視する必要があるかどうかはわかりません: "%hhd%*[:]%hhd"。(これにより、区切り文字として複数の文字を受け入れることができますが、それ以外の場合、利点はわかりません。また、少なくとも技術的には、整数型%dのアドレスを使用してから渡すことはサポートされていません。ただし、128 未満の非負の入力値で問題が発生することはないと思います。)unsigned%hhd signed char

于 2012-11-19T16:08:27.217 に答える
1

私はこのようにします

unsigned tmp_hour, tmp_mins;
unsigned char hour, mins;

sscanf(hour.c_str(), "%u:%u", &tmp_hours, &tmp_mins);
hour = tmp_hours;
mins = tmp_mins;

あいまいなscanfオプションをいじることが少なくなります。エラーチェックも追加します。

于 2012-11-19T16:07:02.277 に答える
1

izomorphius が述べたようにsscanf、バリアントは C++ ではなく、C です。C++ の方法は、ストリームを使用することです。次のように動作します(驚くほど柔軟ではありませんが、アイデアが得られるはずです)

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main(int argc, char* argv[])
{
    string str = "14:30";

    stringstream sstrm;

    int hour,min;

    sstrm << str;

    sstrm >> hour;
    sstrm.get(); // get colon
    sstrm >> min;

    cout << hour << endl;
    cout << min << endl;

    return 0;
}

getlineコロンまですべてを取得するために使用することもできます。

于 2012-11-19T16:02:00.437 に答える
0

私の理解では、hin%hhdは有効なフォーマット指定子ではありません。10進整数の正しい指定子はです%d

R.Martinho Fernandesがコメントで述べているように%d:%d、コロン(':')で区切られた2つの数字に一致します。

何か違うものが欲しかったですか?

いつでもテキスト文字列全体を読み取って、好きなように解析できます。

于 2012-11-19T15:57:28.060 に答える
0

sscanfwith%hhd:%hhdは完全に正常に機能しているようです:

std::string time("14:30");
unsigned char hour, min;
sscanf(time.c_str(), "%hhd:%hhd", &hour, &min);

hh長さ修飾子は、値をunsignedcharに格納できるようにするためのものであることに注意してください。

ただし、sscanfこれはC標準ライブラリからのものであり、これを行うためのより優れたC++の方法があります。これを行うC++11の方法は、以下を使用することですstoi

std::string time("14:30");
unsigned char hour = std::stoi(time);
unsigned char min = std::stoi(time.substr(3));

C ++ 03では、stringstream代わりに使用できますが、本当に必要な場合は少し面倒ですchar

std::stringstream stream("14:30");
unsigned int hour, min;
stream >> hour;
stream.ignore();
stream >> min;
于 2012-11-19T16:05:14.100 に答える