views:

116

answers:

2

Hi! I have problems with this program. The idea is to read strings from text file and include them in 2D dynamic array with constant number of columns and varying number of rows. If the initial number of rows is not enough to include all strings the memory block for the array has to be reallocated. The code is compiling OK but the execution is impossible.

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define SIZE 80
#define DELTA 5

char** include(char b[SIZE],char** p,int n,int k,int flag);
void output(char **p,int k);

int main(void)
{
char **ptr;  
FILE *fp;    
int i=0,koef=1;
char buffer[SIZE];

 if((ptr=(char **)malloc(DELTA*sizeof(char *)))==NULL){  
  printf("Error!Memory not allocated!\n");
  exit(1);
 }
 if((fp=fopen("test.txt", "r")) == NULL) {  
            printf("Cannot open file.\n");
            exit(1);
 }
 do{    
  if(fgets(buffer,sizeof(buffer),fp)==NULL){  
         printf("Error while reding file!\n");
  exit(1);
  }  
  if(i<(DELTA*koef))  
  ptr=include(buffer,ptr,i,koef,1);                                                                                  
 else {
         koef++; 
         ptr=include(buffer,ptr,i,koef,2);
 } 
  i++;    
  }while(!feof(fp));  

 free(ptr);        

 return 0;
}

char** include(char b[SIZE],char** p,int n,int k,int flag)
{
  switch(flag){
      case 1: *(p+n)=(char *)malloc(sizeof(b));
              strcpy( *(p+n),b);
       break;
      case 2: if((p=(char **)realloc(p,k*DELTA*sizeof(char *)))==NULL){ 
                  printf("Error!Memory not allocated!\n");
                  exit(1);
       }
      *(p+n)=(char *)malloc(sizeof(b));
      strcpy(*(p+n),b);     
      break;
}
  return p;
 }

void output(char **p,int k)
{
  int j;
  for(j=0;j<k;j++)
  printf("%s\n",*(p+j));
}
A: 

fgets() returns a NULL when end of file is reached or there is an error. In your case, as you are checking in a do-while loop,so the condition feof(fp) is never reached as you exit on checking the return value of fgets().
You should do like this:


while(fgets(buffer,sizeof(buffer),fp)!=NULL)
{
  if(ferror(fp))
  {
    printf("Error Reading file\n");
    exit(1);
  }
  if(i <(DELTA*koef))
  ptr=include(buffer,ptr,i,koef,1);
  else {
         koef++;
         ptr=include(buffer,ptr,i,koef,2);
  }
  i++;
}


Neeraj
+2  A: 

Specifying the size of an array argument has no effect.

void func(char b[SIZE]);

Is equivalent to

void func(char *b);

Consequently, when you say

case 1: *(p+n)=(char *)malloc(sizeof(b));

The sizeof will evaluate to the size of a pointer to char. Try using

case 1: *(p+n)=(char *)malloc(SIZE * sizeof(b));

The same error occurs where you say

*(p+n)=(char *)malloc(sizeof(b));

Which you could change to

*(p+n)=(char *)malloc(SIZE * sizeof(b));

You should set size so that the buffer has space for the entire line including the newline character and also the terminating \0. Otherwise, strcpy will not work correctly. You should use strncopy anyway. Once you make those changes, fgets will return 0 once the end of the file is reached and your program will report "Error while reding file!". You should change the termination of the read-loop accordingly.

Furthermore, you are not actually using a multidimensional array. You are using an array of pointers to arrays of characters. In C, a 2-dimensional array would be allocated in a contiguous block of memory and accessed in row-major order. This would be OK in your case because all rows are supposed to have the same length. Nevertheless, you are trying to maintain an array of pointers which in turn point to the rows. This also works but is not technically what we would call a multidimensional array in C. Its called an Iliffe vector or simply an array of arrays.

All in all, your code is rather intertwined and hard to follow. You should try and simplify your program which will make finding errors much easier for you in the future.

VoidPointer