C - fclose()seg fault //如何不写内存// euclidean div alg的C实现

时间:2014-08-31 00:48:41

标签: c segmentation-fault fclose

所以我刚刚完成了一个学校计划。它编译并运行罚款,直到执行最后一行。我得到了所有正确的输出,我希望只是无法弄清楚我正在做什么导致这个段错误。对不起,如果这是一个重复的问题。我看到很多seg故障问题,但是看不到比较,因为他们中的大多数人都说了很长的引用空指针的行,但我很自信我的指针不是空的。

下面是代码:对不起,我只想给那些希望帮助有机会扫描代码的人,看看他们是否看到了FILE *的任何问题。谢谢。

版主:如果有更好的方法来分享这段代码,请告诉我。上次我分享了指向第三方网站的链接,并将其删除。

大约250行。

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


//Constants
#define NUM_OF_CANDIDATES 7
#define INPUT_FILE_NAME "elections.txt"
#define NUM_OF_VOTES 117


//Stuctures

/**
 * Represents data connected to a candidate. Stores total votes and a name up to
 * 20 letters(inclusive).
 */
typedef struct candidate
{
    char name[21];
    int votes;
} Candidate;


//Method Prototypes
int Initialize(Candidate*, int, FILE*);
int ProcessVotes(Candidate*, int, int, FILE*);
void printResults(Candidate*, int, int);

/**
 * Method: int main()
 * 
 * Summary: Entry point to program 
 * 
 * @return 
 *  EXIT_FAILURE - Some error occurred
 *  EXIT_SUCCESS - No errors
 */
int main()
{
    //Instantiate array of Candidate
    Candidate electionCandidates[NUM_OF_CANDIDATES];

    //Open input file
    FILE* fin = fopen(INPUT_FILE_NAME, "r");
    if(fin == NULL)
    {
        printf("Unable to open file %s\n", INPUT_FILE_NAME);

        return EXIT_FAILURE;
    }

    //Initialize candidates
    if( Initialize(electionCandidates, NUM_OF_CANDIDATES, fin) )
    {
        printf("Failed to initialize candidates.\n");

        fclose(fin);
        return EXIT_FAILURE;
    }

    //Process the votes
    if(ProcessVotes(electionCandidates, NUM_OF_CANDIDATES, NUM_OF_VOTES, fin ))
    {
        printf("Failed to process votes\n");

        fclose(fin);
        return EXIT_FAILURE;
    }

    //Print results
    printResults(electionCandidates, NUM_OF_CANDIDATES, NUM_OF_VOTES );

    //Clean up
    fclose(fin);
    return EXIT_SUCCESS;

}


/**
 * Method: int Intialize(Candidate* arr, int numOfCandidates, FILE* fin)
 * 
 * Summary:
 *      
 *      Initializes the Candidates in arr. Reads input from fin
 * 
 * @param arr - pointer to array of Candidate
 * @param numOfCandidates - number of candidates in arr
 * @param fin - input file holding initial date
 * 
 * @return 
 *      0 - Success
 *      1 - Failed to Initialize
 */
int Initialize(Candidate* arr, int numOfCandidates, FILE* fin)
{
    char buf[21] = {'\0'};
    char* c;

    //Loop through all Candidate
    int i = 0;
    for(i = 0; i < numOfCandidates; i++)
    {
        //fscanf fails to read a string
        if( fgets(buf, 20, fin) == NULL || feof(fin) )
        {
           return 1; 
        }

        //Remove new line char from buffer stream
        c = strrchr(buf, '\n');
        *c = '\0';

        //Copy name from buffer to voter's struct
        strcpy((arr+i)->name, buf);

        //INitialize votes to 0
        (arr+i)->votes = 0;

    }

    return 0;

}


/**
 * Method: int ProcessVotes(Candidate* arr, int numOfCandidates, int numOfVotes, FILE* fin)
 * 
 * Summary:
 * 
 *      Counts votes corresponding to the candidates in arr from the input file
 *
 * @param arr - pointer to array of Candidate
 * @param numOfCandidates - number of Candidate in arr
 * @param numOfVotes - number of votes to process
 * @param fin - input file to read data from
 * @return 
 *      0 - Process Success
 *      1 - Failure to process votes
 */
int ProcessVotes(Candidate* arr, int numOfCandidates, int numOfVotes, FILE* fin)
{
    int i = 0, curVote = 0, idx = 0;

    for( i = 0; i < numOfVotes; i++ )
    {
        if(feof(fin) || fscanf(fin, "%d", &curVote ) == 0 )
        {
            return 1;
        }

        //Valid votes corresponding to candidates are 1<= curVote <= numOfCanidates
        //Indexes corresponding to the current vote will be ( curVote - 1 )
        idx = curVote - 1;
        if( idx / numOfCandidates == 0)
        {
            (arr+idx)->votes++;
        }


    }

    return 0;

}


/**
 * Method: void printResults( Candidate* arr, int numOfCandidates, int numOfVotes )
 * 
 * Summary:
 * 
 *      Displays the results out to stdin. First finds the winners as well
 * as updating spoiled votes. Then displays winners and spoiled votes
 * 
 * @param arr - pointer to array of Candidate
 * @param numOfCandidates - numberOfCandidates in arr
 * @param numOfVotes - number of Votes processed
 */
void printResults( Candidate* arr, int numOfCandidates, int numOfVotes )
{
    // Holds Candidate* to reference the winners
    Candidate** winners = (Candidate**)malloc(sizeof(Candidate*)*numOfCandidates);
    *winners = arr; //assume first Candidate is the only winner
    int numOfWinners = 1;

    //counter for spoiled votes. max number of spoiled votes is numOfVotes
    //subtract first candidate's votes because we will start our loop
    //with the second candidate
    int spoiledVotes = numOfVotes - arr->votes; //subtract first Candidate votes


    int i = 0;
    for(i = 1; i < numOfCandidates; i++)
    {

        if( (arr+i)->votes > (*winners)->votes )
        {
            //Single winner at this point re-initialize list and counter
            *winners = arr + i;
            numOfWinners = 1;

        }

        else if ((arr + i )->votes == (*winners)->votes )
        {
            //add a winner to winner list
            *(winners + numOfWinners) == (arr+i);
            numOfWinners++;
        }

        //update spoiled votes
        spoiledVotes -= (arr+i)->votes;

    }

    //Tie
    if(numOfWinners > 1)
    {
        printf("There is a tie between %s ", (*winners)->name);
        for( i = 1; i < numOfWinners; i++)   
        {
            printf("and %s ", (*winners + i)->name );
        }

        printf("who got a total of %d votes each.\n", (*winners)->votes);

    }

    //No tie
    else
    {
        printf("%s won the election with %d votes.\n",
                (*winners)->name, (*winners)->votes );

    }

    printf("There was a total of %d spoilt votes.\n", spoiledVotes);

    //Clean up
    free(winners);
}

2 个答案:

答案 0 :(得分:1)

编译警告

        *(winners + numOfWinners) == (arr+i);

应该是:

        *(winners + numOfWinners) = (arr+i);

答案 1 :(得分:1)

ProcessVotes中,您有:

    idx = curVote - 1;
    if( idx / numOfCandidates == 0)
    {
        (arr+idx)->votes++;
    }

但是,您没有代码可以验证curVotefscanf()扫描后是否为正数。这意味着如果curVote小于或等于0,则在arr上使用负索引,这将损坏内存(并导致未定义的行为)。