【问题标题】:Various questions about arrays in C关于 C 中数组的各种问题
【发布时间】:2015-01-20 16:03:19
【问题描述】:

所以我现在正在尝试学习 C,并且我正在编写基本脚本以确保我有基础,但我正在努力理解以下代码的问题:

#include <stdio.h> //Linking external libraries.
#include <math.h>

int main(void) {
    /* First I will set my variables.
    */
    double std; //Standard Deviation
    double sqdif;
    double avg;
    int N=10; //number of elements
    double X[10]; //Not sure why I cannot use N here.
    int i;


    /* Now I will prompt for input and listen for values,
    then assign those values respectively.*/

    for (i = 1; i < 11; i++) {
        printf("Please enter X[ %d ", i);
        printf("]: ");
        scanf("%d", &X[i-1]);
    }

    for (i = 0; i < N; i++) {
        avg = avg + X[i];
        printf("\n %d", X[i]);
    }
    avg = avg / N;
    printf("\nThe average is: %d", avg);


    return 0;
}

我的两个主要问题是这样的:

  1. 为什么我不能使用 N 来定义我的数组 X?
  2. 为什么我的脚本会返回:

1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 平均值为:4196197

为了我的结果?如果您在代码中看到错误,请告诉我!

谢谢,

附言。这显然是一个不完整的脚本。

【问题讨论】:

  • 对于问题 1:您遇到什么错误?如果你尝试双 X[N]; ?
  • 您不能在double X[N] 中使用N 作为您的下标,因为N 是可变的。请改用const int N = 10;,您需要使用C99 标准。将for (i = 0; i &lt; N; i++) 更改为for (avg = 0, i = 0; i &lt; N; i++) 以在循环之前初始化avg
  • double X[10] 调用scanf("%d", &amp;X[i-1]) 是一个非常糟糕的主意。
  • 您的 printf 也使用 %d 作为双精度数。使用 %f。
  • 保持一致。循环从01 开始。转到N11.、i-1i。这是一个巨大的混乱。

标签: c arrays scanf


【解决方案1】:

为什么我不能使用 N 来定义我的数组 X?

在 1999 年标准之前,必须使用 常量表达式 指定数组大小,其值可以在编译时计算;这意味着要么是一个数字文字,例如10,一个预处理器宏,它将扩展为一个数字文字,例如#define N 10,或者一个涉及文字或扩展为文字的宏的算术表达式:

#define X 10
...
int arr1[X];     
int arr2[2 * X];
int arr3[10];
int arr4[2 * 4 + 2];

X2 * X102 * 4 + 2 都是常量表达式,可以在编译时求值。

在您的代码中,N 不是常量表达式;它只是一个常规变量,其值直到运行时才确定。

C99 引入了可变长度数组的概念,其大小可以在运行时确定。如果您使用了 C99 编译器(例如,带有 -std=c99 选项的 gcc),那么您的代码就会被编译。 Visual Studio 对 C99 的支持充其量是最少的,我认为当前版本根本不支持 VLA。

VLA 有许多限制;您不能对它们使用初始化程序,也不能在文件范围内(在任何函数之外)声明它们。你要小心它们,因为它们的内存是从堆栈中分配的,就像任何其他本地 (auto) 变量一样。

2011 C 标准使 VLA 成为可选的(我的理解是正确实施它们是一个主要的痛苦),因此它们可能不会得到很好的支持。

为什么我的脚本返回: 1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 平均为:4196197

正如其他人指出的那样,您在 printfscanf 调用中使用了错误的转换说明符。 %d 期望相应参数的类型为 int(对于 printf)和 int *(对于 scanf)。您需要改用 %f%lf

scanf("%lf", &X[i-1]);  // %lf expects pointer to double
...
printf("%f", X[i-1]);  // %f expects double

请注意,printfscanf 中的转换说明符不是对称的,这是重要的一种情况。要阅读double,您必须使用%lf;常规的%f 期望相应的参数是指向float 的指针。但是,您可以使用%f 打印双精度或浮点数。

查看您方便的 C 参考手册以了解这两个函数。

还需要初始化avg:

double avg = 0.0;

【讨论】:

  • 非常彻底!出色的反应。这回答了我的关键问题。
【解决方案2】:
printf("\n %d", X[i]);

应该是

printf("\n %f", X[i]);

因为X[i] 的类型是double

即使没有错,请考虑像这样重写 for 循环以获得更好的可读性,当然还要再次将 %d 更改为 %f

 for (i =0; i < 10; i++) {
        printf("Please enter X[ %d ]:", i);
        scanf("%f", &X[i]);
    }

【讨论】:

  • 同样的修复也需要应用于scanf 语句。
  • 谢谢! printf 语句特别有用。
【解决方案3】:

为什么我不能使用 N 来定义我的数组 X?

你可以。您正在使用可变长度数组。 C99 中引入了可变长度数组。您需要在 C99 模式下编译代码(使用 -std=c99 选项)。

为什么我的脚本会返回:
1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 平均为:4196197

avg 未初始化。在使用 in 语句之前使用 0 对其进行初始化:

avg = avg + X[i];  

否则程序会因为未定义的行为而出现错误。另请注意,%lf%f 分别用于扫描和打印 double 数据类型。

double avg = 0; /* Initialize it with 0 */
int N=10; 
double X[N]; /* Variable length array. C99 mode needed to compile the code */

【讨论】:

  • 非常感谢。来自 Java 的东西有点不同,所以边走边学。欣赏它。
  • 请注意,VLA 在 C2011 中现在是可选,因此未来对它们的支持可能会参差不齐。
【解决方案4】:
avg = avg + X[i];

avg 从未初始化,avg 的值不确定,因此您会看到未定义的行为。

你有另一个 UB

printf("\n %d", X[i]);

printf() 中使用错误的格式说明符将是UB。

printf("\n %lf", X[i]);

您扫描来自 0-9 的值并打印来自 0-10 的值,这里您再次使用未初始化的 a[10] 元素。

汇总变化应该是这样的:

 avg = 0;

    for (i = 0; i < N; i++) {
        printf("Please enter X[ %d ", i);
        printf("]: ");
        scanf("%lf", &X[i]);
    }

    for (i = 0; i < N; i++) {
        avg = avg + X[i];
        printf("\n %lf", X[i]);
    }
    avg = avg / N;
    printf("\nThe average is: %lf", avg);

C99 支持 VLA(可变长度数组),您可以使用它们

int N = 10;
double X[N]; /* Valid */

【讨论】:

  • 随便。措辞不好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 2019-09-16
  • 2014-02-21
  • 1970-01-01
相关资源
最近更新 更多