Отладчик выдает правильный вывод, а нормальное выполнение — нет.

У меня возникла эта странная проблема, когда мой код делает именно то, что я хочу, когда я запускаю его через отладчик, но он не работает, когда я запускаю его в обычном режиме. Что еще более странно, так это то, что я также не получаю ошибку времени выполнения. Вот где может быть проблема, но я не уверен на 100% в этом:

void calcMostMissed (double *ptr, int totalContestants, int arrSize)
{
    //output header
    cout << endl << "MOST MISSED QUESTIONS" << endl;

    //check how many times a question is missed and its percentage, then output it if it's above 60%
    double curQuest = *ptr;
    int freq = 0;
    int j = 0;
    double percentMissed;
    for (int i = 0; i <= arrSize; i++)     //loop through the missed questions array
    {
        if (*(ptr + i) > 0)      //if pointer is pointing at a question number (extra space in array is set to 0)...
        {
            if (*(ptr + i) == curQuest)      //then check how often it occurs in the array
            freq++;
        }
        else    //if the pointer is not pointing at a question number anymore...
        {
            //calculate percent missed and output it if its 60% or greater
            percentMissed = (static_cast<double>(freq) / totalContestants) * 100;
            if (percentMissed >= 60)
            {
                cout << static_cast<int>(curQuest) << "\t" << fixed << setprecision(2) << percentMissed << "%" << endl;
            }
            // check if the question's percentage missed has already been calculated and evaluated
            j++;
            curQuest = *(ptr + j);
            int r = 0;
            while (r < j)
            {
                if (*(ptr + r) == curQuest)
                {
                    if (j < arrSize - 1)
                    {
                        j++;
                        curQuest = *(ptr + j);
                    }
                }
                r++;
            }
            if (!(j == arrSize - 1 && r == arrSize - 1))
            {
                i = 0;
            }
            freq = 0;
        }
        //if the current question variable has been through all missed question, then leave loop
        if (curQuest < 1)
        {
            break;
        }
    }
}

Что эта функция должна делать в целом, так это находить процент пропущенных ответов по всем пропущенным вопросам и выводить только те, которые превышают 60% включительно.

См. также:  Как правильно поменять местами пустые указатели?

Вот что выводит мой отладчик (и как я хочу, чтобы это выглядело):

Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C

0012387654 - 0.00
1 2 3
C A B
A B C

0012364213 - 0.00
1 2 3
C A B
A B C

Mean: 0.00
Median: 0.00
Mode: 0.00

MOST MISSED QUESTIONS
1       100.00%
2       100.00%
3       100.00%

Вот что выдает нормальное выполнение:

Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C

0012387654 - 0.00
1 2 3
C A B
A B C

0012364213 - 0.00
1 2 3
C A B
A B C

Mean: 0.00
Median: 0.00
Mode: 0.00

MOST MISSED QUESTIONS

Process returned 0 (0x0)   execution time : 14.442 s
Press any key to continue.

Мой отладчик работает до конца моей программы просто отлично, но по какой-то причине обычное выполнение все еще имеет недостатки. Любые предложения приветствуются, и я уточню все, что я, возможно, забыл упомянуть.

Если это поможет, я использую Code::Blocks в качестве своей IDE.

Еще немного информации о моем коде: есть 3 вопроса, и все участники набрали 0% на тесте, что означает, что все вопросы имеют неправильные ответы.

Вывод: числа — это идентификатор участника, рядом с ним — его оценка, список чисел под ним — это номер вопроса, в котором они ошиблись, под ним — ответы участника, а под ним — правильные ответы.

Это функция, которая вызывает функцию calcMostMissed:

void statReport (double *ptr, int totalScores, double *mmqPtr, int arrSize)
{
    //calculate mean of scores
    double mean = calcMean(ptr, totalScores);

    //calculate median of scores
    double median = calcMedian(ptr, totalScores);

    //calculate mode of scores
    double *mode = calcMode(ptr, totalScores);

    //output to console the data
    cout << "Mean: " << fixed << setprecision(2) << mean << endl;
    cout << "Median: " << median << endl;
    cout << "Mode: ";
    sort(mode, mode + totalScores);
    int j = 0;
    for (int i = 0; i < totalScores; i++)
    {
        if (*(mode + i) != -1)
        {
            if (j == 0)
            {
                cout << *(mode + i);
            }
            else
            {
                cout << ", " << *(mode + i);
            }
            j++;
        }
    }
    cout << endl;

    //call calcMissedQuestions function
    calcMostMissed(mmqPtr, totalScores, arrSize);

    //delete pointers
    delete[] mode;
    mode = nullptr;
    delete[] mmqPtr;
    mmqPtr = nullptr;
}

