// Arup Guha
// 5/29/2020
// Code for Summer 2020 COP 3502 Section 16 Quiz

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "leak_detector_c.h"

// Dummy struct to show viability of question #2.
typedef struct sodacan {
    int oz;
} sodacan;

// Struct for Part B.
typedef struct charnode {
    char c;
    struct charnode* next;
} charnode;

int stringlen(charnode* front);
charnode* makeLinkedList(char* word);
void convertToUpper(charnode* front);
void freeList(charnode* ptr);
void printString(charnode* ptr);

int main(void) {

    // So we can get the leak detector report.
    atexit(report_mem_leak);

    // Part A Question #1
    int n;
    scanf("%d", &n);
    double* array = calloc(n, sizeof(double));

    // Test to see array set to 0.
    for (int i=0; i<n; i++)
        printf("%.1lf ", array[i]);
    printf("\n");

    // Free this memory.
    free(array);

    // Part A Question #2 Given mallocs.
    scanf("%d", &n);
    int* sizes = malloc(n*sizeof(int));
    sodacan** cans = malloc(n*sizeof(sodacan*));

    for (int i=0; i<n; i++) {
        scanf("%d", &sizes[i]);
        cans[i] = malloc(sizes[i]*sizeof(sodacan));
    }

    // Part A Question #2 Solution - can be verified using leak detector.

    // First free each 1D array of cans.
    for (int i=0; i<n; i++)
        free(cans[i]);

    // Now, free both original arrays that were allocated.
    free(cans);
    free(sizes);

    /*** Part B tests starts here. ***/
    charnode* teststr = makeLinkedList("hello");
    printf("Length of string is %d\n", stringlen(teststr));
    printString(teststr);
    convertToUpper(teststr);
    printString(teststr);

    freeList(teststr);
    return 0;
}

// Solution to Part B Question #1
int stringlen(charnode* front) {

    // Store answer here.
    int res = 0;

    // Iterate through list.
    while (front != NULL) {

        // Just add 1 each time we hop.
        res++;

        // Hop to next node.
        front = front->next;
    }

    // This is our result.
    return res;
}

// Support code to test Part B questions
charnode* makeLinkedList(char* word) {

    int i = 0;

    // This is our list initially.
    charnode* front = NULL;
    charnode* back = NULL;

    // Go till null char.
    while (word[i] != '\0') {

        // Make the new node.
        charnode* tmp = malloc(sizeof(charnode));
        tmp->c = word[i];
        tmp->next = NULL;

        // All we have to do for first item.
        if (i == 0) {
            front = tmp;
            back = tmp;
        }

        // Patch old back to new back and update back.
        else {
            back->next = tmp;
            back = tmp;
        }

        // Go to next character in the word.
        i++;
    }

    // This is our pointer.
    return front;
}

// Solution to Part B Question #2
void convertToUpper(charnode* front) {

    // Go through whole list.
    while (front != NULL) {

        // Convert this character.
        front->c = toupper(front->c);

        // Go to next character.
        front = front->next;
    }
}

// Frees all the memory for the linked list pointed to by ptr.
void freeList(charnode* ptr) {
    if (ptr != NULL) {
        freeList(ptr->next);
        free(ptr);
    }
}

void printString(charnode* ptr) {
    while (ptr != NULL) {
        printf("%c", ptr->c);
        ptr = ptr->next;
    }
    printf("\n");
}
