Самый простой "правильный" способ, вероятно, этот, взятый из статьи Бьярна Страуструпа Изучение стандарта C ++ как нового языка .
(Примечание: Я изменил код Бьярне, чтобы проверять isspace()
вместо только конца строки.Также из-за комментария @ matejkramny использовать while(1)
вместо while(true)
... и до тех пор, пока мы достаточно еретичны, чтобыотредактировав код Страуструпа, я также добавил в комментарии C89 вместо стиля C ++. :-P)
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
void quit() /* write error message and quit */
{
fprintf(stderr, "memory exhausted\n");
exit(1);
}
int main()
{
int max = 20;
char* name = (char*) malloc(max); /* allocate buffer */
if (name == 0) quit();
printf("Enter a file name: ");
while (1) { /* skip leading whitespace */
int c = getchar();
if (c == EOF) break; /* end of file */
if (!isspace(c)) {
ungetc(c, stdin);
break;
}
}
int i = 0;
while (1) {
int c = getchar();
if (isspace(c) || c == EOF) { /* at end, add terminating zero */
name[i] = 0;
break;
}
name[i] = c;
if (i == max - 1) { /* buffer full */
max += max;
name = (char*) realloc(name, max); /* get a new and larger buffer */
if (name == 0) quit();
}
i++;
}
printf("The filename is %s\n", name);
free(filename); /* release memory */
return 0;
}
Это охватывает:
- пропуск пробелов до тех пор, пока вы не достигнетеввод символов
- динамическое расширение строкового буфера для размещения строк произвольного размера
- условия обработки, когда память не может быть выделена
Существуют ли более простые, но неработающие решения,который может даже работать немного быстрее?Абсолютно !!
Если вы используете scanf в буфере без ограничения на размер чтения, то ваш ввод превышает размер буфера, это создаст дыру в безопасности и / или сбой.
Ограничение размера чтения, скажем, до 100 уникальных символов имени файла может показаться лучше, чем сбой.Но это может быть хуже;например, если пользователь имел в виду (...)/dir/foo/bar.txt
, но вы в конечном итоге неправильно интерпретируете его ввод и перезаписываете файл с именем bar.t
, который, возможно, им небезразличен.
Лучше всего рано освоиться с этими проблемами. Мое мнение заключается в том, что если ваши требования оправдывают что-то близкое к металлическому и "C-like", то стоит подумать о переходе на C ++.Он был разработан для решения именно этих проблем - с помощью методов, которые являются надежными и расширяемыми, но все еще работают хорошо.