• wordnum_commented.c

  • §

    Jonas Altrock ew20b126@technikum-wien.at

    To overview.

    The whole source file wordnum_commented.c.

    /* compile with `clang -std=c99 -Wall -o wordnum wordnum_commented.c` */
  • §

    Include the usual header files.

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
  • §

    Store all state for the exam in one big struct. Two tables with allocated capacity and actual item count. Putting it in a struct is not necessary, this could be global variables.

    typedef struct exam {
        char **wordTable;
        int wordTableSize;
        int words;
        int **numTable;
        int numTableSize;
        int nums;
    } exam_t;
  • §

    Exam gave the function names for how to split up the solution. Each function takes the whole exam_t structure because it might need several parts.

    void allocAndReadInput(exam_t *exam);
    void sortNum(exam_t *exam);
    void output(exam_t *exam);
    void freeMemory(exam_t *exam);
  • §

    main()

  • §
    int main() {
  • §

    Static struct initialization of all state.

        exam_t exam = {
                .wordTable = calloc(16, sizeof(char *)),
                .wordTableSize = 16,
                .words = 0,
                .numTable = calloc(16, sizeof(int *)),
                .numTableSize = 16,
                .nums = 0
        };
  • §

    Read in input, sort numbers, output, and free dynamic memory.

        allocAndReadInput(&exam);
        sortNum(&exam);
        output(&exam);
        freeMemory(&exam);
        return 0;
    }
  • §

    allocAndReadInput()

  • §

    read input, distinguish between word and number, check for duplicated words, allocate memory + reallocate if necessary, store in wordTable / numTable

    void allocAndReadInput(exam_t *exam) {
        char buffer[64];
    
        do {
  • §

    read at most 63 characters

            scanf("%63s", (char *) &buffer);
  • §

    end program if it is “.”

            if (strcmp(".", buffer) == 0) {
                return;
            }
  • §

    try to convert to number

            char *rest;
            int num = strtol(buffer, &rest, 10);
  • §

    no rest, this is a valid number

            if (*rest == '\0') {
  • §

    make space if table capacity is too small

                if (exam->nums == exam->numTableSize) {
                    exam->numTableSize *= 2;
                    exam->numTable = realloc(exam->numTable,
                                            exam->numTableSize * sizeof(int *));
                }
    
                exam->numTable[exam->nums] = malloc(sizeof(int));
                *exam->numTable[exam->nums] = num;
                exam->nums += 1;
            }
  • §

    some rest, this is not an number but a word.

            else {
                bool found = false;
  • §

    search for word in table

                for (int i = 0; i < exam->words; i++) {
                    if (strcmp(buffer, exam->wordTable[i]) == 0) {
                        found = true;
                        break;
                    }
                }
  • §

    skip duplicate word

                if (found) {
                    continue;
                }
  • §

    make space if table capacity is too small

                if (exam->words == exam->wordTableSize) {
                    exam->wordTableSize *= 2;
                    exam->wordTable = realloc(exam->wordTable,
                                             exam->wordTableSize * sizeof(char *));
                }
  • §

    insert duplicate of word in table

                exam->wordTable[exam->words] = strdup(buffer);
                exam->words += 1;
            }
        } while (1);
    }
  • §

    sortNum()

  • §

    sort numTable ascending, with bubble sort.

    See also bubble sort in sort.c.

    void sortNum(exam_t *exam) {
        for (int i = 0 ; i < exam->nums - 1; i++) {
            for (int j = 0 ; j < exam->nums - i - 1; j++) {
  • §

    swap down if larger

                if (*exam->numTable[j] > *exam->numTable[j + 1]) {
                    int *tmp = exam->numTable[j];
                    exam->numTable[j] = exam->numTable[j + 1];
                    exam->numTable[j + 1] = tmp;
                }
            }
        }
    }
  • §

    output()

  • §
    void output(exam_t *exam) {
  • §

    print both wordTable and numTable

        for (int i = 0; i < exam->words; i++) {
            printf("%s ", exam->wordTable[i]);
        }
    
        printf("\n");
    
        for (int i = 0; i < exam->nums; i++) {
            printf("%i ", *exam->numTable[i]);
        }
    }
  • §

    freeMemory()

  • §
    void freeMemory(exam_t *exam) {
        for (int i = 0; i < exam->words; i++) {
            free(exam->wordTable[i]);
            exam->wordTable[i] = NULL;
        }
    
        for (int i = 0; i < exam->nums; i++) {
            free(exam->numTable[i]);
            exam->numTable[i] = NULL;
        }
    
        free(exam->wordTable);
        exam->wordTable = NULL;
        exam->words = 0;
        free(exam->numTable);
        exam->nums = 0;
        exam->numTable = NULL;
    }