#include <stdio.h>

int fill_array(void);
int display_array(int count);

typedef struct
{
    char worker_name[20];
    float  hourly_pay;
    int  hours;
}WorkerRecord;

int main()
{
    WorkerRecord info[50];
    int count, k;
    float average_wage;
    
    count = fill_array();
    display_array(count);
    
    for(k = 0, average_wage = 0; k < count; k++)
    {
        average_wage += info[k].hourly_pay;
    }
    
    average_wage /= count;
    
    printf("\nAverage Hourly Wage: $%.2f", average_wage);


    printf("\n\nPress any key to continue...");
    getchar();
    return 0;
}

int fill_array(void)
{
    WorkerRecord info[50];
    int count = 0;
    
    FILE * pointer;
    
    pointer = fopen("workers.txt", "r");
    
    if(pointer == NULL)
    {
        printf("The file can not be found.\n\n\n");
        printf("Press any key to continue...");
        getchar();
        return 1;
    }
    
    while(!feof(pointer))
    {
        fscanf(pointer, "%s%d%f", info[count].worker_name, &info[count].hours, &info[count].hourly_pay);
        count++;
    }

    fclose(pointer);
    
    return (count);
}

int display_array(int count)
{
    WorkerRecord info[50];
    int k;
    float gross_pay[50];
    
    printf(" Name\t\tHours\t\tHourly Pay\tGross Pay\n");
    printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
    
    for(k = 0; k < count; k++)
    {
        gross_pay[k] = (info[k].hourly_pay * info[k].hours);
    }
    
    for(k = 0; k < count; k++)
    {
        printf("%s\t\t%d\t\t$%.2f\t\t$%.2f\n", info[k].worker_name, info[k].hours, info[k].hourly_pay, gross_pay[k]);
    }
    
    return 0;
}

Ok, I've done everything that I need to do, but I don't understand anything about pointers. I need to be able to access the data stored in the struct in the fill_array function in my other two functions, but I have no clue how to do this. (I only learned about structs the day before last).

Any help is greatly appreciated,
~Alan

Also, if anyone could just explain to me what pointers are and how to use them, that would be great. I've looked up other tutorials online, but they seem so vague that I can't really understand them as I am more of a hands-on learner rather than someone who can read the basics and then know how to do it. ;S

Pointers are variables that hold memory addresses. That's it. Their power is within how you manipulate them.

In your fill_array() function, you declared the sturcture array as automatic, meaning they eventually vanish in stack memory as soon as the function returns. You can do

WorkerRecord *info = calloc(50, sizeof(WorkerRecord));

which will reserve you basically a 50-element array in the heap which will be pointed to by info pointer. This will not disappear and only ever will if you either use free() on it or upon program termination.

To access a structure pointer, you need to use the '->' operator instead of the '.' operator. They are the same in effect. You don't need to change any of your code.

info[0]->member
info[1]->member

If you want to access this array/data, instead of returning the count variable, return info pointer instead(if you are going to do it as I did. Alternatively, you can declare it as static). Then you should rephrase your function return type to WorkerRecord *fill_array();

Considering that I have never heard of calloc before, I am thinking that maybe static is the way to go? If I use static, will I still be able to return count? That would make it easier, I think.

Oh, so you want to return both count and the structure array? It seems you also have the array in your main(). In that case, you can just declare a pointer to WorkerRecord in your function parameters instead of void.

int fill_array(WorkerRecord *info);

like so. When you call fill_array, pass to it info array and then modify it within the function. You need not declare another instance of info array within the function. When you pass info array to the function, you are passing the address of the first element of the array. This makes it possible to directly(or indirectly) modify info array(or pointer, in this case now). The change to pointer structure operators is still needed.

I didn't notice your main() before. lol sorry I was used to not using prototypes.

Ahh, so if I do as you listed above, it will be directly changing my info array in my main function, even though I'm adding information to it in the fill_array function? (Sorry to sound completely stupid, but for some reason, pointers are hard for me to understand.)

EDIT: Maybe a pseudo code (I think that's what it's called lol) example may help me the best atm. Like, on how pointers work between functions.

Passing the info to the fill_array() creates a 'pass by reference', whatever you do to this reference is pretty much permament(in a way), contrary to a pass by value where a copy of the original data is just passed.

Assuming your above code works, removing the info definition in fill_array() and passing the info array from main to it, with proper operator changeups, will do the trick. Changes done to info array within fill_array() reflects to the info array within main as you are maniplating the actual memory.

int another = 5;
int *pointer1 = &another;
int automatic;
void foo(int *point_param){
 /* passing me pointer1 variable which holds the address of variable another gives me the ability to directly modify variable another because of your reference via piointer1 */

*point_param = 1337; /* Hey, I changed variable another's value. It's because I had its memory address.*/
}

void teehee(int auto_var){
 /* Passing me variable automatic only gives variable auto_var a 'copy' of the value of variable automatic. In effect, it's simply auto_var = automatic; */
/* Any modification to auto_var does not reflect to variable automatic as you are actually manipulating the memory reserved FOR auto_var, not variable automatic */
/* On the flipside, our previous function modifies the address reserved FOR variable another which pointer1 holds which is given to point_param function paremeter */

/* given our knowledge that an array name evaluates to a memory address/pointer, we can therefore conclude that when we pass this array around, we pass around its address and therefore make affective modifications */
}

Memory addresses are really just like any other 'typical' values, like an integer 5, or a float 3.1415, or a char 'a'. Except, well, they are addresses to memory which gives you the ability to reference this location and change anything that is in it.

So, what's the difference between passing the pointer to fill_array than passing the info variable itself?

int fill_array(WorkerRecord *info);
count = fill_array(&info);
fscanf(pointer, "%s%d%f", *info[count]->worker_name, *info[count]->hours, *info[count]->hourly_pay);

Am I doing that correctly so far? (Those are the only lines I have changed so far.)

The array name itself evaluates to a pointer. The array name is not like a variable which sort of acts like a container. The array name in itself points to the first element of the array(or the whole reserved block, depending on how you think about it).

count = fill_array(info);

is the correct one.

Also, you don't have to use the dereference operator when you're using the structure pointer operator. At least, not in your context.

info[index]->member

in itself references the member. If you apply the dereference operator, that would mean that the structure member you are calling to has to be a pointer type and you are referring to the content of its content(what the memory location it points to contains).

Thanks, all of that makes sense!

Also, sorry for wasting your time, even though I learnt a lot from the making of this thread. My prof sent out an email, just moments ago, saying that she meant to tell us that the array can be globally scoped, so all of this was unnecessary. :(

People will tell you not to globally scope anyways. You'd have to unlearn globalizing and relearn localizing. But I suppose that's good for now.

I figured as much, but I am just learning the basics as this class was meant to be an introduction to basic programming and prepare me for next semester, which is C++ and C#. I am sure that I will be taught how to effectively use pointers in one of those classes, otherwise I will be utterly useless as a programmer. :P

Again, thanks for all of your help though!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.