[英]Workaround: ISO C90 forbids variable length array
I am reading from a file called reg.dat, and setting the first variable in each column as an index of variable Y, and the remaining variables in each column as a index of X. Then, I want to feed X and Y into dgesv function to calculate the linear regression. 我正在从一个名为reg.dat的文件中读取文件,并将每列中的第一个变量设置为变量Y的索引,并将每列中的其余变量设置为X的索引。然后,我想将X和Y馈入dgesv函数来计算线性回归。
My code to do so follows (in chunks, because I could not include it all at once on this website). 我执行此操作的代码如下(成块,因为我无法一次将其全部包含在此网站上)。 The error I get when I run gcc -ansi -pedantic readReg.c -o readReg -llapack -lblas -lgfortran
, is as follows: 运行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
For instance, if the file reg.dat is: 例如,如果文件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
then X = [5.1, 4.9, 4.7, 4.6, 5] and Y = [3.5, 1.4, 3, 1.4, 3.2, 1.3, 3.1, 1.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);
Next, I manipulate X and Y... 接下来,我操纵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];
}
}
Next I print results 接下来我打印结果
/* 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;
}
Helper functions... 辅助功能...
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] = '\0';
if (j==0){
Y[i] = atof(data);
i++;
}
data = strtok(NULL, " ");
}
}
for (i=0;i<nRow;i++){
printf("%f\n", Y[i]);
}
return 0;
}
Helper functions... 辅助功能...
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] = '\0';
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;
}
Helper functions... 辅助功能...
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;
}
EDIT: 编辑:
I now changed to malloc() for X1, XtY, XtX, and ipiv. 现在,我将X1,XtY,XtX和ipiv更改为malloc()。 I also now used multi-dimensional dynamic array for X1. 现在,我还为X1使用了多维动态数组。 The errors are all gone when I run gcc, except for: 运行gcc时,所有错误均消失了,除了:
readReg.c: In function ‘main’:
readReg.c:62: error: subscripted value is neither array nor pointer
Below is the updated main function: 以下是更新后的主要功能:
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);
}
...
}
You first declare nRow and nCol without assigning any value: 您首先声明nRow和nCol而不分配任何值:
int nCol;
int nRow;
...and now define four variable-length arrays which use nRow and nCol: ...现在定义四个使用nRow和nCol的可变长度数组:
int i, j, k, n1=nCol, n2=1, ipiv[nCol], info;
double X1[nRow][nCol], XtX[(nCol) * (nCol)], XtY[nCol];
Firstly, variable-length arrays are forbidden in C90. 首先,在C90中禁止使用可变长度数组。 Use malloc()
for these. 为此使用malloc()
。 You seem to know how to use malloc()
based on your code. 您似乎知道如何根据您的代码使用malloc()
。
Secondly, how do you expect the compiler to know how large the arrays are as you declare the arrays before assigning any value to nCol
and nRow
? 其次,在将任何值分配给nCol
和nRow
之前,您如何期望编译器在声明数组时知道数组的nRow
?
One of your arrays is multidimensional. 数组之一是多维的。 See How do I work with dynamic multi-dimensional arrays in C? 请参阅如何在C中使用动态多维数组? for more information how to work with dynamic multidimensional arrays. 有关更多信息,请参见如何使用动态多维数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.