【问题标题】:C-get specific input from userC-从用户那里获取特定的输入
【发布时间】:2016-04-04 07:51:27
【问题描述】:

我需要从用户那里得到一些特定的输入(用户需要输入“init 3 4 NORTH”,3是X(int类型)的值,4是Y(int类型)的值,NORTH是direction(enum type) init 是他们必须输入的命令。)如果用户只输入“3 4 NORTH”,程序将不会做任何事情。

我不允许使用任何 scanf 系列来获取输入。

这是我目前实现的:

char input[10];
printf("Enter the command...\n");
if(fgets(input,sizeof(input),stdin)!= NULL){
     if(input[0]=='i' && input[1]=='n' && input[2]=='i' && input[3]=='t'){
        int x=atoi(&input[5]);
        int y=atoi(&input[7]);
         //doing similar things for Direction value.....
       }
     }

所以我的想法是检查第一个值“init”,并获取两个 int 值,获取方向值。 我希望我的解释足够清楚,希望任何人都可以分享他们的想法。

【问题讨论】:

  • 首先,strncmp man7.org/linux/man-pages/man3/strcmp.3.html 会帮助你...
  • sscanf 也会帮助你。
  • 输入缓冲区太小。
  • "init 3 4 NORTH" 是 {'i','n','i','t',' ','3','4',' ','N','O','R','T','H','\0'},如您所见,它大于输入缓冲区所包含的 10 个字符。
  • 如果用户正在输入一行文本,请停止计数字符。将缓冲区声明为 [256]。不要乱用 [10] 或任何其他小值,(除非您在 RAM 受限的嵌入式环境中)。

标签: c stdin


【解决方案1】:

您的方法的一个问题是,如果数字 > 9,它将不起作用。如果您不想使用 scanf,您可以阅读带有 fgets 的行,然后使用 sscanf 提取它的部分。请注意,即使在检查值本身之前,也会检查读数的有效性。

#include <stdio.h>
#include <string.h>

int main(void) {
    char line[256];
    char cmd[32];
    char dir[32];
    int x;
    int y;

    if(fgets(line, sizeof line, stdin) == NULL) {
        return 1;
    }
    if(sscanf(line, "%32s%d%d%32s", cmd, &x, &y , dir) != 4) {
        return 1;
    }

    // now check you got valid command, values, and direction
    if(strcmp(cmd, "init") != 0) {
        return 1;
    }
    if(x < 0 || x > 99 || y < 0 || y > 99) {
        return 1;
    }
    if(strcmp(dir, "NORTH") != 0) {
        return 1;
    }

    printf("Your command: %s %d %d %s\n", cmd, x, y, dir);
    return 0;
}

【讨论】:

  • 哈,这个程序只是一个主机游戏(9x9),所以我不需要超过9的数字。很抱歉我也不能使用sscanf,我的导师想要我们来学习如何使用 fgets,因为他们说它比 scanf 和 sscanf 更好。但是您的方法在实际编程世界中非常好,感谢您的帮助!
  • @Jason Wang 在这种情况下,您的问题应该是“我不允许使用scanf 系列函数”,但您说“它不安全”。这使用fgets 和sscanf 而不是scanf。
【解决方案2】:

无论您如何处理,您只需按顺序逐步完成,并验证您从用户那里获得的所需init DIRECTION X Y 输入的每个部分。无法使用scanf 系列,这不是问题,您只需要依赖指针和索引算法即可。

在这方面的一种方法是沿着输入字符串向下移动指针,并在进行过程中比较值。有很多方法可以做到这一点,但一种方法如下:

#include <stdio.h>
#include <string.h>

#define MAXC 256

void help() { printf (" format 'init DIRECTION X Y'\n"); }

int main (void) {

    enum { EAST, NORTH, WEST, SOUTH } dir;
    char *names[] = { "EAST", "NORTH", "WEST", "SOUTH" };
    char input[MAXC] = "";
    char *init = "init";
    int x, y;

    for (;;) {
        char *p, *ep = NULL;
        printf ("Enter the commmand: ");
        fgets (input, MAXC, stdin);
        if (strncmp (input, init, strlen (init))) { /* compare 'init' 1st */
            help(); continue;
        }
        if (!(p = strchr (input, ' ') + 1)) {   /* find 1st space */
            help(); continue;
        }   /* locate 'N', 'S', 'E', 'W' */
        while (*p && *p != 'E' && *p != 'N' && *p != 'W' && *p != 'S') p++;
        if (!*p || !(ep = strchr (p, ' '))) {   /* find following space */
            help(); continue;
        }
        *ep = 0;        /* nul-terminate */
        switch (*p) {   /* test cardinal names */
            case 'E' : if (strcmp (p, "EAST")) { help(); continue; }
                    else dir = EAST;
                    break;
            case 'N' : if (strcmp (p, "NORTH")) { help(); continue; }
                    else dir = NORTH; 
                    break;
            case 'W' : if (strcmp (p, "WEST")) { help(); continue; }
                    else dir = WEST;
                    break;
            case 'S' : if (strcmp (p, "SOUTH")) { help(); continue; }
                    else dir = SOUTH; 
                    break;
            default : help(); continue;
        }
        *ep = ' ';      /* restore space */
        p = ep + 1;     /* advance to next char */
        while (*p && (*p < '0' || '9' < *p)) p++;   /* find digit */
        if (!*p) {
            help(); continue;
        }
        x = *p++ - '0'; /* set x value -- single digit conversion */
        while (*p && (*p < '0' || '9' < *p)) p++;   /* find digit */
        if (!*p) {
            help(); continue;
        }
        y = *p - '0';   /* set y value -- single digit conversion */
        break;          /* made it! break out of loop */
    }

    printf ("\n direction '%s', x '%d', y '%d'\n\n", names[dir], x, y);

    return 0;
}

