чтение строки с пробелами с помощью sscanf

для проекта, я пытаюсь прочитать int и строку из строки. Единственная проблема заключается в том, что sscanf прерывает чтение %s, когда видит пробел. Есть ли вообще обойти это ограничение? Вот пример того, что я пытаюсь сделать:

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid", "%d %s", &age, buffer);

    printf("%s is %d years oldn", buffer, age);
    return 0;
}

что он печатает: "круто 19 лет", где мне нужно "прохладный ребенок 19 лет". Кто-нибудь знает как это исправить?

5 ответов


следующая строка начнет читать номер (%d), а затем все, что отличается от вкладок или новых строк (%[^\t\n]).

sscanf("19 cool kid", "%d %[^\t\n]", &age, buffer);

вы хотите %c спецификатор преобразования, который просто считывает последовательность символов без особой обработки пробелов.

обратите внимание, что сначала вам нужно заполнить буфер нулями, потому что %c спецификатор не записывает нуль-Терминатор. Вам также необходимо указать количество символов для чтения (в противном случае по умолчанию используется только 1):

memset(buffer, 0, 200);
sscanf("19 cool kid", "%d %199c", &age, buffer);

если вы хотите сканировать до конца строки (зачистка новой строки, если есть), просто используйте:

char *x = "19 cool kid";
sscanf (x, "%d %[^\n]", &age, buffer);

потому что %s соответствует только символам без пробелов и останавливается на первом найденном пробеле. The %[^\n] спецификатор формата будет соответствовать каждому символу, который не (из-за ^) на выбор дали (это строки). Другими словами, он будет соответствовать любому другому персонажу.


имейте в виду, что вы должны выделяться достаточно места в буфере, чтобы взять строку, так как вы не можете быть уверены, сколько будет прочитано (хорошая причина держаться подальше от scanf/fscanf если вы не используете определенную ширину поля).

вы могли бы сделать это:

char *x = "19 cool kid";
char *buffer = malloc (strlen (x) + 1);
sscanf (x, "%d %[^\n]", &age, buffer);

(вам не нужно * sizeof(char) так вот всегда 1 по определению).


Так как вы хотите, чтобы конечная строка из ввода, вы можете использовать %n (количество символов, использованных до сих пор), чтобы получить позицию, с которой начинается конечная строка. Это позволяет избежать проблем с копиями памяти и размером буфера, но стоит того, что вам может потребоваться сделать их явно, если вы хотите копию.

const char *input = "19  cool kid";
int age;
int nameStart = 0;
sscanf(input, "%d %n", &age, &nameStart);
printf("%s is %d years old\n", input + nameStart, age);

выходы:

cool kid is 19 years old

Я думаю, это то, что вы хотите, он делает именно то, что вы указали.

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
    int age;
    char* buffer;
    buffer = malloc(200 * sizeof(char));
    sscanf("19 cool kid", "%d cool %s", &age, buffer);
    printf("cool %s is %d years old\n", buffer, age);
    return 0;
}

формат ожидает: сначала число (и помещает его туда, куда указывает &age), затем пробелы (ноль или больше), затем литеральная строка "круто", затем пробелы (ноль или больше) снова, а затем, наконец, строка (и поместите это в любые буферные точки). Вы забыли "классную" часть в строке формата, поэтому формат тогда просто предполагает, что это строка, которую вы хотели назначить буферу. Но вы не хочу назначать эту строку, просто пропустите ее.

альтернатива, у вас также может быть строка формата, например: "%d %s %s", но затем вы должны назначить для нее другой буфер (с другим именем) и распечатать его как: "%s %s-это %d years old\n".