在 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 中获取用户输入的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 上获取用户当前位置的最简单、最可靠的方法是啥?