Подтвердить что ты не робот

Чтение строки с пробелами с помощью 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 old\n", buffer, age);
    return 0;
}

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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


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

Вы можете сделать это с помощью:

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

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

Ответ 4

Так как вы хотите, чтобы возвращающая строка была введена с помощью ввода, вы можете использовать %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

Ответ 5

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

#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;
}

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

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