简体   繁体   中英

Segmentation fault in merge sort function : CS50 pset 3 ; tideman

Now I am in a process that tries to check each function which I have made. I have finished checking the vote and record_preference function. It's worked. Now, I'm struck with the sort function which I try to use merge sort. I have been using this merge function in my past problem, but, when I try to use it for this time. It showed me "segmentation fault". Here's my terminal [picture 1] when I try to insert ballots like this picture [picture 2] . As you see, "Before sort" has appeared but "After sort" hasn't. "Segmentation fault" has appeared instead.

ps. score_winner is a variable that I made for using it like score tags for sorting pairs in increasing order.What on my mind is the terminal should appear like (below).

before sort : 
pair 0 :7 alice bob 
pair 1 :6 charlie alice 
pair 2 :5 bob charlie 

after sort : 
pair 0 :5 bob charlie  
pair 1 :6 charlie alice 
pair 2 :7 alice bob

My code [the merge function is inmost.]

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

// Max number of candidates
#define MAX 9

// preferences[i][j] is number of voters who prefer i over j
int preferences[MAX][MAX];

// locked[i][j] means i is locked in over j
bool locked[MAX][MAX];

// Each pair has a winner, loser
typedef struct
{
    int winner;
    int loser;
}
pair;

// Array of candidates
string candidates[MAX];
pair pairs[MAX * (MAX - 1) / 2];

int pair_count;
int candidate_count;

// Function prototypes
void merge(int left, int mid, int right);
void merge_sort(int left, int right);
bool vote(int rank, string name, int ranks[]);
void record_preferences(int ranks[]);
void add_pairs(void);
void sort_pairs(void);

int main(int argc, string argv[])
{
    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: tideman [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] = argv[i + 1];
    }

    // Clear graph of locked in pairs
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            locked[i][j] = false;
        }
    }

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

    // Query for votes
    for (int i = 0; i < voter_count; i++)
    {
        // ranks[i] is voter's ith preference
        int ranks[candidate_count];

        // Query for each rank
        for (int j = 0; j < candidate_count; j++)
        {
            string name = get_string("Rank %i: ", j + 1);

            if (!vote(j, name, ranks))
            {
                printf("Invalid vote.\n");
                return 3;
            }
        }

        record_preferences(ranks);

        printf("\n");
    }

    add_pairs();

    printf("%i \n", pair_count);
    printf("before sort : \n");
    for(int i=0;i<pair_count;i++)
    {
        printf("pair %i :", i);
        printf("%i ", preferences[pairs[i].winner][pairs[i].loser]); //score of winner
        printf("%s ", candidates[pairs[i].winner]);
        printf("%s ", candidates[pairs[i].loser]);
        printf("\n");
    }
    printf("\n");

    merge_sort(0, pair_count - 1);

    printf("after sort : ");
    for(int i=0;i<pair_count;i++)
    {
        printf("pair %i :", i);
        printf("%i ", preferences[pairs[i].winner][pairs[i].loser]); //score of winner
        printf("%s ", candidates[pairs[i].winner]);
        printf("%s ", candidates[pairs[i].loser]);
        printf("\n");
    }
    printf("\n");

    return 0;
}

// Update ranks given a new vote
bool vote(int rank, string name, int ranks[])
{
    // TODO
    string name1[candidate_count];
    for (int i = 0; i < candidate_count; i++)
    {
        name1[i] = candidates[i];
    }
    int sum = 0;
    for (int j = 0; j < candidate_count; j++)
    {
        if (strcmp(name, name1[j]) == 0)
        {
            sum = sum + 1;
            ranks[rank] = j;
        }
        else
        {
            sum = sum + 0;
        }
    }
    if (sum == 1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// Update preferences given one voter's ranks
void record_preferences(int ranks[])
{
    // TODO
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            if (i < j)
            {
                preferences[ranks[i]][ranks[j]] = preferences[ranks[i]][ranks[j]] + 1;
            }
            else
            {
                preferences[ranks[i]][ranks[j]] = preferences[ranks[i]][ranks[j]] + 0;
            }
        }
    }

    return;
}

