【发布时间】:2011-12-11 12:25:58
【问题描述】:
似乎有很多方法可以让您在 C 中获取用户输入。
需要很少代码的最简单方法是什么?
基本上我需要显示这个:
Enter a file name: apple.text
基本上我需要向用户询问文件名。所以我需要一些能得到用户输入的单词的东西。
【问题讨论】:
似乎有很多方法可以让您在 C 中获取用户输入。
需要很少代码的最简单方法是什么?
基本上我需要显示这个:
Enter a file name: apple.text
基本上我需要向用户询问文件名。所以我需要一些能得到用户输入的单词的东西。
【问题讨论】:
最简单的“正确”方式大概就是这个,取自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://stackoverflow.com/questions/7831755/what-is-the-simplest-way-of-getting-user-input-in-c/ */ 之类的评论中添加评论,这表明您进行了研究,保留链接以供以后阅读。另外,任何调试代码库的人如果遇到神秘的崩溃,都会引起他们的注意——不仅看到警告,而且看到指向讨论正确解决方案的指针。
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;
}
【讨论】:
#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;
}
【讨论】:
C++,然后是ಠ_ಠ。在 C 中使用 scanf
您应该编写自己的 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;
}
【讨论】:
scanf 有字符限制,例如scanf("%99s", mySize100Buffer);。但与fgets 不同,边界由数字字符串指定,因此捕获BUFSIZE-1 关系涉及生成自定义格式字符串。有点不切实际...
使用这个简单的代码
#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);
}
【讨论】: