У меня возникла эта странная проблема, когда мой код делает именно то, что я хочу, когда я запускаю его через отладчик, но он не работает, когда я запускаю его в обычном режиме. Что еще более странно, так это то, что я также не получаю ошибку времени выполнения. Вот где может быть проблема, но я не уверен на 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
Я думаю, что условие if (curQuest < 1) break;
ближе к концу кода срабатывает на первой итерации i=0
вышеуказанного цикла, и, следовательно, ничего не печатается. Это каким-то образом преодолевается при запуске программы gdb. Вам, по крайней мере, нужно будет предоставить входные параметры вашей функции, чтобы определить, что пошло не так, или, что еще лучше, опубликовать программу main
. — person amy schedule 14.03.2021
@Giogre Я добавил как функцию, которая вызывает calcMostMissed, так и основную функцию. надеюсь, это поможет — person amy schedule 14.03.2021
Ниже я думаю, что проблема заключается в том, что я все еще не могу ее правильно скомпилировать, потому что другие функции и входные файлы не предоставляются, вероятно, правильно, чтобы не загромождать вопрос еще больше:
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