C ++从字符串中获取小时和分钟

时间:2012-11-19 15:46:25

标签: c++ scanf

我正在为学校编写C ++代码,我只能使用std库,所以没有提升。我需要解析像“14:30”之类的字符串并将其解析为:

unsigned char hour;
unsigned char min;

我们将字符串作为c ++字符串,因此没有直接指针。我尝试了这段代码的所有变体:

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

但我一直收到错误的数据。我做错了什么。

6 个答案:

答案 0 :(得分: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);
}

希望它有所帮助。

答案 1 :(得分:2)

您的问题当然是您正在使用sscanf。然后 你会在几小时和几分钟内使用一些非常特殊的类型 int。因为你正在解析一个正好5个字符的字符串,所以 最简单的解决方案就是确保所有角色都合法 在该位置,使用isdigit表示字符0,1,3和4,以及 与角色2的':'相比。一旦你完成了它,它就是微不足道的 从字符串创建std::istringstream,并输入到 intchar(之后你会忽略)和第二个int。如果 你希望在输入中更灵活,例如允许事物 像"9:45"一样,你可以跳过初始检查,只需输入 进入intcharint,然后检查char是否包含':' (并且两个int在范围内)。

至于你的sscanf失败的原因:你要求它匹配一些东西 比如"12[:]34"你给它的是什么。我不确定 您是否尝试使用"%hhd:%hhd",或者出于某种原因使用[ 真的想要一个角色类,在这种情况下,你必须使用"%hhd%*[:]%hhd" 转换说明符,然后忽略输入:%d。 (这将允许接受多个字符作为分隔符, 但除此之外,我没有看到优势。另外,技术上至少, 使用unsigned然后传递%hhd整数类型的地址 不受支持,signed char 必须为{{1}}。在实践中, 但是,我认为你不会遇到任何问题 非负输入值小于128。)

答案 2 :(得分: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将所有内容放到冒号上。

答案 3 :(得分: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选项。我也会添加一些错误检查。

答案 4 :(得分:0)

我的理解是h中的%hhd不是有效的格式说明符。十进制整数的正确说明符是%d

正如R.Martinho Fernandes在评论中所说,%d:%d将匹配由冒号(':')分隔的两个数字。

你想要不同的东西吗?

您可以随时读取整个文本字符串并以任何方式解析它。

答案 5 :(得分:0)

带有sscanf

%hhd:%hhd似乎完全正常:

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

请注意,hh长度修饰符只是允许将值存储在unsigned char中。

但是,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;