I'm using the following code below and I'm receiving a Thread 1: EXC_BAD_ACCESS (code=1, address=0x68)
error. What are some ways I can execute this better? I'm simply loading a txt file that has roughly 500000 numbers and they are each on a new line. I've looked at a few resources how to do this, but I end up with these oddities. I'm hoping a c guru can help me out.
#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define COUNT_ARRAY_LENGTH 10
#define MAX_NUMBER 500001
int *load_file(){
FILE *file;
file = fopen("somefile.txt", "r");
int a[MAX_NUMBER];
int i=0;
int num;
while(fscanf(file, "%d", &num) > 0) {
a[i] = num;
i++;
}
fclose(file);
return a;
}
int main(int argc, const char *argv[])
{
int *a;
a = load_file();
for(int i = 0; i < MAX_NUMBER; i++){
printf("%d\n", a[i]);
}
return 0;
}
Converting comments into an answer.
My immediate guess would be that you're failing to open the file — an error you don't check for and must always check for. Files go AWOL, or the program is run from the wrong directory, or they have the wrong permissions.
if (file == NULL)
{
fprintf(stderr, "Failed to open file '%' for reading\n", "somefile.txt");
exit(EXIT_FAILURE);
}
The repeated literal for the file name shows why you should never pass a string literal as the file name to fopen()
; you should have a variable so that you can report the file name in the error message too, without repeating yourself.
const char *filename = "somefile.txt";
if ((file = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open file '%' for reading\n", filename); n.
exit(EXIT_FAILURE);
}
In fact, you should probably pass the name of the file to be loaded to the load_file()
function so that you can more easily change it (by command line arguments, for example). That is as well as passing the array, and the size of the array. That gives you a more generic function, one more easily adapted to other uses.
You could also #include <errno.h>
and #include <string.h>
and use strerror(errno)
to print the system error message to give more help to the user (but knowing the file name is a huge step in the right direction).
Also, you should have while (i < MAX_NUMBER && fscanf(file, "%d", &num) > 0)
so you don't overflow the array.
Also, you're returning the address of the local array in load_file() — you can't do that safely. Define the array in main()
and pass the pointer as a parameter. Your main()
also assumes that the array was filled. Revise load_file()
to return how many numbers were loaded so you don't access unloaded numbers.
Putting all those changes together might yield:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUMBER 500001
static size_t load_file(const char *filename, size_t arrsiz, int *array)
{
FILE *file;
if ((file = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
exit(EXIT_FAILURE);
}
size_t i = 0;
int num;
while (i < arrsiz && fscanf(file, "%d", &num) > 0)
array[i++] = num;
fclose(file);
return i;
}
int main(void)
{
int a[MAX_NUMBER];
size_t num = load_file("somefile.txt", MAX_NUMBER, a);
for (size_t i = 0; i < num; i++)
printf("%d\n", a[i]);
return 0;
}
That's been compiled but not run.
You could process a command-line argument like this:
int main(int argc, char **argv)
{
if (argc > 2)
{
fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *filename = (argc == 2) ? argv[1] : "somefile.txt";
int a[MAX_NUMBER];
size_t num = load_file(filename, MAX_NUMBER, a);
for (size_t i = 0; i < num; i++)
printf("%d\n", a[i]);
return 0;
}
Or you could allow more than one argument and iterate over them all.
Sometimes, it's better to do the file opening and closing in the main()
and pass the open file stream to the function. You can then read from stdin
if there are no command-line arguments. The options are legion!