// Record pairs of candidates where one is preferred over the other
void add_pairs(void)
{
    // TODO
    for (int i = 0; i < candidate_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            if (i < j)
            {
                if (preferences[i][j] < preferences[j][i])
                {
                    pairs[pair_count].winner = j;
                    pairs[pair_count].loser = i;
                    pair_count = pair_count + 1;
                }
                else if (preferences[i][j] > preferences[j][i])
                {
                    pairs[pair_count].winner = i;
                    pairs[pair_count].loser = j;
                    pair_count = pair_count + 1;
                }
                else
                {
                    pair_count = pair_count + 0;
                }
            }
        }
    }
    return;
}

// Sort pairs in decreasing order by strength of victory
void sort_pairs(void)
{
    // TODO
    merge_sort(0, pair_count - 1);
}

void merge(int left, int mid, int right)
{

    int len1 = mid - left + 1;
    int len2 = right - mid;
    int i;
    int index1 = 0, index2 = 0;
    // create temp array
    int score_winner[MAX];
    for (i = 0; i < pair_count; i++)
    {
        score_winner[i] = preferences[pairs[i].winner][pairs[i].loser];
    }
    int left_array[len1];
    int right_array[len2];
    int str_win_left_array[len1];
    int str_win_right_array[len2];
    int str_los_left_array[len1];
    int str_los_right_array[len2];

    //take array to temp array
    for (i = 0; i < len1; i++)
    {
        left_array[i] = score_winner[left + i];
        str_win_left_array[i] = pairs[left + i].winner;
        str_los_left_array[i] = pairs[left + i].loser;
    }
    for (i = 0; i < len2; i++)
    {
        right_array[i] = score_winner[mid + 1 + i];
        str_win_left_array[i] = pairs[mid + 1 + i].winner;
        str_los_left_array[i] = pairs[mid + 1 + i].loser;
    }

    i = left;
    while (index1 < len1 && index2 < len2)
    {
        if (left_array[index1] < right_array[index2])
        {
            score_winner[i] = left_array[index1];
            pairs[i].winner = str_win_left_array[index1];
            pairs[i].loser = str_los_left_array[index1];
            index1++;
        }
        else
        {
            score_winner[i] = right_array[index2];
            pairs[i].winner = str_win_right_array[index2];
            pairs[i].loser = str_los_right_array[index2];
            index2++;
        }
        i++;
    }
    // check for other one
    while (index1 < len1)
    {
        score_winner[i] = left_array[index1];
        pairs[i].winner = str_win_left_array[index1];
        pairs[i].loser = str_los_left_array[index1];
        i++;
        index1++;
    }
    while (index2 < len2)
    {
        score_winner[i] = right_array[index2];
        pairs[i].winner = str_win_right_array[index2];
        pairs[i].loser = str_los_right_array[index2];
        i++;
        index2++;
    }

}

void merge_sort(int left, int right)
{
    int mid;
    int i;
    if (left < right)
    {
        mid = (left + right) / 2;
        merge_sort(left, mid);
        merge_sort(mid + 1, right);

        merge(left, mid, right);
    }
}

Your code created a negative index at line 227. The following is the error message. Please use this link to debug it. Just click "Start" to build the code and bring up the terminal.

 Memory access error: reading from the outside of a memory space; abort execution.
  # Reading 4 bytes from 0xf7a36fc0 will read undefined values.
  #
  # The memory-space-to-be-read (start:0x824c960, size:324 bytes) is bound to 'preferences' at
  #    file:/prog.c::9, 0
  #
  #                               0x824c960               0x824caa3
  #                               +------------------------------+
  #                         ......| the memory-space-to-be-read  |
  #                               +------------------------------+
  #                         ^~~~~~~~~~
  # the read starts at 0xf7a36fc0 that is 276912544 bytes before the memory-space start.
  #
  # Stack trace (most recent call first) of the read.
  # [0]  file:/prog.c::227, 9
  # [1]  file:/prog.c::299, 9
  # [2]  file:/prog.c::107, 5
  # [3]  [libc-start-main]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM