scanf — C ++ получает часы и минуты из строки

Я пишу код C ++ для школы, в которой я могу использовать только библиотеку std, так что никакого повышения. Мне нужно разобрать строку вроде «14:30» и разобрать ее в:

unsigned char hour;
unsigned char min;

Мы получаем строку как строку c ++, поэтому прямой указатель отсутствует. Я перепробовал все варианты этого кода:

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

но я продолжаю получать неправильные данные. Что я делаю неправильно.

4

Решение

Как уже упоминалось, вы должны использовать %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);
}

Надеюсь, поможет.

2

Другие решения

Ваша проблема, конечно, в том, что вы используете sscanf, И это
Вы используете какой-то особенный тип для часов и минут, вместо
из int, Поскольку вы анализируете строку ровно из 5 символов,
Самое простое решение — просто убедиться, что все символы легальны
в этом положении, используя isdigit для символов 0, 1, 3 и 4, и
по сравнению с ':' для персонажа 2. Как только вы это сделали, это тривиально
создать std::istringstream из строки, и введите в
int, char (который вы потом проигнорируете) и второй int, Если
Вы хотите быть более гибкими в вводе, например, позволяя вещи
лайк "9:45" также вы можете пропустить начальные проверки и просто ввести
в int, char а также intзатем проверьте, что char содержит ':'
(и что два int находятся в пределах досягаемости).

Что касается того, почему ваш sscanf терпит неудачу: вы просите, чтобы это соответствовало чему-то
лайк "12[:]34", который не что вы даете. Я не уверен
пытаетесь ли вы использовать "%hhd:%hhd"или если по какой-то причине вы
действительно хотите класс персонажа, в этом случае вы должны использовать [ как
спецификатор преобразования, а затем игнорировать ввод: "%hhd%*[:]%hhd",
(Это позволит принять более одного символа в качестве разделителя,
но в остальном я не вижу преимущества. Кроме того, технически, по крайней мере,
с помощью %d а затем передать адрес unsigned интегральные типы
не поддерживается, %hhd должен быть signed char, На практике,
Тем не менее, я не думаю, что вы когда-либо столкнетесь с какими-либо проблемами для
неотрицательные входные значения меньше 128.)

2

Как упоминается Изоморфия 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 чтобы получить все до толстой кишки.

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 опции. Я бы тоже добавил проверку ошибок.

1

Я понимаю, что h в %hhd не является допустимым спецификатором формата. Правильный спецификатор для десятичных целых чисел %d,

Как говорит Р.Мартиньо Фернандес в своем комментарии, %d:%d будет соответствовать двум числам, разделенным двоеточием (‘:’).

Вы хотели что-то другое?

Вы всегда можете прочитать всю текстовую строку и проанализировать ее так, как хотите.

0

sscanf с %hhd:%hhd Кажется, работает прекрасно

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

Обратите внимание, что hh Модификатор длины просто позволяет сохранить значение в неподписанном символе.

Тем не мение, 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;
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector