首页 > 解决方案 > 在 C 中输入字母之前要求输入数字的程序

问题描述

嗨,我正在尝试制作一个程序,该程序要求输入数字,直到在 C 中输入一个字母。这就是我所拥有的

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

int main(void){
    long siz = 10;
    float *biglist = malloc(sizeof(float)* siz);
    int n, sum = 0;
    while ((n  = getchar() )!= "d"){
        scanf("%d",n);
        sum = sum + n;
    }
    printf("The sum is : %d",sum);
}

标签: c

解决方案


虽然您可以进行面向字符的输入getchar()并寻找一些特殊字符来打破循环,但这可能不是最好的方法。相反,当您阅读用户输入时,您希望使用面向行的输入函数来确保一次使用完整的输入行。这样可以确保没有未读的违规字符stdin会弄乱您的下一个输入。现在,虽然通过一次读取一个字符可以缓解这种情况 - 您需要采用来处理所有测试和转换的逻辑重新发明了轮子。

相反,如果您一次阅读一行,您可以允许用户输入任意数量的数字(每行一个,直到您的分配限制),然后只需Enter在空行上单独按下即可停止输入。标准方法是将一行输入读入缓冲区(字符数组),然后使用sscanf()或如果需要更多错误检测和报告,则使用strtol()strtof()strtod()等从缓冲区解析所需信息。

一次读取一行时,只需提供足够大的缓冲区来处理预期最长的行(以及踩在键盘上的猫)。如果您在嵌入式设备上,只需相应地减小缓冲区大小。要调整缓冲区的大小(或其他任何需要固定大小的东西),#define一个常量或使用一个全局变量enum来实现相同的目的,例如

#define MAXF 1000       /* if you need a constant, define one (or more) */
#define MAXC 1024
....
    char line[MAXC] = "";
    float *ma = malloc (MAXF * sizeof *ma),     /* or float ma[MAXF] = {0}; */

现在您只需读取输入,检查输入的数量是否适合您的数组并检查是否'\n'单独输入,例如

    puts ("enter one float per-line, [Enter] alone when done");
    
    /* while ma not full, and line read and not empty line */
    while (nfloat < MAXF && fgets (line, MAXC, stdin) && *line != '\n') {

要将输入转换为float,只需使用从缓冲区sscanf()中解析 a来验证在递增和计数器之前发生了成功的转换,例如floatline sum

        /* if valid conversion to float */
        if (sscanf (line, "%f", &ma[nfloat]) == 1) {
            sum += ma[nfloat];                  /* sum float */
            nfloat += 1;                        /* increment counter */
        }

总而言之,你可以这样做:

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

#define MAXF 1000       /* if you need a constant, define one (or more) */
#define MAXC 1024

int main (void) {
    
    char line[MAXC] = "";
    float *ma = malloc (MAXF * sizeof *ma),     /* or float ma[MAXF] = {0}; */
        sum = 0;
    size_t nfloat = 0;
    
    if (ma == NULL) {
        perror ("malloc-ma");
        return 1;
    }
    
    puts ("enter one float per-line, [Enter] alone when done");
    
    /* while ma not full, and line read and not empty line */
    while (nfloat < MAXF && fgets (line, MAXC, stdin) && *line != '\n') {
        /* if valid conversion to float */
        if (sscanf (line, "%f", &ma[nfloat]) == 1) {
            sum += ma[nfloat];                  /* sum float */
            nfloat += 1;                        /* increment counter */
        }
    }
    
    printf ("The sum is : %f\n", sum);
    free (ma);      /* don't forget to free what you allocate */
}

注意:分配的内存被释放。虽然这将在程序退出时自动发生,但您不会总是在 中分配main()。如果无法释放您分配的内存,则在这种情况下无法释放内存将导致内存泄漏内存丢失)

示例使用/输出

./bin/sumfloats
enter one float per-line, [Enter] alone when done
10.1
10.3
10.3
10.3

The sum is : 41.000000

如果要输出所有存储的浮点数,则只需在输出总和之前添加一个输出循环,例如

    for (size_t i = 0; i < nfloat; i++)
        printf (i ? " %.1f" : "%.1f", ma[i]);
    
    printf ("\nThe sum is : %.2f\n", sum);
    free (ma);      /* don't forget to free what you allocate */
}

在这种情况下,您将输出每个精度为 1 位float的部分,sum以及精度为 2 的总和,例如

./bin/sumfloats
enter one float per-line, [Enter] alone when done
10.1
10.3
10.3
10.3

10.1 10.3 10.3 10.3
The sum is : 41.00

这与您尝试的内容略有不同,但这种方法将为您节省很多痛苦(以及潜在的逻辑错误)。如果您还有其他问题,请仔细查看并告诉我。


推荐阅读