Язык Си: выборы большинством голосов


Начинается третья неделя обучения Computer Science CS50 (Гарвард) и мы продолжаем учить язык C. Первое задание: реализация системы голосования, где выигрывает кандидат, получившей наибольшее количество голосов, т.н. мажоритарная система по большинству или просто «победитель получает все» (plurality.c). Пользователь может выбрать из списка кандидатов одного и проголосовать за него. При подсчете голосов, кандидат, набравший наибольшее количество голосов, объявляется победителем выборов.

Как же реализовать такой функционал?

  1. В константе #define MAX n укажем максимальное количество кандидатов, которое может быть на выборах;
  2. Создадим структуру: struct candidate. В каждом элементе этой структуры будет два поля: строка name (имя кандидата), и число voices (количество голосов,  которые получил кандидат).
  3. Создадим глобальный массив candidates, каждый элемент которого относится к структуре candidate.
  4. Создадим глобальную переменную candidate_count (количество кандидатов на выборах).
  5. Передадим аргументы командной строки в массив candidates.
  6. Попросим пользователя ввести количество избирателей.
  7. Попросим пользователя проголосовать, вызвав функцию vote.
  8. В функции print_winner, проведем подсчет голосов и напечатаем имя победителя (или победителей) выборов.

Как обычно, Игроглаз работает без библиотеки cs50.h, что требует некоторой переработки кода и использования указателей. Поэтому вариант Штукенции (он находится ниже) в этот раз выглядит более простым. Итак, решение Игроглаза:

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

// Max number of candidates
#define MAX 9

// Candidates have name and vote count
typedef struct
{
    char name[1000];
    int votes;
}
candidate;

// Array of candidates
candidate candidates[MAX];

// Number of candidates
int candidate_count;

// Function prototypes
bool vote(char *name);
void print_winner(void);

int main(int argc, char *argv[])
{
    int i, j;
    int voter_count;

    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: plurality [candidate ...]\n");
        return 1;
    }

    // Populate array of candidates
    candidate_count = argc - 1;
    if (candidate_count > MAX)
    {
        printf("Maximum number of candidates is %i\n", MAX);
        return 2;
    }
    for (i = 0; i < candidate_count; i++)
    {
        strcpy(candidates[i].name, argv[i + 1]);
        candidates[i].votes = 0;
    }

    printf("Number of voters: ");
    scanf("%d", &voter_count);
    while (getchar() != '\n') ; // clear buffer

    // Loop over all voters
    for (i = 0; i < voter_count; i++)
    {
        char name[1000]; // local array for user input

        printf("Vote: ");
        // lets the user input candidate name to vote
        for (j = 0; ; j++)
        {
            scanf("%c", &name[j]);
            if (name[j] == '\n')
            {
                name[j] = '\0'; // replace last char from \n to \0
                break;
            }
        }

        // Check for invalid vote
        if (!vote(name))
        {
            printf("Invalid vote.\n");
        }
    }

    // Display winner of election
    print_winner();

    getchar();
    getchar();
    return 0;
}

// Update vote totals given a new vote
bool vote(char *name)
{
    int i;

    for (i = 0; i < candidate_count; i++)
    {
        if (strcmp (name, candidates[i].name) == 0)
        {
            candidates[i].votes++;
            return true;
        }
    }

    return false;
}

// Print the winner (or winners) of the election
void print_winner(void)
{
    int i;
    int max = 0;

    // find maximum votes
    for (i = 0; i < candidate_count; i++)
    {
        if (max < candidates[i].votes)
            max = candidates[i].votes;
    }

    // print winner(s)
    for (i = 0; i < candidate_count; i++)
    {
        if (max == candidates[i].votes)
            printf("%s\n", candidates[i].name);
    }
    return;
}

Решение Штукенции:

Самым сложным моментом здесь оказалось сделать вывод победителя. Для это нужно найти кандидата с наибольшим числом голосов. Здесь как раз пригодилась информация про сортировку значений из лекции. Еще один момент, если количество голосов у нескольких кандидатов получается одинаковым, то программа должна показать всех этих кандидатов.

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

// Max number of candidates
#define MAX 9

// Candidates have name and vote count
typedef struct
{
    string name;
    int votes;
}
candidate;

// Array of candidates
candidate candidates[MAX];

// Number of candidates
int candidate_count;

// Function prototypes
bool vote(string name);
void print_winner(void);

int main(int argc, string argv[])
{
    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: plurality [candidate ...]\n");
        return 1;
    }

    // Populate array of candidates
    candidate_count = argc - 1;
    if (candidate_count > MAX)
    {
        printf("Maximum number of candidates is %i\n", MAX);
        return 2;
    }
    for (int i = 0; i < candidate_count; i++)
    {
        candidates[i].name = argv[i + 1];
        candidates[i].votes = 0;
    }

    int voter_count = get_int("Number of voters: ");

    // Loop over all voters
    for (int i = 0; i < voter_count; i++)
    {
        string name = get_string("Vote: ");

        // Check for invalid vote
        if (!vote(name))
        {
            printf("Invalid vote.\n");
        }
    }

    // Display winner of election
    print_winner();
}

// Update vote totals given a new vote
bool vote(string name)
{
    for (int i = 0; i < candidate_count; i++)
    {
        if (!strcmp(name, candidates[i].name))
        {
            candidates[i].votes += 1;
            return true;
        }
    }
    return false;
}

// Print the winner (or winners) of the election
void print_winner(void)
{
    int biggest_vote = 0;
    string winner;

    for (int i = 0; i < candidate_count; i++)
    {
        if (candidates[i].votes > biggest_vote)
        {
            biggest_vote = candidates[i].votes;
            winner = candidates[i].name;
        }
    }

    for (int j = 0; j < candidate_count; j++)
    {
        if (candidates[j].votes == biggest_vote)
        {
            printf("%s\n", candidates[j].name);
        }
    }

    return;

}

Тестируем программу:


Запись опубликована в рубрике С (Си). Добавьте в закладки постоянную ссылку.

Добавить комментарий

🇬🇧 Attention! Comments with URLs/email are not allowed.
🇷🇺 Комментарии со ссылками/email удаляются автоматически.