Search code examples
cstringc89

Why is NULL printed here? - C-90


The code:

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

#define N 500
#define M 100

/*Version 1*/
void replace_word(char *word);
void add_new_word_dictionary(void);
void do_nothing(void);
void return_basic(void);
void check_word(void);
void compute_words(void);
void compute_characters(void);
void compute_ch_sp(void);
void compute_num_dif_words(void);
void create_istogram(void);
void save_file(void);
int get_choice(void);
void return_word(void);
void insert_text(int numwords, char matrix[N][M], int posit);

int main() {
    int j;
    int choice = 0;
    char matrix[N][M];
    char word[40] = { "t" };
    while (1) {
        choice = get_choice();
        if (choice == 0) {
            insert_text(M, matrix, 1);
        }
        if (choice == 1) {
            add_new_word_dictionary();
        }
        if (choice == 2) {
            do_nothing();
        }
        if (choice == 3) {
            save_file();
        }
        if (choice == 4) {
            compute_words();
        }
        if (choice == 5) {
            break;
        }
        for (j = 0; j < M; j++) {
            printf("%s", matrix[N][M]);
        }
    }

    printf("\n End of Program \n");
    return 0;
}

void replace_word(char *word) {
    return;
}

void add_new_word_dictionary(void) {
    char word[50] = { "s" };
    printf("\nPlease enter the word\n");
    scanf("\n%s", word);
    printf("Your word is %s", word);
    return;
}

void do_nothing(void) {
    printf("\n do_nothing \n");
    return;
}

void return_basic(void) {
    printf("\n return basic \n");
    return;
}

void check_word(void) {
    printf("\n check word \n");
    return;
}

void compute_words(void) {
    printf("\n compute_words \n");
    return;
}

void compute_characters(void) {
    printf("\n compute characters \n");
}

void compute_ch_sp(void) {
    printf("\n compute_ch_sp \n");
    return;
}

void compute_num_dif_words(void) {
    printf("\n compute_num_same_words \n");
    return;
}

void create_istogram(void) {
    printf("\n create istogram \n");
    return;
}

void save_file(void) {
    printf("\n save_file \n");
    return;
}

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;
}

void insert_text(int numwords, char matrix[N][M], int  posit) {
    int i;
    int j;
    char word2[40] = { "" };

    while (strcmp(word2, "*T*E*L*O*S*")) {
        printf("\n Add the word \n");
        scanf("\n%s", word2);

        if (posit + 1 > numwords) {
            printf("\n Out of Bounds \n ");
        }

        for (i = numwords - 2; i >= posit; i--) {
            strcpy(matrix[i + 1], matrix[i]);
            if (!i)
                break;
        }
        strcpy(matrix[posit], word2);
        j++;
    }
    for (i = 0; i < j; i++) {
        printf("%s", matrix[i]);
        printf("\n j is %d\n", j);
    }
    return;
}

The problem: I have a function called insert_text. This function adds a string in the 1st position of an array (at least that is what I think it does) and it is called if choice is 0 and executes itself until the string *ΤELOS* is given. When in insert_text I print matrix I get a bunch of *(null)*s... I can count how many words matrix has (by declaring a variable j and incrementing by 1 inside the while loop, but that does not seem to work either. How can I fix this?


Solution

  • The printing code is incorrect: matrix is an array of N arrays of M characters, where you store null terminated C strings. As coded, you pass a single character just beyond the end of the array to printf for %s, which expects a string. The loop should be:

        for (j = 0; j < N; j++) {
            printf("%s ", matrix[j]);
        }
    

    Note that char matrix[N][M]; is uninitialized, so its contents will seem random. Initialize matrix as char matrix[N][M] = { "" };

    Also note that in add_new_word_dictionary(), the scanf() conversion should be scanf("%49s", word); to prevent a potential buffer overflow if the user enters a very long word.

    Same in insert_text, the code should be scanf("%39s", word2) ans you should test the return value to check for input errors.

    Finally, arrays are indexed from 0 in C, so insert_text should be given a position of 0 and the number of words should be N, not M.

    Both the test and the insertion loop have problems too.

    Here is a modified version:

    // call from main as insert_text(N, matrix, 0);
    //
    void insert_text(int numwords, char matrix[N][M], int posit) {
        char word2[40];
        int i, j = 0;
    
        for (;;) {
            printf("\n Add the word \n");
            if (scanf("%39s", word2) != 1) {
                break;  // end of file or input error
            }
            if (!strcmp(word2, "TELOS")) {
                break;  // magic word
            }
            if (posit >= numwords) {
                printf("\n Out of Bounds \n");
                break;
            }
            for (i = numwords - 2; i >= posit; i--) {
                strcpy(matrix[i + 1], matrix[i]);
            }
            strcpy(matrix[posit], word2);
            j++;
        }
        for (i = 0; i < j; i++) {
            printf("%s ", matrix[i]);
        }
        printf("\n j is %d\n", j);
    }
    

    Here is a modified version of the whole program:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define N 500
    #define M 100
    
    /*Version 1*/
    void replace_word(char *word);
    void add_new_word_dictionary(void);
    void do_nothing(void);
    void return_basic(void);
    void check_word(void);
    void compute_words(void);
    void compute_characters(void);
    void compute_ch_sp(void);
    void compute_num_dif_words(void);
    void create_istogram(void);
    void save_file(void);
    int get_choice(void);
    void return_word(void);
    void insert_text(int numwords, char matrix[N][M], int  posit);
    
    int main() {
        int j, done = 0;
        char matrix[N][M] = { "" };
    
        while (!done) {
            switch (get_choice()) {
            case 0:
                insert_text(N, matrix, 0);
                break;
            case 1:
                add_new_word_dictionary();
                break;
            case 2:
                do_nothing();
                break;
            case 3:
                save_file();
                break;
            case 4:
                compute_words();
                break;
            default:
                done = 1;
                break;
            }
            for (j = 0; j < N; j++) {
                if (matrix[j][0])
                    printf("%s ", matrix[j]);
            }
            printf("\n");
        }
        printf("\n End of Program \n");
        return 0;
    }
    
    void add_new_word_dictionary(void) {
        char word[50];
        printf("\nPlease enter the word\n");
        if (scanf("%49s", word) == 1)
            printf("Your word is %s\n", word);
    }
    
    void replace_word(char *word)   { printf("\n replace word \n"); }
    void do_nothing(void)           { printf("\n do_nothing \n"); }
    void return_basic(void)         { printf("\n return basic \n"); }
    void check_word(void)           { printf("\n check word \n"); }
    void compute_words(void)        { printf("\n compute_words \n"); }
    void compute_characters(void)   { printf("\n compute characters \n"); }
    void compute_ch_sp(void)        { printf("\n compute_ch_sp \n"); }
    void compute_num_dif_words(void) { printf("\n compute_num_same_words \n"); }
    void create_istogram(void)      { printf("\n create istogram \n"); }
    void save_file(void)            { printf("\n save_file \n"); }
    
    int get_choice(void) {
        int choice = -1;
        printf("\nSelect a choice from  the below \n");
        printf("Select 0 to add text \n");
        printf("Select 1 to add new words in the dictionary \n");
        printf("Select 2 to enter  enter correction mode \n");
        printf("Select 3 to save the text \n");
        printf("Select 4 to see the statistics about your text \n");
        printf("Select 5 to exit the program\n");
        scanf("%d", &choice);
        return choice;
    }
    
    // call from main as insert_text(N, matrix, 0);
    //
    void insert_text(int numwords, char matrix[N][M], int posit) {
        char word2[40];
        int i;
    
        for (;;) {
            printf("\n Add the word \n");
            if (scanf("%39s", word2) != 1) {
                break;  // end of file or input error
            }
            if (!strcmp(word2, "TELOS")) {
                break;  // magic word
            }
            if (posit >= numwords) {
                printf("\n Out of Bounds \n");
                break;
            }
            for (i = numwords - 2; i >= posit; i--) {
                strcpy(matrix[i + 1], matrix[i]);
            }
            strcpy(matrix[posit], word2);
            posit++;
        }
        for (i = 0; i < posit; i++) {
            printf("%s ", matrix[i]);
        }
        printf("\n posit is %d\n", posit);
    }