4

我刚刚被介绍给 C,我被分配编写一个程序来模仿杂货店的自助结账线。这涉及到我必须根据用户输入用杂货商品的价格填充一个数组,然后将它们相加并将它们复制到一个文件中。

填充整数数组的最简单方法是使用 for 循环。但是对于浮点类型的数组会有所不同吗?

它看起来像这样吗?或者这是不正确的?

int size, i;
float items[size];
printf("How many items are you checking out today?");
scanf("%d", &size);
for(i=0;i<size;i++){
  printf("Enter the price of an item\n");
  scanf("%f", items[i]);
}

我是这个网站的新手,所以提前谢谢

4

3 回答 3

3

I would recommend always initializing variables as you declare them to prevent "garbage" values by accident. Also, I don't really recommend pre-declaring your loop counters. You see it in a lot of old code (it used to be required due to compiler limitations), but now I just think it's code noise. It would look like this:

for (int i = 0; i < size; i++) {
    // stuff
}

Also, your code has a big problem. You're using what's known as a variable-size array, and they are not a good idea. You generally want to either declare the array size at compile time, or dynamically allocate the space for the array using malloc.

Going back to the initalization, though, this is how you would set every element in a stack-allocated array on declaration:

#define SIZE 4

int main(void)
{
    float items[SIZE] = { 0 };
}

If you dynamically allocate the array, I recommend using calloc or memset to set the array elements to a default value for the same reason.

To answer your question about populating the array, yes, there is no difference as to how you would actually go about doing it. A for loop works just fine in both cases. Just remember to check the return value of scanf.

于 2018-05-04T05:09:44.363 回答
2

正如已经正确指出的那样,您不能声明float items[size];直到size被有效初始化为正整数值。由于您尝试访问未初始化的值,您尝试声明items之前size包含一个值会调用未定义的行为。(此时您的代码的有效操作已经结束,它可以做任何事情,从看起来正确运行到 StackOverflow 或 SegFaulting)

每当您进行用户输入时,必须考虑输入缓冲区中保留的每个字符(stdin此处)。scanf由于scanf处理输入匹配失败的方式,在与(或家人)一起接受输入时尤其如此。当任何一种情况发生时,都不会读取更多字符,并且输入缓冲区中的任何违规字符都不会被读取 - 只是在等待下一次尝试读取时再次咬你(如果你在循环中接受输入,通常会导致无限循环)

(这是推荐使用面向行的函数fgets来获取用户输入的主要原因之一)

scanf可以使用,如果使用正确。这意味着有责任检查每次退货。你必须处理三个条件scanf

  1. (return == EOF)EOF用户通过按Ctrl+d(或在 windows 上Ctrl+z,但请参阅CTRL+Z 在 Windows 10 中不生成 EOF )生成手册来取消输入;
  2. (return == expected No. of conversions)表示读取成功——然后由您来检查输入是否满足任何附加条件(例如正整数、正浮点等);和
  3. 否则,您必须处理匹配输入失败,并且必须考虑输入缓冲区中可能留下的每个字符。(通常您将在输入缓冲区中向前扫描,直到发现 a '\n'orEOF丢弃任何剩余的无关字符)

如果你做你的工作,你可以成功地scanf根据需要使用。

接下来,一般注意不要对货币使用浮点数(当您由于舍入错误而开始亏损时,人们会非常生气)虽然这对于您的示例程序很好 - 只需了解,在真正的货币处理程序中,您将处理货币作为无符号值乘以100(或任何需要的值)以确保可以准确表示所有金额。

scanf要求放在一起,您可以安全地执行以下操作:

#include <stdio.h>

/* function to empty extraneous characters from stdin
 * (like the '\n' generated by pressing [Enter])
 */
void empty_stdin()
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

int main (void) {

    int size = 0, i;
    float total = 0.0;

    for (;;) {  /* loop continually until valid size entered */
        int rtn;
        printf ("How many items are you checking out today?: ");
        rtn = scanf ("%d", &size);
        if (rtn == EOF) {       /* handle EOF */
            fprintf (stderr, "(user canceled input)\n");
            return 1;
        }
        else if (rtn == 1 && size > 0) {    /* valid int received */
            empty_stdin();
            break;
        }   /* otherwise, handle error */
        fprintf (stderr, "error: invalid input.\n\n");
        empty_stdin (); /* remove any chars from stdin up to '\n' */
    }
    float items[size];  /* declare VLA of size floats */

    for (i = 0; i < size; i++) {
        items[i] = 0.0; /* initialize each (or memset VLA) */
        for (;;) {      /* loop continually until valid item price entered */
            int rtn;
            printf ("  price of item[%2d]: ", i + 1); /* prompt for price */
            rtn = scanf ("%f", &items[i]);
            if (rtn == EOF) {       /* handle EOF */
                fprintf (stderr, "(user canceled input)\n");
                return 1;
            }
            else if (rtn == 1 && items[i] > 0) { /* valid price received */
                empty_stdin();
                break;
            }   /* otherwise, handle error */
            fprintf (stderr, "error: invalid input.\n\n");
            empty_stdin (); /* remove any chars from stdin up to '\n' */
        }
        total += items[i];
    }
    printf ("\ntotal (%d items): $%.2f\n", size, total);
}

示例使用/输出

(显示有故意输入错误)

$ ./bin/checkout
How many items are you checking out today?: what?
error: invalid input.

How many items are you checking out today?: 4
  price of item[ 1]: free?
error: invalid input.

  price of item[ 1]: 1.25
  price of item[ 2]: 3.50
  price of item[ 3]: discount?
error: invalid input.

  price of item[ 3]: 2.25
  price of item[ 4]: 3

total (4 items): $10.00

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

于 2018-05-04T05:52:57.887 回答
0

There is no difference in usage of arrays in terms of usage. But there are few changes required in your code.

#define MAX_SIZE (10)

int size=0, i=0; //It is always better to initialize the variables.
float items[MAX_SIZE] = {0.0f}; //Automatically the entire array will be initialized to zero.
printf("How many items are you checking out today?");
scanf("%d", &size);
if(size > MAX_SIZE)
    size = MAX_SIZE;

for(i=0;i<size;i++){
  printf("Enter the price of an item\n");
  scanf("%f", &items[i]); //You need to pass address of variable to scanf
}

There are other ways to implement your code to handle array size. This is one of the way.

于 2018-05-04T05:08:59.670 回答