0

I am trying to read a large list of English words from a text file to array of strings. The number of words is 2016415, and maximum length of a word is 69 characters.

If I define array like "char data[2016415][70]; " then I get stack overflow when I run the program.

So I am trying to use calloc() instead, however I can't understand how should I type-cast it so that it becomes equivalent to "char data[2016415][70];".

The following program returns "passing arg 1 of `fgets' makes pointer from integer without a cast" warning during compiling. And when I execute it, it gets "Exception: STATUS_ACCESS_VIOLATION" problem.

Can you help me?

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

int main(void){
char *data;  //data[2016415][70];

int i;
FILE *fsol;

fsol = fopen("C:\\Downloads\\abc\\sol2.txt","r");

data = (char*) calloc(2016415,70);

for(i=0;i<2016415;i++){
    fgets(data[i] , 70 , fsol);
}

fclose(fsol);

return 0;

}

Sunny88
  • 2,860
  • 3
  • 24
  • 25
  • 2
    Have you tried using fgets(&data[i*70] , 70 , fsol); instead? – Il-Bhima Jun 29 '10 at 23:09
  • Here's a related question from earlier today: http://stackoverflow.com/questions/3144132/malloc-in-c-but-use-multi-dimensional-array-syntax – Cogwheel Jun 29 '10 at 23:13
  • fgets(&data[i*70] , 70 , fsol); works great. Thanks! – Sunny88 Jun 29 '10 at 23:40
  • Out of curiosity, how this even compiled? There is no implicit conversion from `char` to `char*`, which would be required for the call to `fgets` to be valid. WTH is it a warning and not an error? – Pavel Minaev Jun 30 '10 at 00:05

5 Answers5

1

Okay, sorry about the previous suggestion. I forgot how horrible arrays can be. This one is tested with a small data set of 10 words, but it should scale to your word count. Note that fgets() seems to pull in the line endings as part of the preceding word.

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

#define MAX_WORD_CNT 2016415
#define MAX_WORD_LEN 70

int main(void)
{
    char *data;  //data[2016415][70];

    int i;
    FILE *fsol;

    fsol = fopen("C:\\Downloads\\abc\\sol2.txt","r");

    data = (char*) calloc(MAX_WORD_CNT, MAX_WORD_LEN);

    // check for valid allocation
    if (data == NULL)
    {
        return 1;
    }

    for(i=0; i<MAX_WORD_CNT; i++)
    {
        fgets(&data[i * MAX_WORD_LEN], MAX_WORD_LEN, fsol);
    }

    fclose(fsol);

    return 0;
}
Amardeep AC9MF
  • 18,464
  • 5
  • 40
  • 50
1

calloc just allocates a big swath of memory - not an array of pointers to other arrays.

fgets expects a pointer to the memory location it should dump it's stuff at.

So instead of giving it the contents of data[i], you want to give it the address of data[i] so it can put its stuff there.

fgets(&data[i], 70, fsol);

You'll probably also need to adjust your loop so that it goes up by 70-odd characters at a time rather than one.

Anon.
  • 58,739
  • 8
  • 81
  • 86
0

Here's how I would allocate the array

char **data = malloc(MAX_WORD_CNT * sizeof(char *));
for(int i = 0; i < MAX_WORD_CNT; i++)
    data[i] = malloc(MAX_WORD_LEN);

you might want to add some error checking for malloc though.

Bwmat
  • 4,314
  • 3
  • 27
  • 42
0

data is a pointer to char (also addressable as an array of char), so data[i] is a single char. fgets expects a pointer to char but you're passing it a single char; that's why you're getting the warning, you're trying to use a char (integer) as a pointer.

When you run the program, it then takes that single char argument and interprets it as a pointer to char, hence the access violation because the value of that char is not a valid address.

So, in your loop you should pass fgets a pointer into data and increment that by 70 with each iteration. You can use the "pointer to an array element" form &data[i] and increment i, or the simple pointer form, with another pointer variable initially set to data, and itself incremented.

Paul Richter
  • 6,154
  • 2
  • 20
  • 22
0

The answer is simple: you DON'T cast it. Casting the results of malloc/calloc/etc. has no purpose but can have the side-effect of hiding a major bug if you forgot to include stdlib.h. The return type of these allocation functions, which is void *, will automatically be cast to whatever you need.

If you really want to know the type, it's (char (*)[70]). But please don't actually obfuscate your program by writing that. (Unless you're actually writing C++, in which case you should have tagged your question C++ and not C, or better yet used new.)

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711