4

I have read several posts related to my question on C. This indeed help me cut down on my errors. However, I'm still having problems that other posts couldn't solve for me. Basically, this is what I am trying to do.

Define an array in main. I pass in a pointer to this array to a function. This function will open up a file, parse that file, and put information from that file into the array whose pointer I passed in. Well, it fails.

The errors I get are:

work.c:12: error: array type has incomplete element type
work.c: In function ‘main’:
work.c:20: error: type of formal parameter 1 is incomplete
work.c: At top level:
work.c:25: error: array type has incomplete element type

The entire code follows below. But I think you only need to focus on how I defined my array, and pointer, and so on.

#include <stdio.h>
#include <stdlib.h>

//Defining Preprocessed Functions 
char readFile(char array[][], int, int);
//void displayStudentInfo(int*);

//Implements Step 1 and 2 of Student Instuctions
int main(int argc, char* argv[])
{
    int x = 256;
    int y = 256;
    char arrays[x][y]; 
    readFile(&arrays,x,y);
    //displayStudentInfo(&array);
    return 0;
}

char readFile(char array[][], int x, int y)
{
    char line[256]; //Three columns 0, 1, 2 corresponds to firstname, lastname, score. 
    char* string;
    int columns = 3;

    x = 0;
    //int y; //Defines rows and columns of 2D array to store data
    //char array[x][y]; //Defines the array which stores firstname, lastname, and score



    FILE *file;
    file = fopen("input.txt", "r");

    //Test to make sure file can open 

    if(file  == NULL)
    {
        printf("Error: Cannot open file.\n");
        exit(1);
    }
    else
    {
        while(!feof(file))
        {
          /* 
            if(fgets(line, 256, file))//fgets read up to num-1 characters from stream and stores them in line
            {
                printf("%s", line);
            }
            */
            if(fgets(line,256,file)!=NULL)
            {
                for(y = 0; y < columns; y++)
                {
                    array[x][y]=strtok(fgets(line,256,file), " ");
                }
                x++;
            } 
        }
    }
    fclose(file);
}
pb2q
  • 58,613
  • 19
  • 146
  • 147
GeekyOmega
  • 1,235
  • 6
  • 16
  • 34

3 Answers3

3

You have a few problems. The first two are similar:

First, you're using an unbounded array in your function declaration: the compiler needs to know more about the argument, i.e. the dimensions. In this case it's sufficient to provide one of the dimensions:

char readFile(char array[][NUM_Y], int, int);

Now the compiler has enough information to handle the array. You can leave off a dimension like this, but it's usually better to be explicit, and declare the function as:

char readFile(char array[NUM_X][NUM_Y], int, int);

Next, when you're declaring your arrays array in main, you'll need to be more specific about dimensions - similar to the argument list for the function:

char arrays[x][NUM_Y];

Choose NUM_Y to be more than large enough fit the amount of data that you'll expect.

Next, you're not initializing x and y in main, then you go on to declare an array using those variables. This is bad because these variables can contain any garbage value, including 0, and so you'll end up with an array of unexpected dimensions/size.

Finally, when you pass the array to your function, don't de-reference it, just pass along the variable:

readFile(arrays, x, y);

In C, when you pass an array to a function, what is actually passed is a pointer to the first element. This means that the array isn't copied, and so the function has access to the area of memory that it expects to change. I'll guess that you're de-referencing because that's the way that you've learned to pass simpler types that you want to change in the function, like ints or structs, but with arrays you don't need to do this.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • Why did you write char readFile(char array[][NUM_Y], int, int); and not char readFile(char array[NUM_X][NUM_Y], int, int);? That is, why is the first [] left empty? – GeekyOmega Jul 29 '12 at 21:54
  • you **can** specify _both_, and in fact, that's usually a good idea. But it's not required. with an array argument, you can leave 1 dimension unspecified. – pb2q Jul 29 '12 at 21:56
  • Nice. Thanks. I learned a lot from your post! Why did you not like using &arrays instead of just arrays? Doesn't this create more space in the memory by copying arrays into array in the function? I thought I actually save memory space by using &array? – GeekyOmega Jul 29 '12 at 22:03
  • @GeekyOmega Arrays aren't passed by value, what is passed is a pointer to the first element. For arrays, the pointer to the first element contains the same address as the pointer to the array, so passing `&arrays` works, if the compiler accepts it. Normally, and in this case, `&arrays` has the wrong type, so the compiler will complain (at least with warnings turned on). And concerning the `char array[][NUM_Y]` in the declaration, the actual type of the function parameter is `char (*)[NUM_Y]`, pointer to array of `NUM_Y` `char`s. – Daniel Fischer Jul 29 '12 at 22:18
  • Okay, this is just for learning purposes. I want to try pass, manually, pointer to the first element. And compiler complains about it because it has wrong type. How can I rewrite readFile preproccessor and function? Something like char readFile(int*, int, int)? – GeekyOmega Jul 29 '12 at 22:31
2

char arrays[x][y]; : x,y must be constants or actual values, not variables: http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1.2.html#arrays

You can workaround this limitation by declaring a pointer instead and assign it to the address returned when reserving the memory needed using malloc(sizeof(byte)*y) x times, on each position reserved by malloc(sizeof(byte)*x): http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.13.html#malloc

NotGaeL
  • 8,344
  • 5
  • 40
  • 70
  • I changed the code to read int x = 256; and y = 256; in main. I am still getting the exact same error message. – GeekyOmega Jul 29 '12 at 21:44
  • you can do something like `#define X 4` and `char myarray[X];`, but x can't be a variable. you can just declare a pointer `char myarray[];` and then make it point to x bytes of memory reserved with malloc, like: `myarray=malloc(sizeof(char)*x);`. That's the way to assign the size of an array during execution time in C. I don't know if I'm explaining myself right, do you get what I mean? – NotGaeL Jul 29 '12 at 21:51
  • 1
    Thanks. You just taught me about malloc and I know I will need it when I work on structs. I have seen it floating around Zed Shaw's website where he teaches C. Thank you so much for your help! – GeekyOmega Jul 29 '12 at 22:04
  • 2
    In C99 and later, the array dimensions can be variables. – Daniel Fischer Jul 29 '12 at 22:22
  • you're right, and it seems to be also true for multidimensional arrays... That's good to know :) – NotGaeL Jul 29 '12 at 22:47
  • Thanks for your comments. I am learning so much! – GeekyOmega Jul 31 '12 at 18:17
1

In the definition

char arrays[x][y];

y should be always a const. There is absolutely no exception for this. Other dimension - x can be a variable when you define object on the stack on some of the compilers only.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51