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

发布于 2024-12-10 22:21:50 字数 176 浏览 0 评论 0原文

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

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

基本上我需要显示这个:

Enter a file name: apple.text

基本上我需要向用户询问文件名。所以我需要一种能够获取用户将输入的单词的东西。

There seem to be a LOT of ways you can get user input in 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

薄暮涼年 2024-12-17 22:21:50

最简单的“正确”方法可能就是这个,取自 Bjarne Stroustrup 的论文 学习标准 C++ 作为一种新语言

(注意:我更改了 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;
}

这涵盖:

  • 跳过空格,直到到达字符输入 动态
  • 扩展字符串缓冲区以适应任意大小的字符串
  • 处理无法分配内存的条件

是否有更简单但损坏的解决方案,甚至可能运行快一点?绝对地!!

如果您使用 scanf 进入对读取大小没有限制的缓冲区,那么您的输入超出了缓冲区的大小,它将创建安全漏洞和/或崩溃。

将读取的大小限制为文件名中的 100 个唯一字符可能看起来比崩溃要好。但情况可能更糟;例如,如果用户的意思是 (...)/dir/foo/bar.txt 但您最终误解了他们的输入并覆盖了一个名为 bar.t 的文件,该文件可能他们关心。

在处理这些问题时最好尽早养成良好的习惯。 我的观点是,如果您的需求证明了一些接近金属和“类似 C”的东西是合理的,那么考虑跳转到 C++ 是非常值得的。它旨在通过强大且可扩展且性能良好的技术来精确管理这些问题。

The simplest "correct" way is probably this one, taken from Bjarne Stroustrup's paper Learning Standard C++ As A New Language.

(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)

#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.

Limiting the size of the reading to, say, only 100 unique characters of a filename might seem better than crashing. 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.

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++. It was designed to manage precisely these concerns--with techniques that are robust and extensible, yet still perform well.

葵雨 2024-12-17 22:21:50

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

scanf seems to work in a non-hostile environment. In other words, you're making a simple utility program for yourself.

BUFSIZ usually far exceeds the size limits of UNIX pathnames.

#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;
}
二智少女猫性小仙女 2024-12-17 22:21:50
#include <stdio.h>
int main(void)
{
    char file[100];
    printf("File Name?: \n");
    fgets(file, 100, stdin);
    printf("Your input: %s", file);
}
#include <stdio.h>
int main(void)
{
    char file[100];
    printf("File Name?: \n");
    fgets(file, 100, stdin);
    printf("Your input: %s", file);
}
水中月 2024-12-17 22:21:50
#include <iostream>
#include <string>

using namespace std;

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

    string filepath;
    cin >> filepath;
}
#include <iostream>
#include <string>

using namespace std;

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

    string filepath;
    cin >> filepath;
}
第几種人 2024-12-17 22:21:50

您应该编写自己的 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;
}

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. 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.

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;
}
生生不灭 2024-12-17 22:21:50

使用这个简单的代码

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

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);
      }                                                                                                                             
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文