1
#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)
{
    // TODO
    for (int i = 0; i <= candidate_count -1 ; i++)
    {
        if (strcmp(name, candidates[i].name) == 0)
        {
            candidates[i].votes = candidates[i].votes + 1;
            return true;
        }
    }
    return false;
}

// Print the winner (or winners) of the election
void print_winner(void)
{
    // TODO
    candidate temp[0];
    for (int i = 0; i < candidate_count; i++)
    {
        if((candidates[i].votes > candidates[i + 1].votes) && (i + 1 < candidate_count))
        {
            temp[0] = candidates[i];
            candidates[i] = candidates[i+1];
            candidates[i+1] = temp[0];
            i = -1;
        }

    }

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

}


Hello there, thank you for taking your precious time reading my question :)

I just got into CS50 and really appreciate the way David Malan is teaching. I have no real prior programming experience, though I had to program a little during school.

I looked for this answer in other threads, but did not find a corresponding one. Please feel free to rectify me if I have overseen a possible answer.

The problem now is the following: When I run this code, it works fine. It prints everything out as it should. Except that in most cases, after everything worked fine, it returns a segmentation fault (core dumped) after it gives the right output.

I assume that I refer to an array index that does not exist, but can't spot it. Debugging does not help either, as it shows the error at the very last curly bracket of main.

Thank you for your time :)

Edit: I added int temp2[candidate_count]; after sorting some things out. It does not do anything but declaring an int-array with the size of candidate_count. But with this, it works. I can't fathom the reason?

#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)
{
    // TODO
    for (int i = 0; i < candidate_count; i++)
    {
        if (strcmp(name, candidates[i].name) == 0)
        {
            candidates[i].votes = candidates[i].votes + 1;
            return true;
        }
    }
    return false;
}

// Print the winner (or winners) of the election
void print_winner(void)
{
    // TODO
 int temp2[candidate_count];


    candidate temp[0];
  for (int i = 0; i < candidate_count; i++)
    {
        if((candidates[i].votes > candidates[i+1].votes) && (i + 1 < candidate_count))
        {
            temp[0] = candidates[i];
            candidates[i] = candidates[i+1];
            candidates[i+1] = temp[0];
            i = -1;
        }

    }


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

}

If I take it out, it does not work properly anymore.

Redgrieve
  • 69
  • 7
  • 1
    Do you know the input for your program? Then you can easily [*debug*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) your program. More specifically use a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to catch the crash as ans when it happens. That will allow you to locate where in your code it happens, and let you examine involved variables to see their values. – Some programmer dude Aug 27 '22 at 15:48
  • 1
    On one note, in the loop `for (int i = 0; i <= candidate_count -1 ; i++)` why not `for (int i = 0; i < candidate_count; i++)` instead? Don't mix different expressions that do the same thing, try to keep things consistent. It will make it easier to read, understand and maintain your code. As well as make it easier to debug it. – Some programmer dude Aug 27 '22 at 15:50
  • As a hint: With the GCC or Clang compilers build with the flag `-Wpedantic`, it will [give you a warning](https://godbolt.org/z/4h4nhzGEr) you should listen to. – Some programmer dude Aug 27 '22 at 15:52
  • @Someprogrammerdude - Thank you for the time you took to formulate those answers. Regarding the first one - I tried debugging. But it does not help - it gives me the segmentation fault error at the last curly bracket with no further explanation. Thank you for the advice regarding the loop - I can't explain why I designed it that way :)And I will give the GCC compiler a shot. Thanks again :) – Redgrieve Aug 27 '22 at 15:57
  • 1
    You also have a few of array out-of-bounds cases in the `print_winner` function. For example you access `candidates[-1]`. – Some programmer dude Aug 27 '22 at 16:06
  • Thank you! This is where I assume my problem lies. If I comment this block out, it works fine. I apologize that I have to ask, but where do I access candidates[-1]? i = 0 at the start of the for loop. So the first index I access should be 0? I set i to -1 inside the loop so that it get iterated to 0 after it runs through and starts again from scratch. – Redgrieve Aug 27 '22 at 16:09
  • @chux-ReinstateMonica - Thank you for your time :) The value of `candidate_count -1`should be the number of candidates - 1. The number is declared at the beginning of the program and set by user input. If I had 2 candidates, it should be "1". If 5, then it would be "4". The way you are asking, I fear that I made a thought mistake, have I? :o – Redgrieve Aug 28 '22 at 09:29
  • @Redgrieve Mistake on my part - comment removed. – chux - Reinstate Monica Aug 28 '22 at 13:20

1 Answers1

1

Your suspect line of code probably is:

    if((candidates[i].votes > candidates[i + 1].votes) && (i + 1 < candidate_count))

As this goes out of bounds past the end of your array of candidates. Just to check that out, I added in a quick test to peer into that region and print it.

if (i == candidate_count -1)
    printf("Suspect code ahead: name-> %s, votes: %d\n", candidates[i + 1].votes);
        if((candidates[i].votes > candidates[i + 1].votes) && (i + 1 < candidate_count))

When I ran the program on my machine with three candidates, this was the terminal output.

@Una:~/C_Programs/Console/Candidate/bin/Release$ ./Candidate A B C
Number of voters: 5
Vote: A
Vote: B
Vote: B
Vote: B
Vote: C
Suspect code ahead: name-> (null), votes: -1921036152
B

In my case, the program did not experience a segment fault, but could just as well have as it is reading out-of-bounds memory. What you probably need to do is some bounds checking so that you do not attempt to read past your array.

Check that out.

NoDakker
  • 3,390
  • 1
  • 10
  • 11
  • Hey there, thanks for that elaborated answer :) I did notice, that candidate[i+1] gets out of bound eventually. Though I thought because of the "&& (i + 1 < candidate_count))" it won't and thus is not important for me. Is this what you meant? I will try to fix it and edit this answer if it works =) – Redgrieve Aug 27 '22 at 21:12
  • 2
    Even with the "&&" where you are performing an "and" compound test, the first part of the test is going to be performed first which could trigger the segment fault. Looking at your code, you might just have to revise the for loop to test for "(candidate_count - 1)". – NoDakker Aug 27 '22 at 22:01
  • Ok, I tried as you said, but it did not help for reasons unknown. As I again commented a few things out, here is what happened. A remainder code-snipped saying `int temp2[candidate_count]` which does absolutely nothing, lets me run the code without a problem. I will post the edited code in my question above. – Redgrieve Aug 27 '22 at 22:32
  • I will post my solution to CS50 and ask for help there within my comments. Maybe someone there could explain in detail? But I would not have found a way to execute the code without errors without your effort. Thank you so much :) – Redgrieve Aug 27 '22 at 22:41