'File manipulating code ends in an unexpected way-C90 [duplicate]

The code :

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

#define MAX 100000
#define N 40


int get_choice(void);
int check_word(char *word);
void insert_text(FILE ** p_fp);
char *add_word(char *word);
void add_word_in_dictionary(FILE ** p_fp);
void save_file(FILE **fp);
int count_characters(FILE **fp);
int count_spaces(FILE **fp);
void txt_to_array(FILE **fp, char x[MAX][N]);
void sort_array_alphabetically(char matrix[MAX][N]);
int count_words_same(char matrix[MAX][N]);
void create_istogram(char matrix[MAX][N]);
void print_symbols(int times,int numch);
void create_file(char matrix[MAX][N]);
int count_words(void);

int main()
{
    FILE *fp;
    FILE *fp2;  /*fp for Alice....txt and fp2 for englishWords.txt */
    int choice = 0;
    char matrix[MAX][N] = {" "};
    while(1)
    {
        choice = get_choice();

        if(choice == 0)
        {
            insert_text(&fp);
        }

        if(choice == 1)
        {
            add_word_in_dictionary(&fp2);
        }

        if(choice == 2)
        {
            printf("\n You have entered correction mode but in this version, nothing happens \n");
        }

        if(choice == 3)
        {
            save_file(&fp);
            printf("\n The file has been saved \n");
        }

         if(choice == 4)
        {
            printf("The number of character in the file : %d ",count_characters(&fp));
            printf("The number of spaces in the file : %d ",count_spaces(&fp));
            txt_to_array(&fp,matrix);
            printf("The number of different words in the file : %d ",count_words()- count_words_same(matrix));
            create_istogram(matrix);
            create_file(matrix);
            printf("\n A file has been created with the statistics of the text \n");
        }

        if(choice == 5)
        {
            break;
        }

    }

    printf("\n The program has ended \n");
    return 0;
}



int get_choice(void) {
    int choice = 0;
    printf("\n Select a choice from  the below \n");
    printf("\n Select 0 to add text \n");
    printf("\n Select 1 to add new words in the dictionary \n");
    printf("\n Select 2 to enter  enter correction mode \n");
    printf("\n Select 3 to save the text \n");
    printf("\n Select 4 to see the statistics about your text \n");
    printf("\n Select 5 to exit the program\n");
    scanf("\n%d", &choice);
    return choice;
}



int check_word(char *word)
{
    FILE *readfile;
    char word1[40];
    readfile = fopen("englishWords.txt","r");

    if(!readfile)
    {
       printf("\n There was an error opening the file \n");
       return -1;
    }

     while(fscanf(readfile,"%s",word1) != EOF)
    {
        if(strcmp(word,word1) == 0)
        return 1;

        else
        {
            return 0;
        }
    }

    fclose(readfile);
    return 0;
}



void insert_text(FILE ** p_fp)
{
     char word[100];
    *p_fp = fopen("AlicesAdventuresInWonderland.txt", "a+");
    fprintf(*p_fp, "%s\n", add_word(word));
    return;
}



char *add_word(char *word)
{
    printf("\n Please enter the word \n");
    scanf(" %100[^\n]", word);
    return word;
}



void add_word_in_dictionary(FILE ** p_fp)
{
    char word[100];
    *p_fp = fopen("englishWords.txt","a+");
    fprintf(*p_fp, "%99s\n",add_word(word));
    return;
}



void save_file(FILE **fp)
{
    fclose(*fp);
    return;
}



int count_characters(FILE **fp)
{
    char ch = ' ';
    int count_ch = 0;
    *fp = fopen("AlicesAdventuresInWonderland.txt", "r");
    if(*fp == NULL)
    {
        printf("\n There was an error opening the file \n");
        return 0;
    }

    while(ch != EOF)
    {
        if(ch != ' '  && ch !=  '\n')
        {
            count_ch++;
        }
        ch=fgetc(*fp);
    }

    fclose(*fp);

    return count_ch;
}



