Following on from the discussion in the comments, an example is probably the easiest way to sew up the loose ends. While declaring the memory as a block to hold your 5 computers is fine, you will find in more complex situations, that declaring x
number of pointers-to-pointers and then allocating space for each computer and assigning that value to the pointer makes more sense. (it is what allows the computers[i]
reference later on).
However, for this example, simply declaring a block big enough to hold 5 is fine. Try the following, and if you have further questions, just let me know:
#include <stdio.h>
#include <stdlib.h>
#define MAXSN 24
#define NCOMP 5
typedef struct {
char serialNumber[MAXSN];
int price;
int GBofRAM;
int GBofHardDrive;
} Computer;
Computer *readComputers (char *filename);
int main (int argc, char **argv) {
Computer *computers = NULL;
int i = 0;
if (argc < 2) {
fprintf (stderr, "error: insufficient input. usage %s filename\n",
argv[0]);
return 1;
}
computers = readComputers ( argv[1] );
if (!computers) {
fprintf (stderr, "error: no computers read from file\n");
return 1;
}
printf ("\n No. serialNumber price GBofRAM GBofHardDrive\n");
printf (" --- ------------ ------ ------- -------------\n");
while ((computers + i)-> serialNumber && i < NCOMP) {
printf ( " (%d) %12s %6d %7d %13d\n", i,
(computers + i)->serialNumber,
(computers + i)-> price,
(computers + i)-> GBofRAM,
(computers + i)-> GBofHardDrive);
i++;
}
free (computers);
return 0;
}
Computer *readComputers (char* filename)
{
FILE* fp = fopen( filename, "r" );
if( !fp ) {
printf( "Error: Invalid file!" );
exit( 0 );
}
/* use calloc to allocate and initialize to 0 since you
do not know how many you will read from file */
Computer *compPtr = calloc ( 5, sizeof *compPtr );
int i = 0;
while (fscanf( fp, "%s %d %d %d",
(compPtr + i)-> serialNumber,
&(compPtr + i)-> price,
&(compPtr + i)-> GBofRAM,
&(compPtr + i)-> GBofHardDrive ) == 4 && i < 5) { i++; }
fclose( fp );
return compPtr;
}
Test Input
$ cat dat/comp.dat
14490 699 24 1000
29056 549 12 1000
19668 659 16 1000
13167 379 4 500
26531 499 8 750
Compile
gcc -Wall -Wextra -o bin/struct_rdcomputers struct_rdcomputers.c
The optimization level -Ofast
or -O(0-3)
[0 default] are optional optimization levels you can add that can greatly reduce runtime. However, for initial building and debugging you will want to minimize the use of optimization to insure the compiler doesn't optimize away information you may need to debug your code.
Output
$ ./bin/struct_rdcomputers dat/comp.dat
No. serialNumber price GBofRAM GBofHardDrive
--- ------------ ------ ------- -------------
(0) 14490 699 24 1000
(1) 29056 549 12 1000
(2) 19668 659 16 1000
(3) 13167 379 4 500
(4) 26531 499 8 750
Memory Check
When you allocate memory dynamically, you are responsible for (1) preserving a pointer to the begining of the block of memory allocated (so it can be freed); and (2) freeing the memory when it is no longer needed. You also need to insure you are using it correctly and there are no errors in the way you are accessing the memory. The use of valgrind
(or similar tool) is simple to use, and essential, to validate you are freeing all memory you have allocated and are not using it in a way that will come back and bite you later. Simply type valgrind progname
and then read the results:
$ valgrind ./bin/struct_rdcomputers dat/comp.dat
==8529== Memcheck, a memory error detector
==8529== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==8529== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==8529== Command: ./bin/struct_rdcomputers dat/comp.dat
==8529==
No. serialNumber price GBofRAM GBofHardDrive
--- ------------ ------ ------- -------------
(0) 14490 699 24 1000
(1) 29056 549 12 1000
(2) 19668 659 16 1000
(3) 13167 379 4 500
(4) 26531 499 8 750
==8529==
==8529== HEAP SUMMARY:
==8529== in use at exit: 0 bytes in 0 blocks
==8529== total heap usage: 2 allocs, 2 frees, 748 bytes allocated
==8529==
==8529== All heap blocks were freed -- no leaks are possible
==8529==
==8529== For counts of detected and suppressed errors, rerun with: -v
==8529== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)