关于C中数组的各种问题
Various questions about arrays in C
所以我现在正在尝试学习 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;
}
我的两个主要问题是:
- 为什么我不能使用 N 来定义数组 X?
- 为什么我的脚本返回:
1
4196197
4196197
4196197
4196197
4196197
4196197
4196197
4196197
4196197
The average is: 4196197
我的结果?如果您看到代码中的错误,请告诉我!
谢谢,
Ps。这显然是一个不完整的脚本。
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 */
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]);
}
Why can I not use N to define my array X?
可以。您正在使用可变长度数组。 C99 中引入了可变长度数组。您需要在 C99 模式下编译您的代码(使用 -std=c99
选项)。
Why is my script returning:
1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 The average is: 4196197
avg
未初始化。在语句中使用之前用 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 */
Why can I not use N to define my array X?
在 1999 标准之前,必须使用 常量表达式 指定数组大小,其值可以在编译时计算;这意味着要么是一个数字文字,例如 10
,一个 预处理器宏 ,它将扩展为一个数字文字,例如 #define N 10
,或者是一个涉及文字或宏的算术表达式扩展为文字:
#define X 10
...
int arr1[X];
int arr2[2 * X];
int arr3[10];
int arr4[2 * 4 + 2];
X
、2 * X
、10
、2 * 4 + 2
都是常量表达式,可以在编译时计算。
在您的代码中,N
不是常量表达式;它只是一个常规变量,其值直到 运行 时间才确定。
C99 引入了可变长度数组 的概念,其大小可以在运行 时确定。如果您使用的是 C99 编译器(例如带有 -std=c99
选项的 gcc),那么您的代码将会编译。 Visual Studio 对 C99 的支持充其量是最少的,我认为当前版本根本不支持 VLA。
VLA 有许多限制;您不能对它们使用初始化程序,也不能在文件范围内(在任何函数之外)声明它们。您要小心使用它们,因为它们的内存像任何其他本地 (auto
) 变量一样从堆栈中分配。
2011 C 标准使 VLA 成为可选(我的理解是正确实施它们是一个主要的痛苦),因此它们可能不会得到很好的支持。
Why is my script returning:
1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 The average is: 4196197
正如其他人所指出的,您在 printf
和 scanf
调用中使用了错误的转换说明符。 %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
请注意,printf
和 scanf
中的转换说明符不是对称的,这是一个重要的例子。要阅读 double
,您 必须 使用 %lf
;常规 %f
期望相应的参数是指向 float
的指针。但是,您可以使用 %f
打印双精度或浮点数。
查看您手边的 C 语言参考手册以了解这两个函数。
你还需要初始化avg
:
double avg = 0.0;
所以我现在正在尝试学习 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;
}
我的两个主要问题是:
- 为什么我不能使用 N 来定义数组 X?
- 为什么我的脚本返回:
1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 The average is: 4196197
我的结果?如果您看到代码中的错误,请告诉我!
谢谢,
Ps。这显然是一个不完整的脚本。
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 */
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]);
}
Why can I not use N to define my array X?
可以。您正在使用可变长度数组。 C99 中引入了可变长度数组。您需要在 C99 模式下编译您的代码(使用 -std=c99
选项)。
Why is my script returning:
1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 The average is: 4196197
avg
未初始化。在语句中使用之前用 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 */
Why can I not use N to define my array X?
在 1999 标准之前,必须使用 常量表达式 指定数组大小,其值可以在编译时计算;这意味着要么是一个数字文字,例如 10
,一个 预处理器宏 ,它将扩展为一个数字文字,例如 #define N 10
,或者是一个涉及文字或宏的算术表达式扩展为文字:
#define X 10
...
int arr1[X];
int arr2[2 * X];
int arr3[10];
int arr4[2 * 4 + 2];
X
、2 * X
、10
、2 * 4 + 2
都是常量表达式,可以在编译时计算。
在您的代码中,N
不是常量表达式;它只是一个常规变量,其值直到 运行 时间才确定。
C99 引入了可变长度数组 的概念,其大小可以在运行 时确定。如果您使用的是 C99 编译器(例如带有 -std=c99
选项的 gcc),那么您的代码将会编译。 Visual Studio 对 C99 的支持充其量是最少的,我认为当前版本根本不支持 VLA。
VLA 有许多限制;您不能对它们使用初始化程序,也不能在文件范围内(在任何函数之外)声明它们。您要小心使用它们,因为它们的内存像任何其他本地 (auto
) 变量一样从堆栈中分配。
2011 C 标准使 VLA 成为可选(我的理解是正确实施它们是一个主要的痛苦),因此它们可能不会得到很好的支持。
Why is my script returning: 1 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 4196197 The average is: 4196197
正如其他人所指出的,您在 printf
和 scanf
调用中使用了错误的转换说明符。 %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
请注意,printf
和 scanf
中的转换说明符不是对称的,这是一个重要的例子。要阅读 double
,您 必须 使用 %lf
;常规 %f
期望相应的参数是指向 float
的指针。但是,您可以使用 %f
打印双精度或浮点数。
查看您手边的 C 语言参考手册以了解这两个函数。
你还需要初始化avg
:
double avg = 0.0;