int count_spaces(FILE **fp)
{
    int count_sp = 0;
    char c;
    *fp = fopen("AlicesAdventuresInWonderland.txt","r");
     while ((c = fgetc(*fp)) != EOF)
    {
        if (c == ' ')
            count_sp++;
    }

    return count_sp;
}



 void txt_to_array(FILE **fp,char x[MAX][N])
{
    int i = 0;
    char str[MAX] = {" "};
    *fp = fopen("AlicesAdventuresInWonderland.txt","r");
    while(!feof(*fp))
    {

            while(fgets(str, sizeof str, *fp))
        {
            strcpy(x[i],str); 
            i++;
        }

    }
    sort_array_alphabetically(x);
    return;
 }



void sort_array_alphabetically(char matrix[MAX][N])
 {
    int  i = 0;
    int j= 0;
    char s[40] = {" "};
    for(i=0;i<MAX;i++)
        {
        for(j=i+1;j<MAX;j++)
            {
                if(strcmp(matrix[i],matrix[j])>0)
                {
                strcpy(s,matrix[i]); 
                strcpy(matrix[i],matrix[j]);
                strcpy(matrix[j],s);
                }
            }
        }
         return;
}



int count_words_same(char matrix[MAX][N])
{
    int i;
    int count = 0;
     for(i = 0; i < MAX; i++)
    {
        if(strcmp(matrix[i],matrix[i+1]) == 0)
        {
            count++;
        }
     }

     return count;
}



 int count_words(void)
 {
    int words = 0;
    char ch;
    FILE *fp;
    fp = fopen("AlicesAdventuresINWonderland.txt","r");
    while((ch=fgetc(fp))!=EOF)
    {
        putchar(ch);
        if((ch==' ')||(ch=='\n'))
        {
            words++;
        }
    }
    fclose(fp);
    return words;
}


 void create_istogram(char matrix[MAX][N])
{
   int a =0;
   int b = 0;
   int c = 0;
   int d = 0;
   int e = 0;
   int f = 0;
   int g = 0;
   int h = 0;
   int i = 0;
   int j = 0;
   int k = 0;
   int m = 0;
   for(m = 0 ; m < MAX; m++)
   {
       if((strlen(matrix[m])) == 1)
       {
           a++;
       }

       if((strlen(matrix[m])) == 2)
       {
           b++;
       }

       if((strlen(matrix[m])) == 3)
       {
           c++;
       }

       if((strlen(matrix[m])) == 4)
       {
           d++;
       }

       if((strlen(matrix[m])) == 5)
       {
           e++;
       }

       if((strlen(matrix[m])) == 6)
       {
           f++;
       }

       if((strlen(matrix[m])) == 7)
       {
           g++;
       }

       if((strlen(matrix[m])) == 8)
        {
           h++;
       }

       if((strlen(matrix[m])) == 9)
       {
            i++;
       }

       if((strlen(matrix[m])) == 10)
       {
           j++;
        }

        if((strlen(matrix[m])) == 11)
       {
       k++;
       }

       if((strlen(matrix[m])) > 11)
       {
       k++;
       } 


   }
       print_symbols(a-1,1);
       print_symbols(b,2);
       print_symbols(c,3);
       print_symbols(d,4);
       print_symbols(e,5);
       print_symbols(f,6);
       print_symbols(g,7);
       print_symbols(h,8);
       print_symbols(i,9);
       print_symbols(j,10);
       print_symbols(k,11);

       printf("Total number of strings with more than 11 characters : %d\n",k);

    return;
 }

void print_symbols(int times,int numch)
{
     int i;
     printf(" %d:  ",numch);
     for(i = 0 ; i < times; i ++)
    {
        printf("*");
    }
    printf(" (%d) ",times);
    printf("\n");
    return;
}

