简体   繁体   English

解决方法:ISO C90禁止使用可变长度数组

[英]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 ? 其次,在将任何值分配给nColnRow之前,您如何期望编译器在声明数组时知道数组的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.

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