чтение строки с пробелами с помощью sscanf - PullRequest
37 голосов
/ 18 мая 2010

Для проекта я пытаюсь прочитать 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 лет» Кто-нибудь знает как это исправить?

Ответы [ 5 ]

41 голосов
/ 18 мая 2010

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

sscanf("19 cool kid", "%d %[^\t\n]", &age, buffer);
12 голосов
/ 18 мая 2010

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

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

memset(buffer, 0, 200);
sscanf("19 cool kid", "%d %199c", &age, buffer);
8 голосов
/ 18 мая 2010

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

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

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


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

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

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

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

2 голосов
/ 09 ноября 2015

Поскольку вы хотите, чтобы завершающая строка была введена, вы можете использовать %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
0 голосов
/ 17 февраля 2017

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

#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), затем пробел (ноль или более), затем буквенную строку «cool», затем снова пробел (ноль или более), а затем, наконец, строка (и поместите это в любой буфер указывает на). Вы забыли «классную» часть в строке формата, поэтому формат просто предполагает, что это строка, которую вы хотели назначить в буфер. Но вы не хотите назначать эту строку, просто пропустите ее.

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

...