Какой самый простой способ получить пользовательский ввод в C? - PullRequest
20 голосов
/ 20 октября 2011

Кажется, есть много способов получить пользовательский ввод в C.

Какой самый простой способ, требующий небольшого количества кода?

В основном мне нужно отобразить это:

Enter a file name: apple.text

В основном мне нужно спросить у пользователя имя файла. Поэтому мне нужно что-то, что просто получает одно слово, которое будет вводить пользователь.

Ответы [ 6 ]

23 голосов
/ 20 октября 2011

Самый простой "правильный" способ, вероятно, этот, взятый из статьи Бьярна Страуструпа Изучение стандарта 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 ++.Он был разработан для решения именно этих проблем - с помощью методов, которые являются надежными и расширяемыми, но все еще работают хорошо.

7 голосов
/ 20 октября 2011

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 голосов
/ 20 октября 2011
#include <stdio.h>
int main(void)
{
    char file[100];
    printf("File Name?: \n");
    fgets(file, 100, stdin);
    printf("Your input: %s", file);
}
1 голос
/ 20 октября 2011

вы должны написать свою собственную функцию-обертку fgets (), которая читает строку ввода в буфер указанного размера и удаляет символ новой строки, который также читает fgets (). Вы также можете вернуть статус того, была ли вся строка помещена в буфер (т. е. является ли новой строкой в ​​конце буфера). вам никогда не следует использовать scanf или get, если вы не хотите переполнения.

РЕДАКТИРОВАТЬ: думал, что я мог бы предоставить базовый код:

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;
}
1 голос
/ 20 октября 2011
#include <iostream>
#include <string>

using namespace std;

int main()
{
    cout << "Enter a file name:";

    string filepath;
    cin >> filepath;
}
0 голосов
/ 03 декабря 2013

Используйте этот простой код

#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);
      }                                                                                                                             
...