0

I'm new to C but I've programmed in pascal a few weeks ago. In pascal, if you want to change an arrays data, you pass by reference, by typing var myArray essentially. I can't figure out how to do this in C. I've read a ton of questions but none seem to work. Here's what I have so far.

void set_up_elements(char (*array_to_populate)[20])
{
    char* buffer;
    FILE *f;
    f=fopen("elementList.txt","r");
    char copied_text[118][20];
    int i=0;
    while (!feof(f))
    {
        fgets(copied_text[i],80,f);
        ++i;
    }
    //Close the file to free up memory and prevent leaks
    fclose(f);
    f = NULL;
}

Here is my code to populate the array, i read a list of the elements in the periodic table in to the array copied_text. This part works, it successfully populates the array that is INSIDE the function.

int main()
{
    char element_array[118][20];
    set_up_elements(element_array);
<..>
}

This is how i'm trying to call it. The contents of the array element_array doesn't change. Does anyone know how to fix this? Thanks.

Anteara
  • 729
  • 3
  • 14
  • 33
  • 3
    set_up_elements(&element_array); – Lithu T.V Apr 24 '13 at 16:10
  • 1
    Also I think copied_text should be [118][80] since you want to copy 80 characters to it, not 20 characters. – David Apr 24 '13 at 16:11
  • possibly related: http://stackoverflow.com/questions/9446707/correct-way-of-passing-2-dimensional-array-into-a-function – Arun Apr 24 '13 at 16:16
  • See http://c-faq.com/aryptr/pass2dary.html for passing 2-dimensional array to a function – Arun Apr 24 '13 at 16:18
  • 2
    It could be a crash if the file contains more than 118 lines and a line contains more than 20 characters. You would check that. Anyway replace `copied_text` to `array_to_populate` in the `set_up_elements` function's `while` loop (definition of new array is also not needed). – TrueY Apr 24 '13 at 16:21
  • @LithuT.V No, that would be the wrong type. The type and calling of `set_up_elements` is 100% correct as is. – Daniel Fischer Apr 24 '13 at 18:19

3 Answers3

3

1) The following line is wrong

fgets(copied_text[i],80,f);

the size of one element string in your array of strings is 20. and you put as maximum chrachter to read in your fgets() function is 80

so change it to :

fgets(copied_text[i],sizeof(copied_text[0]),f);

2) and you can change this code:

while (!feof(f))
    {
        fgets(copied_text[i],80,f);
        ++i;
    }

with

while (i<118 && fgets(copied_text[i++],80,f));

3) The input parameter of your function

void set_up_elements(char (*array_to_populate)[20])

is not used in your function. it seems that you want to fill it in your function but it's not the case and you are using another array (local array) which could not be seen by the caller

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • Thanks, I had some errors in my original post, changing the fgets first argument from `copied_text` to `array_to_populate` fixed it. Thanks. – Anteara Apr 24 '13 at 16:44
1

Apply the right-left reading rule in understanding the problem...

char element_array[118][20] means that element_array is an array of 118 blocks of 20 chars.

On the other hand, in char (*array_to_populate)[20] array_to_populate is a pointer to an array of 20 chars because of the parens.

You could use char (&array_to_populate)[118][20] which means that array_to_populate is a reference to 118 blocks of 20 chars.

That said, the big issue is that in your function, you are reading into a temporary array that you never copy into the passed in array. In addition, your file read is the wrong size. The following should get the job done...

#define DIM1 118
#define DIM2 20

void set_up_elements(char (&array_to_populate)[DIM1][DIM2])
{
    int i=0;
    FILE *f=fopen("elementList.txt","r");

    for (i = 0; f && !feof(f) && i < DIM1; i++ )
    {
        fgets(array_to_populate[i],sizeof(array_to_populate[0]),f);
    }

    //Close the file to free up memory and prevent leaks
    fclose(f);
}
K Scott Piel
  • 4,320
  • 14
  • 19
  • Argh, this part `fgets(array_to_populate` I completely overlooked... I can't believe that, I looked through my code 50 times and didn't realize the fact that I wasn't referencing the parameter... I feel so silly for that... After changing that, I tested it with `(char (*array_to_populate)[20])` and `(char (&array_to_populate)[DIM1][DIM2])`, and they both work, however, changing it to your method does look neater. I know * is the symbol for a pointer, but what exactly is &? is it essentially used as a 'pass by reference' symbol (like pascals `var arrayToPopulate`? – Anteara Apr 24 '13 at 16:32
  • 1
    Correct... the '&' means pass by reference and you treat it as though it were the original variable rather than a pointer to it. It also allows you to define all of the dimensions of the array on the prototype so that you can't pass a wrong-sized array to it. – K Scott Piel Apr 24 '13 at 16:50
  • 1
    @Anteara `void set_up_elements(char (&array_to_populate)[DIM1][DIM2])` would not compile in C, that's C++. Your declaration and calling of `set_up_elements` was 100% correct. You just did not copy into the argument in the function body. (And of course, you didn't check that you remained inside the array bounds.) – Daniel Fischer Apr 24 '13 at 18:18
1
void set_up_elements(char (*array_to_populate)[20])
{
    char* buffer;//unuse var
    FILE *f;
    f=fopen("elementList.txt","r");
    int i=0;
    while (!feof(f))//caution
    {
        fgets(&(*array_to_populate[i]),20,f);
        ++i;
    }
    //Close the file to free up memory and prevent leaks
    fclose(f);
    f = NULL;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • Undid the down vote and removed my comments as not applicable. – K Scott Piel Apr 24 '13 at 16:31
  • My original post is bad code, it's 2:30 AM and I overlooked a vital part which was i was passing the wrong variable in to fgets, hence why the data wasn't changing outside of the function. However, I did remove the unused buffer variable, and in reading up on your `//caution` comment... is it because the EOF won't be set when you're reading the last line, even though you're at the last line, resulting in the last line being read possibly twice? – Anteara Apr 24 '13 at 16:42
  • 1
    @Anteara That's right. The data itself will turn around in the extra loop if you have just finished reading but it does not become the EOF. – BLUEPIXY Apr 24 '13 at 16:46
  • Note that in the solution I proposed, I added a test for the row exceeding DIM1 -- that prevents the condition of trying to read an extra block from occurring. – K Scott Piel Apr 24 '13 at 16:58
  • It is so. Such information should be given. And though I'm the same if they are less than you planned data. – BLUEPIXY Apr 24 '13 at 17:02