简体   繁体   English

填充整数数组与填充浮点数相同吗?

[英]Is populating an integer array the same as populating a float one?

I'm just getting introduced to C, and I was assigned to write a program that would mimic a self check out line at a grocery store. 我刚刚被介绍给C,我被分配编写了一个程序,可以模仿杂货店的自助结账线。 This involves me having to populate an array with the prices of grocery items based on user input, and add them up and copy them to a file. 这涉及我必须根据用户输入填充杂货项目的价格数组,并将它们添加并复制到文件中。

the easiest way to populate an integer array is with a for loop. 填充整数数组的最简单方法是使用for循环。 But would that be different for an array of type float? 但是对于float类型的数组会有什么不同吗?

would it look something like this? 它看起来像这样吗? Or is this incorrect? 或者这是不正确的?

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

I'm new to this site so thanks in advance 我是这个网站的新手,所以提前感谢

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 . 您通常希望在编译时声明数组大小,或者使用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. 如果动态分配数组,我建议使用callocmemset将数组元素设置为默认值,原因相同。

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. 在两种情况下,for循环都可以正常工作。 Just remember to check the return value of scanf . 只记得检查scanf的返回值。

As has been correctly pointed out, you cannot declare float items[size]; 正如已经正确指出的那样,你不能声明float items[size]; until size has been validly initialized to a positive integer value. 直到size有效地初始化为正整数值。 Your attempt to declare items before size contains a value invokes Undefined Behavior due to your attempt to access an uninitialized value. 您尝试在size包含值之前声明items因尝试访问未初始化的值而调用Undefined Behavior (the valid operation of your code is over at that point and it could do anything from appearing to run correctly to StackOverflow, or SegFaulting) (代码的有效操作已经结束,它可以执行任何操作,从显示正确运行到StackOverflow或SegFaulting)

Any time you are taking user-input, you must account for each character that remains in the input buffer ( stdin here). 无论何时进行用户输入, 必须考虑输入缓冲区中保留的每个字符(此处为stdin )。 This is especially true when taking input with scanf (or family) due to the way scanf handles input or matching failures. 由于scanf处理输入匹配失败的方式,在使用scanf (或系列)输入时尤其如此。 When either occurs, no further characters are read , and any offending characters are left unread in the input buffer -- just waiting to bite you again on your next attempted read (generally resulting in an infinite loop if you are taking input within a loop) 当两者都发生时, 不会再读取任何字符,并且任何有问题的字符都会在输入缓冲区中保持未读状态 - 只是等待您在下次尝试读取时再次咬一下(如果您在循环中接收输入,通常会导致无限循环)

(this is one of the primary reason a line-oriented function such as fgets is recommended for taking user input) (这是建议使用fgets面向行的功能来获取用户输入的主要原因之一)

scanf can be used, if used correctly. 如果使用正确,可以使用scanf This means you are responsible for checking the return of scanf every time . 这意味着 每次都要负责检查scanf返回 You must handle three conditions 你必须处理三个条件

  1. (return == EOF) the user canceling input by generating a manual EOF by pressing Ctrl+d (or on windows Ctrl+z , but see CTRL+Z does not generate EOF in Windows 10 ); (return == EOF)用户通过按Ctrl + d (或在Windows Ctrl + z上生成手动EOF ,但在Windows 10中看到CTRL + Z不生成 (return == EOF)来取消输入;
  2. (return == expected No. of conversions) indicating a successful read -- it is then up to you to check whether the input meets any additional criteria (eg positive integer, positive floating-point, etc..); (return == expected No. of conversions)表示读取成功 - 然后由您来检查输入是否满足任何其他条件(例如正整数,正浮点等); and
  3. otherwise, you must handle the matching or input failure and you must account for every character that may be left in your input buffer. 否则,您必须处理匹配输入失败,并且必须考虑输入缓冲区中可能遗留的每个字符。 (generally you will scan forward in the input buffer until a '\\n' or EOF is found discarding any extraneous characters that remain) (通常你会在输入缓冲区中向前扫描,直到发现'\\n'EOF丢弃任何剩余的无关字符)

If you do your job, you can successfully use scanf as needed. 如果您完成了工作,则可以根据需要成功使用scanf

Next, a general caution do not using floating point for currency (people get real mad when you start losing money due to rounding errors) While it is fine for your example program -- just understand, in a real currency handling program, you would handle currency as an unsigned value multiplied by 100 (or whatever is required) to insure all amounts can be represented exactly. 接下来,一般要注意不要使用浮动点作为货币 (当你因为舍入错误而开始赔钱时,人们会变得很生气)虽然你的示例程序很好 - 只要明白,在真实的货币处理程序中,你会处理货币作为无符号值乘以100 (或任何需要的值)以确保所有金额都可以准确表示。

Putting the scanf requirements together, you could do something like the following safely: 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);
}

Example Use/Output 示例使用/输出

(shown with intentional errors in entry) (显示入口中的故意错误)

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

Look things over and let me know if you have further questions. 仔细看看,如果您有其他问题,请告诉我。

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. 这是其中一种方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM