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

Posted

技术标签:

【中文标题】在 C 中获取用户输入的最简单方法是啥?【英文标题】:What is the simplest way of getting user input in C?在 C 中获取用户输入的最简单方法是什么? 【发布时间】:2011-12-11 12:25:58 【问题描述】:

似乎有很多方法可以让您在 C 中获取用户输入。

需要很少代码的最简单方法是什么?

基本上我需要显示这个:

Enter a file name: apple.text

基本上我需要向用户询问文件名。所以我需要一些能得到用户输入的单词的东西。

【问题讨论】:

可能重复***.com/questions/314401/… 【参考方案1】:

最简单的“正确”方式大概就是这个,取自Bjarne Stroustrup的论文Learning Standard C++ As A New Language。

(注意:我更改了 Bjarne 的代码以检查 isspace() 而不仅仅是行尾。此外,由于 @matejkramny 的评论,使用 while(1) 而不是 while(true)...等等由于我们异端到足以编辑 Stroustrup 的代码,因此我也使用 C89 cmets 而不是 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”的东西是合理的,那么考虑跳转到 C++ 是非常值得的。它旨在精确管理这些问题 - 使用强大且可扩展的技术,但仍然表现良好。

【讨论】:

即使您的班级希望您扫描并继续前进,我建议您将笔记放在任何您故意做坏事/权宜之计的地方。因此,在您的阅读操作旁边,只需在 /* REVIEW: input correctness, see http://***.com/questions/7831755/what-is-the-simplest-way-of-getting-user-input-in-c/ */ 之类的评论中添加评论,这表明您进行了研究,保留链接以供以后阅读。另外,任何调试代码库的人如果遇到神秘的崩溃,都会引起他们的注意——不仅看到警告,而且看到指向讨论正确解决方案的指针。 顺便说一句,问题要求 C 而不是 C++ @matejkramny 在我引用和引用的论文中,Bjarne Stroustrup 将“C 方式”与“C++ 方式”进行了对比。这是我正在展示的他的“C 方式”代码。它不是 C++ 代码。论文的重点是,这种“正确”的 C 代码可以用 C++ 更突出地表达,并且不会降低效率;这可能会让顽固的 C 程序员感到惊讶。我向你保证我能读懂这个问题;我只是认为我读过的关于如何编写默认情况下 C++ 为您所做的“正确”C 版本的最佳答案之一来自一篇写成 C++ 布道工作的论文。你应该阅读这篇论文,虽然它很旧。 C++ 定义了布尔值,在 C 中不存在(默认情况下)。这就是为什么我认为这是 C++ 代码,对于 C 问题 我也想知道为什么会有两个while循环,看来你只需要一个? (原谅我的无知)【参考方案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;

【讨论】:

那么如果字符串超过BUFSIZ会发生什么...? 这确实是可能的,但我的印象是他想在非敌对环境中输入文件名。 ;-) 如果是敌对的,他将不得不做一些更多的事情。他确实要求提供一个只涉及少量代码的解决方案。 刚刚发布的恶意版本。 :-)【参考方案3】:
#include <stdio.h>
int main(void)

    char file[100];
    printf("File Name?: \n");
    fgets(file, 100, stdin);
    printf("Your input: %s", file);

【讨论】:

相关:***.com/questions/1252132/…【参考方案4】:
#include <iostream>
#include <string>

using namespace std;

int main()

    cout << "Enter a file name:";

    string filepath;
    cin >> filepath;

【讨论】:

那是在 C++ 中,您最初将问题标记为。 不要将您的问题标记为C++,然后是ಠ_ಠ。在 C 中使用 scanf【参考方案5】:

您应该编写自己的 fgets() 包装函数,该函数将输入行读取到指定大小的缓冲区中,并删除 fgets() 也读取的换行符。您还可以返回整行是否能够放入缓冲区的状态(即缓冲区末尾的换行符)。除非你想要溢出,否则你不应该真正使用 scanf 或 gets。

编辑:我想我可能会提供一些基本代码:

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;

【讨论】:

这是一个简单的(好吧,不是那么简单)的编程任务。此时只想通过课程。不会过于复杂。不过谢谢! 以上可以在 10 行以下轻松完成,这实际上取决于您需要重复该功能的次数。根据您输入的用途,换行符有时也会导致问题。还值得注意的是,如果 fgets 无法将整行放入缓冲区中,您可能需要删除额外的输入,直到遇到换行符(循环中的 fgetc)。 scanf 有字符限制,例如scanf("%99s", mySize100Buffer);。但与fgets 不同,边界由数字字符串指定,因此捕获BUFSIZE-1 关系涉及生成自定义格式字符串。有点不切实际... 编辑:这里有一些代码来展示你可以拥有它是多么简单(不要复制它,这样你就不会因为抄袭而被逮捕)。【参考方案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);
                                                                                                                                   

【讨论】:

以上是关于在 C 中获取用户输入的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 VB.net 中保存设置的最简单方法是啥

在 Android 上获取用户当前位置的最简单、最可靠的方法是啥?

从终端检测脚本中键盘输入的最简单方法是啥?

从IP地址获取用户纬度和经度的最简单方法是啥[关闭]

在 spark sql 中获取上一次特定月份的结果的最简单方法是啥?

在 C++ 中读取格式化输入的最简单方法是啥?