当您的输入不满足您的要求时,给用户一点help() 提醒他们正确的格式是有帮助的,这样他们就不会无休止地看着闪烁的光标想知道如何解决谜题。

使用/输出示例

$ ./bin/direction
Enter the commmand: dog food
 format 'init DIRECTION X Y'
Enter the commmand: inid NORTH 3 6
 format 'init DIRECTION X Y'
Enter the commmand: init EASY 4 5
 format 'init DIRECTION X Y'
Enter the commmand: init EAST a 6
 format 'init DIRECTION X Y'
Enter the commmand: init WEST 6 b
 format 'init DIRECTION X Y'
Enter the commmand: init SOUTH 4 8

 direction 'SOUTH', x '4', y '8'

您可以添加额外的验证,但这是一个开始。

【讨论】:

    【解决方案3】:
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char input[256];
        printf("Enter the command...\n");
        if(fgets(input,sizeof(input),stdin) != NULL) {
            char    *tok;
            if ((tok = strtok(input, " ")) != NULL) {
                if (strcmp(tok, "init") != 0)
                    ;//error
            }
            else
                ;//error
            if ((tok = strtok(NULL, " ")) != NULL) {
                /*Check first number and process it */
            }
            else
                ;//error
            if ((tok = strtok(NULL, " ")) != NULL) {
                /*Check second number and process it */
            }
            else
                ;//error
            if ((tok = strtok(NULL, " \n")) != NULL) {
                /*Check direction with strcmp */
            }
            else
                ;//error
        }
    }
    

    【讨论】:

    • 这将不匹配方向,除非您将newline 添加到分隔符。 strtok(NULL, " \n")
    • @Morovaille 这是最简单的方法!
    【解决方案4】:

    由于您不能使用 scanf,您应该手动解析输入,非常简单。

    void getcommand ()
    {
        /*Extra byte for null termination*/
        char input[BUFFER_SIZE+1];
        char keyword[BUFFER_SIZE+1];
        char command[BUFFER_SIZE+1];
        int x=0;
        int y=0;
        char direction[BUFFER_SIZE+1];
        printf("Enter the command...\n");
        if(fgets(input,sizeof(input),stdin)!= NULL){
            /*find the first space*/
            int index=0;
            int i=0;
            for(; index<BUFFER_SIZE; ++index){
                if(input[index]==' '){
                    break;
                }
            }
            /*Get the keyword*/
            for(; i<index; ++i){
                keyword[i]=input[i];
            }
            /*set null termination*/
            keyword[index]=0;
            /*Test valid keyword*/
            if(strcmp(keyword, "init")!=0){
                return;
            }
            /*save the command*/
            strcpy_s(command, sizeof(command),keyword);
            /*skip the current space*/
            ++index;
            ++i;
            /*find the next space*/
            for(; index<BUFFER_SIZE; ++index){
                if(input[index]==' '){
                    break;
                }
            }
            /*Get the keyword*/
            int j=0;
            for(; i<index; ++j, ++i){
                keyword[j]=input[i];
            }
            /*add the null termination*/
            keyword[j]=0;
            /*Get the coordinate*/
            int x=atoi(keyword);
            /*skip the current space*/
            ++index;
            ++i;
            /*find the next space*/
            for(; index<BUFFER_SIZE; ++index){
                if(input[index]==' '){
                    break;
                }
            }
            /*Get the keyword*/
            for(j=0; i<index; ++j, ++i){
                keyword[j]=input[i];
            }
            /*add the null termination*/
            keyword[j]=0;
            int y=atoi(keyword);
            /*skip the current space*/
            ++index;
            ++i;
            /*find the next space*/
            for(; index<BUFFER_SIZE; ++index){
                if(input[index]==' ' || input[index]=='\n'){
                    break;
                }
            }
            /*Get the keyword*/
            for(j=0; i<index; ++j, ++i){
                keyword[j]=input[i];
            }
            /*add the null termination*/
            keyword[j]=0;
            /*Test valid keyword*/
            if(strcmp(keyword, "NORTH")==0){
                /*save the direction*/
                strcpy_s(direction, sizeof(command), keyword);
            }
            else if(strcmp(keyword, "SOUTH")==0){
                /*save the direction*/
                strcpy_s(direction, sizeof(command), keyword);
            }
            else if(strcmp(keyword, "EAST")==0){
                /*save the direction*/
                strcpy_s(direction, sizeof(command), keyword);
            }
            else if(strcmp(keyword, "WEST")==0){
                /*save the direction*/
                strcpy_s(direction, sizeof(command), keyword);
            }
            else{
                return;
            }
        }
        return;
    }
    

    这是一项非常重要的学习技能,因此我鼓励您自己尝试使用其他命令。

    希望我没用过c++语法,不习惯写c代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-11
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      相关资源
      最近更新 更多