/*
 * Author: [Your Name]
 * Course: CS& 131, Fall 2026
 * Assignment: Programming Project #5 - Gerrymandering Part 1
 *
 * Description: Reads election district vote data from a CSV file, computes
 * district-level and state-level vote counts and percentages, determines
 * state winners, and displays national election totals and the overall winner.
 */

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

#define DATA_FILE "districts.csv"
#define MAX_DISTRICTS 55
#define MAX_LINE_LENGTH 800

// Function prototypes
void print_intro(void);
int parse_line(char line[], char state[], int dem_votes[], int rep_votes[]);
void compute_district_percentages(const int dem_votes[], const int rep_votes[],
                                  int dem_pct[], int rep_pct[], int num_districts);
int sum_array(const int arr[], int size);
void print_int_array(const int arr[], int size, int include_percent);
void print_state_results(const char state[], const int dem_votes[],
                         const int rep_votes[], int num_districts);
void print_national_results(long total_dem, long total_rep);

int main(void) {
    FILE *file = fopen(DATA_FILE, "r");
    if (file == NULL) {
        printf("Error: Could not open file %s\n", DATA_FILE);
        return 1;
    }

    print_intro();

    char line[MAX_LINE_LENGTH];
    char state[MAX_LINE_LENGTH];
    int dem_votes[MAX_DISTRICTS];
    int rep_votes[MAX_DISTRICTS];

    long national_dem_votes = 0;
    long national_rep_votes = 0;

    // Read each state line once and process its election results
    while (fgets(line, MAX_LINE_LENGTH, file) != NULL) {
        // Strip trailing newline characters if present
        line[strcspn(line, "\r\n")] = '\0';
        if (strlen(line) == 0) {
            continue;
        }

        int num_districts = parse_line(line, state, dem_votes, rep_votes);
        print_state_results(state, dem_votes, rep_votes, num_districts);

        national_dem_votes += sum_array(dem_votes, num_districts);
        national_rep_votes += sum_array(rep_votes, num_districts);
    }

    fclose(file);

    print_national_results(national_dem_votes, national_rep_votes);

    return 0;
}

/*
 * Prints the introductory welcome banner for the program.
 */
void print_intro(void) {
    printf("Welcome to the election results viewer!\n");
    printf("This program calculates the results of an election\n");
    printf("and displays them by district, state and overall.\n\n");
}

/*
 * Parses a single CSV line into the state name and parallel arrays of
 * Democratic and Republican vote counts. Returns the number of districts.
 */
int parse_line(char line[], char state[], int dem_votes[], int rep_votes[]) {
    char *token = strtok(line, ",");
    if (token != NULL) {
        strcpy(state, token);
    }

    int count = 0;
    // Each district is stored in groups of 3: district number, dem votes, rep votes
    while ((token = strtok(NULL, ",")) != NULL && count < MAX_DISTRICTS) {
        // Skip district number token, read Democratic votes
        token = strtok(NULL, ",");
        if (token != NULL) {
            dem_votes[count] = atoi(token);
        }

        // Read Republican votes
        token = strtok(NULL, ",");
        if (token != NULL) {
            rep_votes[count] = atoi(token);
        }
        count++;
    }

    return count;
}

/*
 * Computes integer vote percentages for each district, safely handling
 * districts with 0 total votes to prevent division by zero.
 */
void compute_district_percentages(const int dem_votes[], const int rep_votes[],
                                  int dem_pct[], int rep_pct[], int num_districts) {
    for (int i = 0; i < num_districts; i++) {
        long total = (long)dem_votes[i] + rep_votes[i];
        if (total == 0) {
            dem_pct[i] = 0;
            rep_pct[i] = 0;
        } else {
            dem_pct[i] = (int)(((long)dem_votes[i] * 100) / total);
            rep_pct[i] = (int)(((long)rep_votes[i] * 100) / total);
        }
    }
}

/*
 * Calculates and returns the sum of all integers in an array.
 */
int sum_array(const int arr[], int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

/*
 * Prints an integer array formatted as [v1, v2, ...] with optional '%' signs.
 */
void print_int_array(const int arr[], int size, int include_percent) {
    printf("[");
    for (int i = 0; i < size; i++) {
        printf("%d", arr[i]);
        if (include_percent) {
            printf("%%");
        }
        if (i < size - 1) {
            printf(", ");
        }
    }
    printf("]");
}

/*
 * Computes and displays all vote counts, percentages, and the winning party
 * for a single state.
 */
void print_state_results(const char state[], const int dem_votes[],
                         const int rep_votes[], int num_districts) {
    int dem_pct[MAX_DISTRICTS];
    int rep_pct[MAX_DISTRICTS];

    compute_district_percentages(dem_votes, rep_votes, dem_pct, rep_pct, num_districts);

    long state_dem_total = sum_array(dem_votes, num_districts);
    long state_rep_total = sum_array(rep_votes, num_districts);
    long state_total = state_dem_total + state_rep_total;

    int state_dem_pct = 0;
    int state_rep_pct = 0;
    if (state_total > 0) {
        state_dem_pct = (int)((state_dem_total * 100) / state_total);
        state_rep_pct = (int)((state_rep_total * 100) / state_total);
    }

    printf("State of %s:\n", state);

    printf("Democratic Vote Counts: ");
    print_int_array(dem_votes, num_districts, 0);
    printf("\n");

    printf("Republican Vote Counts: ");
    print_int_array(rep_votes, num_districts, 0);
    printf("\n");

    printf("Democratic Vote Percentage: ");
    print_int_array(dem_pct, num_districts, 1);
    printf(" = %d%% total\n", state_dem_pct);

    printf("Republican Vote Percentage: ");
    print_int_array(rep_pct, num_districts, 1);
    printf(" = %d%% total\n", state_rep_pct);

    if (state_dem_total > state_rep_total) {
        printf("The Democratic candidate won.\n\n");
    } else {
        printf("The Republican candidate won.\n\n");
    }
}

/*
 * Computes and prints the national vote percentages and overall winning party.
 */
void print_national_results(long total_dem, long total_rep) {
    long total_votes = total_dem + total_rep;
    int nat_dem_pct = 0;
    int nat_rep_pct = 0;

    if (total_votes > 0) {
        nat_dem_pct = (int)((total_dem * 100) / total_votes);
        nat_rep_pct = (int)((total_rep * 100) / total_votes);
    }

    printf("The Democrats won %d%% of the national votes.\n", nat_dem_pct);
    printf("The Republicans won %d%% of the national votes.\n", nat_rep_pct);

    if (total_dem > total_rep) {
        printf("The Democratic candidate won.\n");
    } else {
        printf("The Republican candidate won.\n");
    }
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: