1

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...

George S
  • 51
  • 7
  • Does it display anything when it *"ends unexpectedly"*? What input do you give the program to make it *"ends unexpectedly"*? – Gerhard Apr 20 '22 at 10:48
  • https://prnt.sc/GIEtpucSoMxl @Gerhard – George S Apr 20 '22 at 10:51
  • What was your input, i.e. which options did you chose before you got the error? – M Oehm Apr 20 '22 at 10:56
  • 1
    Add your error as text your question. How did you get to this error? – Gerhard Apr 20 '22 at 10:58
  • You pass pointers to file pointers to the functions, but you don't do anything with these pointers in `main`. I think the way your program is desigedn, all of these should be local variables to each function and there shouldn't be any `FILE *`s in `main`. – M Oehm Apr 20 '22 at 11:00
  • Please take some time to read the [the Stack Overflow question checklist](http://meta.stackexchange.com/q/156810/204922). You might also want to learn about [Minimal, Complete, and Verifiable Examples](http://stackoverflow.com/help/mcve). As your question stands now there is insufficient information to be able to help you. – Gerhard Apr 20 '22 at 11:01
  • `scanf("\n%d", &choice);` ==> `scanf("%d", &choice);` – mch Apr 20 '22 at 11:21
  • 2
    The compiler gives you some hints: https://godbolt.org/z/jdKd31drr – mch Apr 20 '22 at 11:24
  • @M Oehm There was no input..I just clicked compilw and run – George S Apr 20 '22 at 11:54
  • Also @M Oehm you suggest removing any *FILE in *main* ? – George S Apr 20 '22 at 12:10
  • I linked two FAQ duplicates: one for the stack overflow bug, another for the use of uninitialized pointers bug. – Lundin Apr 20 '22 at 12:34

2 Answers2

3

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);
}
Oka
  • 23,367
  • 6
  • 42
  • 53
  • Well I made *matrix* global but now when *choice* is either 3 or 4 the program seems to exit the while loop.. – George S Apr 20 '22 at 12:27
  • @GeorgeS Yes, your program is crashing due to mishandling of files. You need to be more consistent with where you open and close files. Establish a clear pattern of open file / do some work / close the file. Consider passing pointers to open files to the functions that do the work, and close the files after these functions. Alternatively, note that you are only working with two files here, and open them each once: `"w+"` or `"a+"` opens a file for reading and writing. Use `fseek` (and/or `rewind`) to navigate these open files, depending on if you want to append data or read the contents. – Oka Apr 20 '22 at 12:47
  • I think that the problem is related to mis-use of uninitialized pointers. Look at my answer below. – Fra93 Apr 20 '22 at 12:54
3

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.

Fra93
  • 1,992
  • 1
  • 9
  • 18
  • So you suggest passing **fp** and **p_fp** as arguements of the function? – George S Apr 20 '22 at 12:24
  • 1
    Do you understand the difference? For what I am understanding you don't need them to be "double" pointers, just single pointers. So declare them to be `FILE* fp` and `FILE* p_fp`, then change your functions accordingly. – Fra93 Apr 20 '22 at 12:26