void create_file(char matrix[MAX][N])
{
    int total_ch;
    int total_words;
    int total_ch_wo_sp;
    int total_dif_words;
    FILE **fp;
    FILE **p_fp;
    *fp = fopen("AlicesAdventuresInWonderland.txt","r");

    total_ch = count_characters(fp);
    total_words = count_words();
    total_ch_wo_sp =  total_ch - count_spaces(fp);
    total_dif_words = total_words - count_words_same(matrix);
    *p_fp = fopen("data.txt","wt");
    fprintf(*p_fp, "Total number of characters : %d\n",total_ch);
    fprintf(*p_fp,"Total number of words : %d\n",total_words);
    fprintf(*p_fp,"Total number of characters without spaces : %d\n",total_ch_wo_sp);
    fprintf(*p_fp,"Total number of different words : %d\n",total_dif_words);
    return;
}

The problem: When I run the code it ends unexpectedly and I cannot think why this is happenning..The program above is supposed to do the following

  1. Read a .txt file
  2. Have a 'menu' with some basic choices
  3. Compute some statistics concerning the .txt file (number of total spaces,number of total characters,number of total words and the number of total words)
  4. Add text to the .txt file
  5. Save the statistics of the text in a .txt file
  6. Print an istogram which contains how many words have 1 character,how many 2,etc...

I guess there are some fatal errors in my code that is causing the program to end in an unexpected way but I am unable to find them..Also I am not aware of using the debugger and as you can judge by the code I am a newbie...

The error I get more specifically is when I click compile and run even though I do not enter something (a number which indicates which function/functions will execute) the program just ends (in the terminal i get process returned a_number..What's more The program has ended-which indicates the end of the program is not printed...



Solution 1:[1]

I am going to point out an issue with the following function:

void create_file(char matrix[MAX][N])
{

    FILE **fp;
    FILE **p_fp;
    *fp = fopen("AlicesAdventuresInWonderland.txt","r");

    // [...]
    *p_fp = fopen("data.txt","wt");

    return;
}

fp and p_fp are variables that point to a pointer of type FILE. When you first use them doing *fp = fopen() you are dereferencing an uninitialized pointer.

   int* p;
   *p = 10; // Means save 10 at the address that p is holding. 

In the above example p is uninitialised, and it's very likely p has 0 (illegal address) or whatever random number (again, an illegal address).

Why do you need a pointer of pointers? This is useful if you want your pointer to be modified whenever it is passed around by other functions, but that's not the case, not even in count_characters.

Solution 2:[2]

0xC00000FD indicates a stack overflow in Windows. With matrix, you are attempting to allocate 40 * 100000 bytes (4MB) with automatic storage duration (a.k.a., "on the stack").

By default, Windows has a maximum stack size of 1MB.

Use dynamic memory (malloc), or make matrix a global by moving it outside of main:

/* ... */
int count_words(void);

char matrix[MAX][N];

int main(void) {
    /* ... */

Changing this will get you past the first hurdle, but there are other issues with your code, including but not limited to:

In sort_array_alphabetically, the outer loop, for(i=0;i<MAX;i++), should be for(i = 0; i < MAX - 1; i++), so that the inner loop does not access an out-of-bounds index.

In create_file, these double pointers

FILE **fp;
*fp = fopen("AlicesAdventuresInWonderland.txt","r");
/* ... */
FILE **p_fp;
*p_fp = fopen("data.txt","wt");

are uninitialized, containing an indeterminate pointer value. *fp and *p_fp effectively point to random memory.

Afterwards you pass these to functions that attempt to reopen the same files, using the same indeterminate pointer value.

You need a single pointer FILE *fp, and to decide where you are going to open close the files.

Here is a cursory example of passing the address of a pointer to another function to be initialized:

void init_file(FILE **dfp) {
    *dfp = fopen("foo.txt", "r");
}

void example(void) {
    FILE *fp;

    init_file(&fp);

    fclose(fp);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Fra93
Solution 2