首页 > 解决方案 > 要求用户在 C 中输入几个数字的正确方法是什么?

问题描述

我正在尝试制作一个关于核导弹发射的 C 程序。以下是我到目前为止的源代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int nukeLaunchCode = 618243;
int NLC_input;
char *address;

int main(void) {
    address = malloc(sizeof(char) * 60);
    printf("\033[0;34m[INFO] C.E.R.B.E.R.U.S Activating");
    fflush(stdout);
    for (int i = 0; i < 3; i++){
        printf(".");
        sleep(1);
    }
    fflush(stdout);
    printf("\n");
    printf("\033[0;32m[INFO] C.E.R.B.E.R.U.S Initialized. Enter destination for nuke in address form: ");
    fgets(address, 60, stdin);
    printf("\033[0;32m[INFO] Geo locating address via Advanced UAV");
    fflush(stdout);
    for (int i = 0; i < 6; i++) {
        printf(".");
        fflush(stdout);
        sleep(1);
    }
    printf("\n");
    fflush(stdout);
    printf("\033[0;31m[WARNING] Target Acquired. Enter 6-digit Nuke Confirmation code to proceed: ");
    fgets(&NLC_input, 7, stdin);
    return 0;

}

问题是代码末尾的 fgets。我收到一条警告说:

Incompatible pointer types passing 'int *' to parameter of type 'char *'

我尝试使用带有"%d"转换符号的 scanf ,然后我收到另一个警告说:

'scanf' used to convert a string to an integer value, but function will not 
report conversion errors; consider using 'strtol' instead

有人可以告诉我我做错了什么吗?此外,我还包含了 fflush 函数,因为我想做一些很酷的事情。我想在打印一个句子后每秒打印一定数量的点来动画加载类的东西。出于某种原因,如果没有 fflush 函数,命令会乱序执行,并且不会打印点。但即使使用 fflush 函数,打印的第一行也不会打印 3 个点,直到打印下一行。我很确定这是 fflush 函数中的错位,但是有人可以帮我解决这个问题吗?谢谢!

标签: c

解决方案


好吧,让我们做一些很酷的事情,让你理顺。首先,正确的原型fgets()是:

char *fgets(char *s, int size, FILE *stream);

男人 3 fgets

在您的代码中,您已经声明int NLC_input;了 ,但随后尝试将 的地址NLC_input用作 的第一个参数fgets()。不允许。将结果的地址int放入一个指针中 int,该指针与需要的指针(例如)int*不匹配。 charchar*fgets()

此外,您不能将用户输入的字符转换为数字形式(如intfgets()。您必须使用strtol()sscanf()将数组中包含的数字转换为数字。(但使用fgets()用户输入做得很好,比尝试直接阅读要好得多scanf()

让我们通过添加来快速概述您的代码:

#include <stdio.h>
#include <unistd.h>

#define MAXC 1024       /* if you need a constant, #define on (or more) */
#define ADRSZ  60

stdlib.h删除,因为不需要动态分配address

int main(void) {
    
    char address[ADRSZ], tmp[MAXC];             /* avoid global variables */
    int nukeLaunchCode = 618243, NLC_input;

注意:如果您不打算更改nukeLaunchCode,那#define nukeLaunchCode 618243会很好 - 但请注意,宏通常在 C 中的 ALL-CAPS 中定义。另一种选择是const int nukeLaunchCode 618243;

您只需要fflush()在您准备好输出时,将它包含在几个额外的时间里,它不会产生任何影响。反而:

    printf ("\033[0;34m[INFO] C.E.R.B.E.R.U.S Activating");
    for (int i = 0; i < 3; i++) {
        putchar ('.');              /* don't use printf for single-char */
        fflush(stdout);             /* fflush only needed when output required */
        sleep(1);
    }
    printf ("\n\033[0;32m[INFO] C.E.R.B.E.R.U.S Initialized. "
            "Enter destination for nuke in address form: ");

注:'\n'包含在第二个开头printf()

现在开始输入:

    if (!fgets(address, 60, stdin)) {           /* validate EVERY user input */
        puts ("(user canceled input)");
        return 0;
    }
    printf ("\033[0;32m[INFO] Geo locating address via Advanced UAV");
    for (int i = 0; i < 6; i++) {
        putchar ('.');
        fflush(stdout);
        sleep(1);
    }
    printf ("\n\033[0;31m[WARNING] Target Acquired. "
            "Enter 6-digit Nuke Confirmation code to proceed: ");

注意:EOF用户可以通过按Ctrl + d, (或在 Windows 上)生成手册来取消输入,Ctrl + z这不是错误,因此您应该EOF为用户处理这种情况)

只需使用 读取您将转换为值的输入NLC_input到临时数组中fgets(),例如

    if (!fgets (tmp, sizeof tmp, stdin)) {      /* fill temporary array */
        puts ("(user canceled input)");
        return 0;
    }
    if (sscanf (tmp, "%d", &NLC_input) != 1) {  /* validate EVERY conversion */
        fputs ("error: invalid integer input.\n", stderr);
        return 1;
    }

现在开始验证启动代码:

    if (NLC_input != nukeLaunchCode) {          /* validate launch code */
        fputs ("error: Invalid Code, self-destruct sequence started ", stdout);
        for (int i = 0; i < 6; i++) {
            putchar ('.');
            fflush(stdout);
            sleep(1);
        }
        puts (" B O O M ! ! !");
        return 1;
    }
    
    puts ("Launch Code Valid, continuing ..."); 
}

示例使用/输出

搏一搏:

$ ./bin/launchcode
[INFO] C.E.R.B.E.R.U.S Activating...
[INFO] C.E.R.B.E.R.U.S Initialized. Enter destination for nuke in address form: N34W67.123
[INFO] Geo locating address via Advanced UAV......
[WARNING] Target Acquired. Enter 6-digit Nuke Confirmation code to proceed: 618244
error: Invalid Code, self-destruct sequence started ...... B O O M ! ! !

如果您还有其他问题,请仔细查看并告诉我。


推荐阅读