C / C ++ sscanf (): получить указатель на текст (если есть) после преобразованного текста - PullRequest
0 голосов
/ 01 марта 2020

Клянусь, я делал это 100 раз в своей карьере и думал, что %s сделал это, но я вижу, что это не так.

В частности, у меня есть

          iParsed = sscanf( pszValue, "%4d-%2d-%2d%c%2d:%2d:%f%s",
                        &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &cSeparator,
                        &stm.tm_hour, &stm.tm_min, &dSec, &pcFollow );

pcFollow - это const char*. Я просто хочу знать, что следует за этим форматом даты / времени, чтобы я мог 1) проверить, не прикреплено ли дополнительное поле в этой точке, или 2) пожаловаться на мусор в строке. В других ситуациях я мог бы захотеть 3) продолжить анализ в этой точке.

%s однако хочет char*, а не char**. Он хочет, чтобы фактический буфер символов содержал копию того, что следует за %f в моем примере.

Единственная идея, которую я имею, состоит в том, чтобы использовать %n, чтобы захватить количество проанализированных символов, и использовать это как смещение до pszValue. На самом деле это было бы хорошо, за исключением того, что я просто не помню, как это делал.

Ответы [ 2 ]

1 голос
/ 01 марта 2020

Вы можете адаптировать свое существующее решение следующим образом:

  1. Как указано в вашем вопросе и ответе @wilx, используйте спецификатор формата %n и передайте дополнительный параметр int в sscanf для захвата количества потребляемых символов (которое также будет индексом любых завершающих данных).
  2. Вместо constchar *, проход адрес одного char для обнаружения присутствия конечных данных.
  3. Используйте возвращаемое значение из sscanf для проверки количества проанализированных элементов ( 7 будет подходящим для вашего случая использования); меньшее число будет означать сбой в середине анализа, а большее число будет означать конечные данные.

Вот рабочий пример (не охватывающий все крайние случаи, но должен быть отправной точкой):

#include <stdio.h>
#include <time.h>

static void parse_time(const char* pszValue, struct tm* pstm, int* piItemsParsed, int* piCharsConsumed, char* pcFollow)
{
    float dSec;
    char cSeparator;
    *piItemsParsed = sscanf( pszValue, "%4d-%2d-%2d%c%2d:%2d:%f%n%c",
                             &pstm->tm_year, &pstm->tm_mon, &pstm->tm_mday, &cSeparator,
                             &pstm->tm_hour, &pstm->tm_min, &dSec, piCharsConsumed, pcFollow );
    printf("Time String    = '%s'\n", pszValue);
    printf("Items Parsed   = %d\n", *piItemsParsed);
    printf("Chars Consumed = %d\n", *piCharsConsumed);
    printf("Char Following = 0x%02x\n", (unsigned int) *pcFollow);
}

static void report(const char* pszValue, int iItemsParsed, int iCharsConsumed)
{
    if (iItemsParsed == 7)
    {
        printf("Timestamp is valid\n");
    }
    else
    {
        printf("Timestamp has trailing data: '%s'\n", pszValue + iCharsConsumed);
    }
}

static void parse_and_report(const char* pszValue, struct tm* pstm)
{
    int iItemsParsed;
    int iCharsConsumed;
    char cFollow;

    parse_time(pszValue, pstm, &iItemsParsed, &iCharsConsumed, &cFollow);
    report(pszValue, iItemsParsed, iCharsConsumed);
}

int main(void)
{
    struct tm stm;
    static const char pszValue[] = "2020-03-01 07:31:30.345";
    static const char pszValue2[] = "2020-03-01 07:31:30.345trailing data";
    static const char pszValue3[] = "2020-03-01 07:31:30.345 more trailing data";
    static const char pszValue4[] = "2020-03-01 07:31:30.345\nyet more trailing data";

    parse_and_report(pszValue, &stm);
    parse_and_report(pszValue2, &stm);
    parse_and_report(pszValue3, &stm);
    parse_and_report(pszValue4, &stm);

    return 0;
}

Пример вывода:

Time String    = '2020-03-01 07:31:30.345'
Items Parsed   = 7
Chars Consumed = 23
Char Following = 0x00
Timestamp is valid
Time String    = '2020-03-01 07:31:30.345trailing data'
Items Parsed   = 8
Chars Consumed = 23
Char Following = 0x74
Timestamp has trailing data: 'trailing data'
Time String    = '2020-03-01 07:31:30.345 more trailing data'
Items Parsed   = 8
Chars Consumed = 23
Char Following = 0x20
Timestamp has trailing data: ' more trailing data'
Time String    = '2020-03-01 07:31:30.345
yet more trailing data'
Items Parsed   = 8
Chars Consumed = 23
Char Following = 0x0a
Timestamp has trailing data: '
yet more trailing data'
0 голосов
/ 01 марта 2020

Вы можете использовать спецификатор формата %n. Она заполняет переменную int количеством символов, использованных на данный момент:

...