И это основная функция:

int main()
{
    string answerKeyName;
    string contestantAnswerName;
    ifstream answerKeyFile;
    ifstream contestantAnswerFile;

    //ask for file names
    cout << "Enter name of answer key file: ";
    cin >> answerKeyName;
    cout << "Enter name of contestant's answers file: ";
    cin >> contestantAnswerName;

    //check if files can be opened properly
    answerKeyFile.open(answerKeyName, ios::binary);
    contestantAnswerFile.open(contestantAnswerName, ios::binary);
    if(!answerKeyFile)
    {
        cout << "Answer key file could not be opened" << endl;
        exit(EXIT_FAILURE);
    }
    if (!contestantAnswerFile)
    {
        cout << "Contestant's answers file could not be opened" << endl;
        exit(EXIT_FAILURE);
    }

    //find how many contestant's there are
    int i = 0;
    string temp;
    while (contestantAnswerFile.good())
    {
        getline(contestantAnswerFile, temp);
        if (temp != "")
        {
            i++;
        }
    }
    contestantAnswerFile.clear();
    contestantAnswerFile.seekg(0, ios::beg);

    //create contestant's score array
    double *scorePtr = new double[i];

    //create pointer for all missed questions
    double *mmqPtr = nullptr;
    int arrSize;

    //compare the contestant's answers to the answer key, then fill array with score
    double score;
    for (int c = 0; c < i; c++)
    {
        score = compareAnswers (contestantAnswerFile, answerKeyFile, mmqPtr, i, arrSize);
        *(scorePtr + c) = score;
    }

    //create the statistics report
    statReport(scorePtr, i, mmqPtr, arrSize);

    //delete dynamically allocated array
    delete[] scorePtr;
    scorePtr = nullptr;

    //close files
    answerKeyFile.close();
    contestantAnswerFile.close();

    return 0;
}

for (int i = 0; i <= arrSize; i++) Это выглядит подозрительно. Допустимые индексы в массиве из arrSize элементов: от 0 до arrSize-1. Ваша программа обращается к ptr[arrSize] — велика вероятность того, что это демонстрирует неопределенное поведение из-за доступа к индексу за пределами границ.   —  person amy    schedule 14.03.2021

См. также:  Flask (непредвиденная ошибка при использовании Gunicorn

Я думаю, что условие if (curQuest < 1) break; ближе к концу кода срабатывает на первой итерации i=0 вышеуказанного цикла, и, следовательно, ничего не печатается. Это каким-то образом преодолевается при запуске программы gdb. Вам, по крайней мере, нужно будет предоставить входные параметры вашей функции, чтобы определить, что пошло не так, или, что еще лучше, опубликовать программу main.   —  person amy    schedule 14.03.2021

@Giogre Я добавил как функцию, которая вызывает calcMostMissed, так и основную функцию. надеюсь, это поможет   —  person amy    schedule 14.03.2021

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. amy

    Ниже я думаю, что проблема заключается в том, что я все еще не могу ее правильно скомпилировать, потому что другие функции и входные файлы не предоставляются, вероятно, правильно, чтобы не загромождать вопрос еще больше:

    double *mmqPtr = nullptr; определяется в main(), затем передается в функцию statReport() без связи с каким-либо объектом. После этого он действует как первый параметр для функции calcMostMissed() и разыменовывается внутри нее, но все еще является nullptr, поэтому это приводит к неопределенному поведению.

    Существует также проблема индекса за пределами цикла внутри цикла, как указано в комментариях.

    Это, или что-то подобное, находится на правильном пути. Программа, запущенная под отладчиком, часто ведет себя иначе. И один конкретный способ заключается в том, что иногда вся память обнуляется под отладчиком, а не обычно. person amy; 14.03.2021

    @davidbak, поэтому среда отладки — это своего рода безопасный режим против UB, вызванный невозможностью инициализации переменных. person amy; 14.03.2021

    Некоторые из них ведут себя так, да. Что может быть проблематично, как выясняет OP … нет ничего более раздражающего, чем заставить вашу программу работать на вашем компьютере только для того, чтобы проверить ее и обнаружить, что она ломается в другом месте … person amy; 14.03.2021

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

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: