Использует ли Malloc в Scanf совместим со стандартом C ANSI - PullRequest
0 голосов
/ 29 января 2019

Я хочу прочитать ввод пользователя и сохранить его.Теперь то, что у меня есть, работает, но мне нужно знать, правильно ли (в соответствии со стандартом ANSI - c90), что scanf сначала назначает переменную "length", прежде чем он выделит память для ввода, или это всего лишь причуда компилятора.

#include <stdio.h>
int main()
{
    char* text;
    int length = 0;
    scanf("%s%n", text = malloc(length+1), &length);

    printf("%s", text);

    return 0;
}  

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Помимо очевидной проблемы с неправильным использованием scanf, указанной в другом ответе, это также не соответствует ни одному стандарту C:

#include <stdio.h>
...
text = malloc(length+1)

, поскольку вы не включили stdlib.h, где malloc найдено, C90 будет считать, что функция malloc имеет вид int malloc(int);, что, конечно, бессмысленно.

А затем, когда вы попытаетесь присвоить int (результат malloc) дляchar*, у вас есть нарушение ограничения C90 6.3.16.1, правил простого присваивания.

Поэтому ваш код не может быть скомпилирован чисто, но компилятор должен выдать диагностическое сообщение.

Вы можете избежать этой ошибки, обновив стандарт до ISO C.

0 голосов
/ 29 января 2019

Проблемы, которые хорошо объясняются другими

Я хочу прочитать ввод пользователя и сохранить его

Чтобы добавить и выполнить цель ОП, подобный код мог бы сделать

int length = 255;
char* text = malloc(length+1);
if (text == NULL) {
  Handle_OOM();
} 
scanf("%255s%n", text, &length);

// Reallocate if length < 255 and/or 
if (length < 255) {
  char *t = realloc(text, length + 1);
  if (t) text = t;
} else {
  tbd(); // fail  when length == 255 as all the "word" is not certainly read.
}

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

0 голосов
/ 29 января 2019

Это будет не работать так, как вы ожидаете.

В то время, когда вы вызываете malloc, length все еще имеет значение 0, поэтому вы выделяете только один байт.length не обновляется, пока не вернется scanf.Таким образом, любая непустая строка будет записывать за пределами выделенного буфера, вызывая неопределенное поведение .

Хотя не точно то же самое, что вы можете сделать, это использоватьgetline при условии, что вы работаете в системе POSIX, такой как Linux.Эта функция читает строку текста (включая новую строку) и выделяет место для этой строки.

char *text = NULL;
size_t n = 0;
ssite_t rval = getline(&text, &n, stdin);

if (rval == -1) {
    perror("getline failed");
} else {
    printf("%s", text);
}
free(text);
...