Я хочу прочитать имя, введенное моим пользователем, используя программы C
Для этого я написал:
char name[20];
printf("Enter name:");
gets(name);
но использование gets
не подходит, поэтому предложите мне лучший способ.
Я хочу прочитать имя, введенное моим пользователем, используя программы C
Для этого я написал:
char name[20];
printf("Enter name:");
gets(name);
но использование gets
не подходит, поэтому предложите мне лучший способ.
Вы никогда не должны использовать gets
(или scanf
с неограниченным размером строки), так как это открывает вам переполнение буфера. Используйте fgets
с дескриптором stdin
, поскольку он позволяет вам ограничить данные, которые будут помещены в ваш буфер.
Вот небольшой фрагмент, который я использую для ввода строки от пользователя:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
Это позволяет мне установить максимальный размер, будет определять, будет ли слишком много данных введено в строке, а также выровнят остальную часть строки, чтобы она не влияла на следующую операцию ввода.
Вы можете проверить его с помощью чего-то вроде:
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Я думаю, что лучший и безопасный способ читать строки, введенные пользователем, использует getline()
Вот пример, как это сделать:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *buffer = NULL;
int read;
unsigned int len;
read = getline(&buffer, &len, stdin);
if (-1 != read)
puts(buffer);
else
printf("No line read...\n");
printf("Size read: %d\n Len: %d\n", read, len);
free(buffer);
return 0;
}
В системе POSIX вы, вероятно, должны использовать getline
, если она доступна.
Вы также можете использовать функцию общественного домена Chuck Falconer ggets
, которая обеспечивает синтаксис ближе к gets
, но без проблем. (Сайт Чака Фальконера больше недоступен, хотя archive.org имеет копию, и я сделал свою собственную страницу для ggets.)
Я нашел легкое и приятное решение:
char*string_acquire(char*s,int size,FILE*stream){
int i;
fgets(s,size,stream);
i=strlen(s)-1;
if(s[i]!='\n') while(getchar()!='\n');
if(s[i]=='\n') s[i]='\0';
return s;
}
он основан на fgets, но свободен от '\n' и stdin дополнительных символов (для замены fflush (stdin), который не работает на всех ОС, полезно, если вам нужно получить строки после этого).
Вы можете использовать функцию scanf для чтения строки
scanf("%[^\n]",name);
Я не знаю о других лучших вариантах получения строки,
В BSD-системах и Android вы также можете использовать fgetln
:
#include <stdio.h>
char *
fgetln(FILE *stream, size_t *len);
Так же:
size_t line_len;
const char *line = fgetln(stdin, &line_len);
line
не завершается нулем и содержит \n
(или что-то, что использует ваша платформа) в конце. Он становится недействительным после следующей операции ввода-вывода в потоке. Вы можете изменить возвращенный буфер line
.