TL; DR Непонятно, что заставляет вас думать, что ваши наборы сканирования не сработали; они работают нормально в этом контексте для меня. Мягко модифицированный код, показанный ниже, демонстрирует это.
Как я отмечал в комментарии , набор сканирования имеет вид %[…]
- он останавливается на ]
и все, что следует (s
в коде в вопросе), не является часть набора сканирования. Если вам нужно включить ]
в набор сканирования, это должен быть первый символ (после каретки, которая отменяет набор сканирования, если вы используете набор сканирования с отрицанием). С s
после набора сканирования, если вход включает s
после конца цифры и последовательности пробелов (первый пробел в наборе сканирования значим; второй, будучи повторением, нет), тогда этот символ будет «потреблен», и следующая операция ввода продолжится после s
; если следующий символ не является s
, то он остается на входе для следующей операции ввода. Кроме того, если следующий символ не является s
, сопоставление завершается неудачно, но sscanf()
не может сообщить об этом, когда набор сканирования является последней или единственной спецификацией преобразования в строке формата. Конечный контекст всегда расходуется; его отсутствие не может быть обнаружено.
Ваш код любопытен тем, что он использует \r
в нескольких местах. Вам редко нужно будет использовать \r
в коде C - вы должны использовать \n
в своем коде (или пробелах, или ...).
Вот программа, тесно связанная с вашей, с некоторыми изменениями. Код проверяет возвращаемое значение с sscanf()
; он заменяет большую часть возвратов каретки другими символами; он сохраняет ошибочные строки формата; он заставляет аргумент функции print соответствовать аргументу функции sscanf()
.
#include <stdio.h>
#include <string.h>
static int testcount = 1;
static void printResult(char *test, char *actual, char *expected)
{
printf("\n\n%d. [%s]: ", testcount++, test);
if (strcmp(actual, expected) == 0)
{
printf("SUCCESS ");
printf("Output: [%s]\n", actual);
}
else
{
printf("FAILED ");
printf("Expected Output: [%s], Actual Output: [%s]\n", expected, actual);
}
}
int main(void)
{
char buffer[] = "250MEL\r";
char *pBuffer = buffer;
char output[5] = {0};
// 1
if (sscanf(pBuffer, "%[ 0-9 ]s", output) != 1)
printf("scanf() 1 failed\n");
printResult("%[ 0-9 ]s", output, "250");
// 2
if (sscanf(pBuffer, "%3[ 0-9 ]s", output) != 1)
printf("scanf() 1 failed\n");
printResult("%3[ 0-9 ]s", output, "250");
return 0;
}
Также выдает ожидаемый результат:
1. [%[ 0-9 ]s]: SUCCESS Output: [250]
2. [%3[ 0-9 ]s]: SUCCESS Output: [250]
Если раньше вы не видели SUCCESS
, то это потому, что символ \r
перемещает позицию записи в начало строки, поэтому последующее переписывание SUCCESS
.
Вспомогательный вопрос
Также, пожалуйста, дайте мне знать, как я могу установить диапазон для A-Z, как показано ниже - но это не работает:
sscanf(pBuffer,"%*[A-Z]s",output);
printResult("%[A-Z]s",output, "MEL" );
Пожалуйста Обратите внимание!
Ваш комментарий показывает, что вы все еще думаете, что %[…]s
является обозначением для набора сканирования, но s
является ложным; это не часть нотации набора сканирования. Хватит думать о %[…]
как о модификаторе %s
; это не модификатор. Это полностью независимая спецификация преобразования, почти полностью не связанная и синтаксически совершенно отличная от %s
. Обозначение в квадратных скобках также категорически и однозначно не является частью какого-либо стандартного синтаксиса спецификации преобразования printf()
.
Вот некоторый пересмотренный код, в значительной степени основанный на предыдущей части ответа (и, следовательно, на коде в вопросе). Он не звездный, но показывает некоторую полезную информацию.
#include <stdio.h>
#include <string.h>
static int strings_match(const char *actual, const char *expected);
static void printResult(const char *format, const char *data, const char *act1,
char *exp1, const char *act2, char *exp2);
int main(void)
{
char buffer1[] = "250MEL@93";
char buffer2[] = " 250 \t\tMELabc";
char number[5] = "";
char letters[5] = "";
const char fmt1[] = "%4[0-9]%4[A-Z]";
const char fmt2[] = " %4[0-9] %4[A-Z]";
if (sscanf(buffer1, fmt1, number, letters) != 2)
printf("sscanf() 1 failed\n");
else
printResult(fmt1, buffer1, number, "250", letters, "MEL");
if (sscanf(buffer2, fmt2, number, letters) != 2)
printf("sscanf() 2 failed\n");
else
printResult(fmt2, buffer2, number, "250", letters, "MEL");
number[0] = '\0';
letters[0] = '\0';
if (sscanf(buffer2, fmt1, number, letters) != 2)
printf("sscanf() 3 failed\n");
else
printResult(fmt2, buffer1, number, "250", letters, "MEL");
const char fmt3[] = "%4[0-9]s%c";
const char fmt4[] = "%4[0-9]%c";
char buffer3[] = "9876sun";
char buffer4[] = "9876moon";
char letter;
if (sscanf(buffer3, fmt3, number, &letter) != 2)
printf("sscanf() 4 failed\n");
else
printf("Data [%s], Format [%s], Output [%s] %c\n", buffer3, fmt3, number, letter);
if (sscanf(buffer3, fmt4, number, &letter) != 2)
printf("sscanf() 5 failed\n");
else
printf("Data [%s], Format [%s], Output [%s] %c\n", buffer3, fmt4, number, letter);
if (sscanf(buffer4, fmt3, number, &letter) != 2)
printf("sscanf() 6 failed\n");
else
printf("Data [%s], Format [%s], Output [%s] %c\n", buffer4, fmt3, number, letter);
return 0;
}
static int strings_match(const char *actual, const char *expected)
{
int rc;
if (strcmp(actual, expected) == 0)
{
rc = 1;
printf(" Output: [%s]", actual);
}
else
{
rc = 0;
printf(" Expected Output: [%s], Actual Output: [%s]", expected, actual);
}
return rc;
}
static int testcount = 1;
static void printResult(const char *format, const char *data, const char *act1,
char *exp1, const char *act2, char *exp2)
{
printf("Format: %d. [%s] Data: [%s]", testcount++, format, data);
int t1 = strings_match(act1, exp1);
int t2 = strings_match(act2, exp2);
if (t1 == 1 && t2 == 1)
printf(" - SUCCESS\n");
else
printf(" - FAILED\n");
}
Выход:
Format: 1. [%4[0-9]%4[A-Z]] Data: [250MEL@93] Output: [250] Output: [MEL] - SUCCESS
Format: 2. [ %4[0-9] %4[A-Z]] Data: [ 250 MELabc] Output: [250] Output: [MEL] - SUCCESS
sscanf() 3 failed
Data [9876sun], Format [%4[0-9]s%c], Output [9876] u
Data [9876sun], Format [%4[0-9]%c], Output [9876] s
sscanf() 6 failed
Обратите внимание, как отличаются две последние успешные строки преобразования - s
в строке формата сопоставляется как литерал с данными, оставляя u
для чтения в символ по сравнению с отсутствием s
в строке формата и символ соответствует s
. Напротив, когда формат ищет s
и находит m
, общий sscanf()
дает сбой - он управляет только 1 вместо 2 спецификаций преобразования.