简体   繁体   English

在C中获取用户输入的最简单方法是什么?

[英]What is the simplest way of getting user input in C?

There seem to be a LOT of ways you can get user input in C. 似乎有很多方法可以在C中获得用户输入。

What is the easiest way that requires little code? 什么是最简单的方法,需要很少的代码?

Basically I need to display this: 基本上我需要显示这个:

Enter a file name: apple.text

Basically I need to ask the user for a file name. 基本上我需要询问用户文件名。 So I need something that just gets that one word that the user will be inputting. 所以我需要的东西只能得到用户输入的那个词。

The simplest "correct" way is probably this one, taken from Bjarne Stroustrup's paper Learning Standard C++ As A New Language . 最简单的“正确”方式可能就是这一点,取自Bjarne Stroustrup的论文“ 学习标准C ++作为新语言”

(Note: I changed Bjarne's code to check for isspace() instead of just end of line. Also, due to @matejkramny's comment, to use while(1) instead of while(true) ...and so long as we're being heretical enough to edit Stroustrup's code, I've subbed in C89 comments instead of C++ style too. :-P) (注意:我更改了Bjarne的代码以检查isspace()而不仅仅是行尾。另外,由于@ matejkramny的注释,使用while(1)而不是while(true) ...只要我们是由于足以编辑Stroustrup的代码,我已经用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;
}

That covers: 这包括:

  • skipping whitespace until you reach character input 跳过空格直到你到达字符输入
  • expanding the string buffer dynamically to fit arbitrary size strings 动态扩展字符串缓冲区以适应任意大小的字符串
  • handling conditions of when memory can't be allocated 处理无法分配内存的条件

Are there simpler but broken solutions, which might even run a bit faster? 是否有更简单但破碎的解决方案,甚至可能运行得更快一些? Absolutely!! 绝对!!

If you use scanf into a buffer with no limit on the read size, then your input exceeds the size of the buffer, it will create a security hole and/or crash. 如果将scanf用于缓冲区而不限制读取大小,则输入超出缓冲区大小,会产生安全漏洞和/或崩溃。

Limiting the size of the reading to, say, only 100 unique characters of a filename might seem better than crashing. 将读取的大小限制为,例如,只有100个文件名的唯一字符似乎比崩溃更好。 But it can be worse; 但它可能会更糟; for instance if the user meant (...)/dir/foo/bar.txt but you end up misinterpreting their input and overwriting a file called bar.t which perhaps they cared about. 例如,如果用户意味着(...)/dir/foo/bar.txt但你最终误解了他们的输入并覆盖了一个名为bar.t的文件,这可能是他们关心的。

It's best to get into good habits early in dealing with these issues. 在处理这些问题时,最好养成良好的习惯。 My opinion is that if your requirements justify something close-to-the-metal and "C-like", it's well worth it to consider the jump to C++. 我的观点是,如果你的要求证明了接近金属和“类C”的东西,那么考虑跳转到C ++是值得的。 It was designed to manage precisely these concerns--with techniques that are robust and extensible, yet still perform well. 它旨在精确管理这些问题 - 使用强大且可扩展的技术,但仍然表现良好。

scanf seems to work in a non-hostile environment. scanf似乎在非恶意环境中工作。 In other words, you're making a simple utility program for yourself. 换句话说,您正在为自己制作一个简单的实用程序。

BUFSIZ usually far exceeds the size limits of UNIX pathnames. 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);                                                                                                                                                             
}

If you need to accumulate data in a program that could be the target of buffer overrun, you might need a bit more. 如果需要在可能成为缓冲区溢出目标的程序中累积数据,则可能需要更多。

#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;
}
#include <stdio.h>
int main(void)
{
    char file[100];
    printf("File Name?: \n");
    fgets(file, 100, stdin);
    printf("Your input: %s", file);
}
#include <iostream>
#include <string>

using namespace std;

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

    string filepath;
    cin >> filepath;
}

you should write your own fgets() wrapper function that reads a line of input into a buffer of a specified size and that removes the newline char that fgets() also reads. 你应该编写自己的fgets()包装函数,它将一行输入读入指定大小的缓冲区,并删除fgets()也读取的换行符。 you could also return a status of whether or not the whole line was able to fit into the buffer (ie. is the newline at the end of the buffer). 您还可以返回整行是否能够适应缓冲区的状态(即缓冲区末尾的换行符)。 you shouldn't ever really use scanf or gets unless you want overflows. 除非你想要溢出,否则你不应该真正使用scanf或获取。

EDIT: thought i might provide some basic code: 编辑:我想我可能会提供一些基本代码:

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;
}

Use this simple code 使用这个简单的代码

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM