Каков самый простой способ получить пользовательский ввод в C?
Кажется, есть много способов, которыми вы можете получить пользовательский ввод в C.
Каков самый простой способ, который требует небольшого кода?
В основном мне нужно отобразить это:
Enter a file name: apple.text
В основном мне нужно задать пользователю имя файла. Поэтому мне нужно что-то, что просто получает одно слово, которое будет вводить пользователь.
Ответы
Ответ 1
Простейший "правильный" способ, вероятно, относится к этому, взятый из статьи Бьярна Страуструпа Стандарт обучения С++ как новый язык.
(Примечание: я изменил код Bjarne, чтобы проверить isspace()
вместо конца строки. Кроме того, из-за комментария @matejkramny использовать while(1)
вместо while(true)
... и до тех пор, Re-еретик достаточно, чтобы отредактировать код Stroustrup, я добавил в комментарии C89 вместо стиля С++.: -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", то стоит подумать о прыжке на С++. Он был разработан таким образом, чтобы точно справляться с этими проблемами - с технологиями, которые являются надежными и расширяемыми, но все же хорошо работают.
Ответ 2
scanf
, похоже, работает в недружественной среде. Другими словами, вы делаете простую служебную программу для себя.
BUFSIZ обычно намного превышает пределы размера путей UNIX.
#include <stdio.h>
int main(void) {
char str[BUFSIZ];
printf("Enter a file name: ");
scanf("%s", str);
printf("You entered: %s\n", str);
}
Если вам нужно накапливать данные в программе, которая может быть целью переполнения буфера, вам может понадобиться немного больше.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * prompt_and_read(const char * prompt) {
char * response;
char * bufsize;
printf("%s", prompt);
asprintf(&bufsize, "%%%us", BUFSIZ);
if((response = malloc(BUFSIZ + 1)) == NULL) {
fprintf(stderr,"out of memory\n");
exit(1);
}
scanf(bufsize, response);
free(bufsize);
return response;
}
int main ( void ) {
char * pathname;
pathname = prompt_and_read("Enter a file name: ");
printf("You entered: [%s]\n", pathname);
free(pathname);
return 0;
}
Ответ 3
#include <stdio.h>
int main(void)
{
char file[100];
printf("File Name?: \n");
fgets(file, 100, stdin);
printf("Your input: %s", file);
}
Ответ 4
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter a file name:";
string filepath;
cin >> filepath;
}
Ответ 5
вы должны написать свою собственную функцию fgets(), которая читает строку ввода в буфер указанного размера и удаляет новую строку char, которую также читает fgets(). вы также можете вернуть статус того, могла ли вся строка быть в состоянии помещаться в буфер (т.е. является новой строкой в конце буфера). вы никогда не должны использовать scanf или получаете, если вы не хотите переполнения.
EDIT: подумал, что я могу предоставить базовый код:
typedef unsigned char BOOL;
#define TRUE 1
#define FALSE 0
/* wraps fgets, returns FALSE if the whole line couldn't fit into the buffer */
BOOL read_input(char *dest, size_t len)
{
/* our temp buffer needs to hold the extra new line char (len + 1)
* should also add error checking to malloc */
BOOL bSuccess = TRUE;
size_t total_len = len + 1;
char *temp = (char*) malloc( total_len * sizeof(char) );
fgets(temp, total_len, stdin);
/* if the whole line wasn't read, we'll return FALSE but still copy temp into dest */
if (temp[strlen(temp) - 1] != '\n')
bSuccess = FALSE;
else
temp[strlen(temp) - 1] = '\0'; /* overwrite the '\n' if it does infact exist */
strcpy(dest, temp);
free(temp);
return bSuccess;
}
Ответ 6
Используйте этот простой код
#include"stdio.h"
#include"stdlib.h"
main()
{
int i=0,j=0;
char c,buf[100];
start:
printf("Enter the name:");
while ( (c=getchar()) != '\n' )
{
buf[i++]=c;
buf[i]='\0';
}
if ( buf[0] == '\0')
{
printf("invalid name\n");
goto start;
}
else
printf("Your name is valid\nName = %s\n",buf);
}