Question

The code I am working on reads in a dictionary of 45430 words and then prints to the file all the other words in the dictionary contained within each word. I am just working on getting the file MyDictionary txt file read into the char array word[45430][30] and then printing this to the words-in-words txt file. I run into a seg fault at 44946 word when I do so, but in the same while loop I am also printing to the console and all words print out properly. Why is it I am getting this seg fault for writing to the file? And why is there no seg fault writing to the console?

Code:

#include <stdio.h>  
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
//char ***alloc_array(int,int);

int main(void){
        FILE *fr; //declare file read file pointer
        FILE *fp; //declare file printed file pointer

        //char array to read in up to 30 chars
        char line[31];

        long numwords=45430; //number of words in dictionary
        int maxlength=31; // the longest string in dictionary (30 chars)
        long i; //counts up to 45430

        //allocate space for 45430 words at a max length of 30 chars (1 extra char for "\0")       
        char ***word = calloc(numwords, sizeof(char **));
        for(i = 0; i != numwords; i++) {
            word[i] = calloc(maxlength, sizeof(char *));
        }

        //Open MyDictionary.txt and determine if there is an error or not        
        fr = fopen ("MyDictionary.txt", "r");  // open the file for reading    

        if(fr==NULL){
               printf("\nError! opening input file");
               exit(1); //Program exits if file pointer returns NULL. 
        }

        //Open  words-within-words.txt and determine if there is an error or not        
        fp = fopen ("words-within-words.txt", "w");  // open the file for reading    
        if(fp==NULL){
               printf("\nError! opening output file");
               exit(1); //Program exits if file pointer returns NULL. 
        }

        int j=0; //counts to 30 for max length
        i=0;
        while(fgets(line, 40, fr) != NULL){ //get a line, up to 40 chars from fr and put first .  done if NULL 

            for(j=0;j<30;){
                word[i][j]=&line[j];
                j++;
            }
            j=0;
            printf("\n%s",word[i][j]); //print out each word of dictionary to console on its own line
            /*
            if((i>4 && i<8)||(i>45428)){
                fprintf(fp,"\nanalyze:word[i][0]=%s\tword[i][2]=%s\ti=%li",word[i][0],word[i][2],i+1);
            }
            */
            fprintf(fp,"%s",word[i][j]); //print out each word of dictionary to words-in-words on its own line
            i++;
        }  
        fclose(fr);  //close the files prior to exiting
        fclose(fp);
        return 0;
} //main

No correct solution

OTHER TIPS

char ***word = calloc(numwords, sizeof(char **));
for(i = 0; i != numwords; i++) {
    word[i] = calloc(maxlength, sizeof(char *));
}

You've got one too many levels of indirection. You are storing a list of words. A word is a char *, so a list of words would be char **.

char **word = calloc(numwords, sizeof(char *));
for (i = 0; i != numwords; i++) {
    word[i] = calloc(maxlength, sizeof(char));
}

This will then necessitate changes to the rest of your code. You can get rid of j entirely. This:

for(j=0;j<30;){
    word[i][j]=&line[j];
    j++;
}

Becomes:

strcpy(word[i], line);

And this:

j=0;
printf("\n%s",word[i][j]);
fprintf(fp,"%s",word[i][j]);
i++;

Becomes:

printf("%s\n", word[i]);
fprintf(fp, "%s\n", word[i]);

'word' should be an array of pointers, so the right type is char **, not char ***. Each entry in the array is a pointer to a buffer of characters:

char **word = (char **)calloc(numwords, sizeof(char *));
if (!word)
    // exit with error

for (i = 0; i != numwords; i++) {
     word[i] = (char *)calloc(maxlength, sizeof(char)); // just allocate 31 bytes
     if (!word[i])
         // exit with error
}

Then a read from file can be done like this:

for (i = 0; fgets(line, 40, fr); i++) {
    strncpy(word[i], line, maxlength);
    printf("word %d: %s\n", i, word[i]);
}

To have one chunk of memory do allocate like this:

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

int main(void)
{
  int result = EXIT_SUCCESS;

  size_t n = 45430;
  size_t l = 30;

  char  (* words)[n][l + 1] = calloc(n, l + 1);
  if (NULL == words)
  {
     result = EXIT_FAILURE;
     perror("calloc() failed");
     goto lblExit;
  }

  for (size_t i = 0; i < n; ++i)
  {
    strncpy((*words)[i], "test", l);
  }

  for (size_t i = 0; i < n; ++i)
  {
    printf("%zu: '%s'\n", i, (*words)[i]);
  }

  free(words);

lblExit:

  return result;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top