解决方法:ISO C90 禁止可变长度数组
Workaround: ISO C90 forbids variable length array
我正在读取一个名为 reg.dat 的文件,并将每列中的第一个变量设置为变量 Y 的索引,并将每列中的其余变量设置为 X 的索引。然后,我想要将 X 和 Y 输入 dgesv 函数以计算线性回归。
我的代码如下(分块,因为我无法一次将其全部包含在此网站上)。我在 运行 gcc -ansi -pedantic readReg.c -o readReg -llapack -lblas -lgfortran
时得到的错误如下:
readReg.c: In function ‘main’:
readReg.c:18: warning: ISO C90 forbids variable length array ‘ipiv’
readReg.c:19: warning: ISO C90 forbids variable length array ‘X1’
readReg.c:19: warning: ISO C90 forbids variable length array ‘X1’
readReg.c:19: warning: ISO C90 forbids variable length array ‘XtX’
readReg.c:19: warning: ISO C90 forbids variable length array ‘XtY’
readReg.c:48: error: subscripted value is neither array nor pointer
例如,如果文件 reg.dat 是:
5.1 3.5 1.4
4.9 3 1.4
4.7 3.2 1.3
4.6 3.1 1.5
5 3.6 1.4
然后 X = [5.1, 4.9, 4.7, 4.6, 5] 和 Y = [3.5, 1.4, 3, 1.4, 3.2, 1.3, 3.1, 1.5, 3.6, 1.4]:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int getCol(char *myStr);
int getRow(char *fileName);
int assignY(int nCol, int nRow, double *Y, char *fileName);
int assignX(int nCol, int nRow, double *X, char *fileName);
void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
int main(){
FILE *f;
char myStr[1000];
int strL;
int nCol;
int nRow;
char *fileName = "reg.dat";
int i, j, k, n1=nCol, n2=1, ipiv[nCol], info;
double X1[nRow][nCol], XtX[(nCol) * (nCol)], XtY[nCol];
double *X;
double *Y;
f = fopen(fileName, "r");
if (f == NULL) perror ("Error opening file");
else {
if (fgets(myStr, 1000, f) != NULL )
puts(myStr);
fclose(f);
}
strL = strlen(myStr);
nCol = getCol(myStr);
nRow = getRow(fileName);
printf("Sample size and number of predictors are %d and %d respectively.\n", nRow, nCol-1);
X = (double *) malloc(sizeof(double) * ((nCol-1) * nRow));
Y = (double *) malloc(sizeof(double) * nRow);
assignY(nCol, nRow, Y, fileName);
assignX(nCol, nRow, X, fileName);
接下来,我操纵 X 和 Y...
/* The following is for doing the dgesv function */
/* design matrix */
for (i=0; i<nRow; i++){
X1[i][0] = 1;
for (j=1; j<n1; j++)
X1[i][j] = X[i][j-1];
}
/* t(X1) %*% X1 */
for (i=0; i<n1; i++){
for (j=0; j<n1; j++){
XtX[i*n1+j] = 0;
for (k=0; k<nRow; k++)
XtX[i*n1+j] += X1[k][i] * X1[k][j];
}
}
/* t(X1) %*% Y */
for (i=0; i<n1; i++){
XtY[i] = 0;
for (j=0; j<nRow; j++){
XtY[i] += X1[j][i] * Y[j];
}
}
接下来我打印结果
/* XtX is symmetric, no transpose needed before passing to Fortran subrountine */
dgesv_(&n1, &n2, XtX, &n1, ipiv, XtY, &n1, &info);
if (info!=0) printf("failure with error %d\n", info);
/* print beta */
printf("The regression coefficients: ");
for (i=0; i<n1; i++){
printf("%f ", XtY[i]);
}
printf("\n");
return 0;
}
辅助函数...
int assignY(int nCol, int nRow, double *Y, char *fileName){
int i=0;
int j;
char string[1000];
char* data = NULL;
FILE *f;
f = fopen(fileName, "r");
while(fgets(string, sizeof(string), f) != NULL){
data = strtok(string, " ");
for (j=0; NULL != data && j<nCol; j++){
if (data[strlen(data) - 1] == '\n')
data[strlen(data) - 1] = '[=15=]';
if (j==0){
Y[i] = atof(data);
i++;
}
data = strtok(NULL, " ");
}
}
for (i=0;i<nRow;i++){
printf("%f\n", Y[i]);
}
return 0;
}
辅助函数...
int assignX(int nCol, int nRow, double *X, char *fileName){
int i=0;
int j;
char string[1000];
char* data = NULL;
FILE *f;
f = fopen(fileName, "r");
while(fgets(string, sizeof(string), f) != NULL){
data = strtok(string, " ");
for (j=0; NULL != data && j<nCol; j++){
if (data[strlen(data) - 1] == '\n')
data[strlen(data) - 1] = '[=16=]';
if (j!=0){
X[i] = atof(data);
i++;
}
data = strtok(NULL, " ");
}
}
for (i=0;i<(nRow*(nCol-1));i++){
printf("%f\n", X[i]);
}
return 0;
}
辅助函数...
int getCol(char *myStr){
int length,i,count=0;
char prev;
length=strlen(myStr);
if(length > 0){
prev = myStr[0];
}
for(i=0; i<=length; i++){
if(myStr[i]==' ' && prev != ' '){
count++;
}
prev = myStr[i];
}
if(count > 0 && myStr[i] != ' '){
count++;
}
return count;
}
int getRow(char *fileName){
char ch;
int count=0;
FILE *f;
f = fopen(fileName, "r");
while(!feof(f)){
ch = fgetc(f);
if(ch == '\n')
{
count++;
}
}
fclose(f);
return count;
}
编辑:
我现在为 X1、XtY、XtX 和 ipiv 更改为 malloc()。我现在还为 X1 使用了多维动态数组。当我 运行 gcc 时,错误都消失了,除了:
readReg.c: In function ‘main’:
readReg.c:62: error: subscripted value is neither array nor pointer
下面是更新后的主函数:
int main(){
FILE *f;
char myStr[1000];
int strL;
int nCol;
int nRow;
char *fileName = "reg.dat";
int i, j, k, n1=nCol, n2=1, info;
double *X;
double *Y;
double **X1;
double *XtX;
double *XtY;
int *ipiv;
double *temp;
f = fopen(fileName, "r");
if (f == NULL) perror ("Error opening file");
else {
if (fgets(myStr, 1000, f) != NULL )
puts(myStr);
fclose(f);
}
strL = strlen(myStr);
nCol = getCol(myStr);
nRow = getRow(fileName);
printf("Sample size and number of predictors are %d and %d respectively.\n", nRow, nCol-1);
X = (double *) malloc(sizeof(double) * ((nCol-1) * nRow));
Y = (double *) malloc(sizeof(double) * nRow);
XtX = (double *) malloc(sizeof(double) * (nCol*nCol));
XtY = (double *) malloc(sizeof(double) * nCol);
ipiv = (int *) malloc(sizeof(int) * nCol);
assignY(nCol, nRow, Y, fileName);
assignX(nCol, nRow, X, fileName);
X1 = malloc(nRow * sizeof(double*));
temp = malloc(nRow * nCol * sizeof(double));
for (i= 0; i < nRow; i++) {
X1[i] = temp + (i * nCol);
}
...
}
您首先声明 nRow 和 nCol 而不分配任何值:
int nCol;
int nRow;
...现在定义四个使用 nRow 和 nCol 的可变长度数组:
int i, j, k, n1=nCol, n2=1, ipiv[nCol], info;
double X1[nRow][nCol], XtX[(nCol) * (nCol)], XtY[nCol];
首先,C90禁止使用变长数组。对这些使用 malloc()
。根据您的代码,您似乎知道如何使用 malloc()
。
其次,在为 nCol
和 nRow
赋值之前声明数组时,您如何期望编译器知道数组有多大?
你的一个数组是多维的。有关如何使用动态多维数组的详细信息,请参阅 How do I work with dynamic multi-dimensional arrays in C?。
我正在读取一个名为 reg.dat 的文件,并将每列中的第一个变量设置为变量 Y 的索引,并将每列中的其余变量设置为 X 的索引。然后,我想要将 X 和 Y 输入 dgesv 函数以计算线性回归。
我的代码如下(分块,因为我无法一次将其全部包含在此网站上)。我在 运行 gcc -ansi -pedantic readReg.c -o readReg -llapack -lblas -lgfortran
时得到的错误如下:
readReg.c: In function ‘main’:
readReg.c:18: warning: ISO C90 forbids variable length array ‘ipiv’
readReg.c:19: warning: ISO C90 forbids variable length array ‘X1’
readReg.c:19: warning: ISO C90 forbids variable length array ‘X1’
readReg.c:19: warning: ISO C90 forbids variable length array ‘XtX’
readReg.c:19: warning: ISO C90 forbids variable length array ‘XtY’
readReg.c:48: error: subscripted value is neither array nor pointer
例如,如果文件 reg.dat 是:
5.1 3.5 1.4
4.9 3 1.4
4.7 3.2 1.3
4.6 3.1 1.5
5 3.6 1.4
然后 X = [5.1, 4.9, 4.7, 4.6, 5] 和 Y = [3.5, 1.4, 3, 1.4, 3.2, 1.3, 3.1, 1.5, 3.6, 1.4]:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int getCol(char *myStr);
int getRow(char *fileName);
int assignY(int nCol, int nRow, double *Y, char *fileName);
int assignX(int nCol, int nRow, double *X, char *fileName);
void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
int main(){
FILE *f;
char myStr[1000];
int strL;
int nCol;
int nRow;
char *fileName = "reg.dat";
int i, j, k, n1=nCol, n2=1, ipiv[nCol], info;
double X1[nRow][nCol], XtX[(nCol) * (nCol)], XtY[nCol];
double *X;
double *Y;
f = fopen(fileName, "r");
if (f == NULL) perror ("Error opening file");
else {
if (fgets(myStr, 1000, f) != NULL )
puts(myStr);
fclose(f);
}
strL = strlen(myStr);
nCol = getCol(myStr);
nRow = getRow(fileName);
printf("Sample size and number of predictors are %d and %d respectively.\n", nRow, nCol-1);
X = (double *) malloc(sizeof(double) * ((nCol-1) * nRow));
Y = (double *) malloc(sizeof(double) * nRow);
assignY(nCol, nRow, Y, fileName);
assignX(nCol, nRow, X, fileName);
接下来,我操纵 X 和 Y...
/* The following is for doing the dgesv function */
/* design matrix */
for (i=0; i<nRow; i++){
X1[i][0] = 1;
for (j=1; j<n1; j++)
X1[i][j] = X[i][j-1];
}
/* t(X1) %*% X1 */
for (i=0; i<n1; i++){
for (j=0; j<n1; j++){
XtX[i*n1+j] = 0;
for (k=0; k<nRow; k++)
XtX[i*n1+j] += X1[k][i] * X1[k][j];
}
}
/* t(X1) %*% Y */
for (i=0; i<n1; i++){
XtY[i] = 0;
for (j=0; j<nRow; j++){
XtY[i] += X1[j][i] * Y[j];
}
}
接下来我打印结果
/* XtX is symmetric, no transpose needed before passing to Fortran subrountine */
dgesv_(&n1, &n2, XtX, &n1, ipiv, XtY, &n1, &info);
if (info!=0) printf("failure with error %d\n", info);
/* print beta */
printf("The regression coefficients: ");
for (i=0; i<n1; i++){
printf("%f ", XtY[i]);
}
printf("\n");
return 0;
}
辅助函数...
int assignY(int nCol, int nRow, double *Y, char *fileName){
int i=0;
int j;
char string[1000];
char* data = NULL;
FILE *f;
f = fopen(fileName, "r");
while(fgets(string, sizeof(string), f) != NULL){
data = strtok(string, " ");
for (j=0; NULL != data && j<nCol; j++){
if (data[strlen(data) - 1] == '\n')
data[strlen(data) - 1] = '[=15=]';
if (j==0){
Y[i] = atof(data);
i++;
}
data = strtok(NULL, " ");
}
}
for (i=0;i<nRow;i++){
printf("%f\n", Y[i]);
}
return 0;
}
辅助函数...
int assignX(int nCol, int nRow, double *X, char *fileName){
int i=0;
int j;
char string[1000];
char* data = NULL;
FILE *f;
f = fopen(fileName, "r");
while(fgets(string, sizeof(string), f) != NULL){
data = strtok(string, " ");
for (j=0; NULL != data && j<nCol; j++){
if (data[strlen(data) - 1] == '\n')
data[strlen(data) - 1] = '[=16=]';
if (j!=0){
X[i] = atof(data);
i++;
}
data = strtok(NULL, " ");
}
}
for (i=0;i<(nRow*(nCol-1));i++){
printf("%f\n", X[i]);
}
return 0;
}
辅助函数...
int getCol(char *myStr){
int length,i,count=0;
char prev;
length=strlen(myStr);
if(length > 0){
prev = myStr[0];
}
for(i=0; i<=length; i++){
if(myStr[i]==' ' && prev != ' '){
count++;
}
prev = myStr[i];
}
if(count > 0 && myStr[i] != ' '){
count++;
}
return count;
}
int getRow(char *fileName){
char ch;
int count=0;
FILE *f;
f = fopen(fileName, "r");
while(!feof(f)){
ch = fgetc(f);
if(ch == '\n')
{
count++;
}
}
fclose(f);
return count;
}
编辑:
我现在为 X1、XtY、XtX 和 ipiv 更改为 malloc()。我现在还为 X1 使用了多维动态数组。当我 运行 gcc 时,错误都消失了,除了:
readReg.c: In function ‘main’:
readReg.c:62: error: subscripted value is neither array nor pointer
下面是更新后的主函数:
int main(){
FILE *f;
char myStr[1000];
int strL;
int nCol;
int nRow;
char *fileName = "reg.dat";
int i, j, k, n1=nCol, n2=1, info;
double *X;
double *Y;
double **X1;
double *XtX;
double *XtY;
int *ipiv;
double *temp;
f = fopen(fileName, "r");
if (f == NULL) perror ("Error opening file");
else {
if (fgets(myStr, 1000, f) != NULL )
puts(myStr);
fclose(f);
}
strL = strlen(myStr);
nCol = getCol(myStr);
nRow = getRow(fileName);
printf("Sample size and number of predictors are %d and %d respectively.\n", nRow, nCol-1);
X = (double *) malloc(sizeof(double) * ((nCol-1) * nRow));
Y = (double *) malloc(sizeof(double) * nRow);
XtX = (double *) malloc(sizeof(double) * (nCol*nCol));
XtY = (double *) malloc(sizeof(double) * nCol);
ipiv = (int *) malloc(sizeof(int) * nCol);
assignY(nCol, nRow, Y, fileName);
assignX(nCol, nRow, X, fileName);
X1 = malloc(nRow * sizeof(double*));
temp = malloc(nRow * nCol * sizeof(double));
for (i= 0; i < nRow; i++) {
X1[i] = temp + (i * nCol);
}
...
}
您首先声明 nRow 和 nCol 而不分配任何值:
int nCol;
int nRow;
...现在定义四个使用 nRow 和 nCol 的可变长度数组:
int i, j, k, n1=nCol, n2=1, ipiv[nCol], info;
double X1[nRow][nCol], XtX[(nCol) * (nCol)], XtY[nCol];
首先,C90禁止使用变长数组。对这些使用 malloc()
。根据您的代码,您似乎知道如何使用 malloc()
。
其次,在为 nCol
和 nRow
赋值之前声明数组时,您如何期望编译器知道数组有多大?
你的一个数组是多维的。有关如何使用动态多维数组的详细信息,请参阅 How do I work with dynamic multi-dimensional arrays in C?。