gpt4 book ai didi

c++ - 找不到运行时检查失败的根源 #2

转载 作者:行者123 更新时间:2023-11-28 04:03:41 25 4
gpt4 key购买 nike

我的代码有两个问题,这让我发疯了。

首先是“运行时检查失败 #2。变量‘等级’周围的堆栈已损坏”

根据我的发现,当某些内容打印在数组边界之外时,这是一个错误。我查看并仔细检查了所有代码并修复了一些可能的问题,但我找不到最后一个触发此代码的问题。

第二,名称为array,为什么显示的是下一行的第一个字母?它不是在本地人中显示额外的字符,但它仍然以这种方式打印。我似乎找不到好的解决方法。

编辑:我将 Switch 语句固定为仅 10、9、8、7、6 测试并删除了不需要的行。

#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
#include<array>
using namespace std;

void outPut ( double score[][6], char name[][10], char grade[11]);
void dataIn ( double score[][6] ,char name[][10]);
void grades ( double score[][6], char grade[11] );

int main ( )
{
double score[11][6];
char name[11][10], grade[11];
for (int q = 0;q < 12;q++)
for (int w = 0;w < 7;w++)
score[q][w] = 0;
for (int z = 0;z < 12;z++)
for (int x = 0;x < 10;x++)
name[z][x] = 0;
dataIn ( score, name );
grades ( score, grade );
outPut ( score, name, grade );
system ( "pause" );
}

void outPut (double score[][6], char name[][10], char grade[11] )
{
cout << endl;
for (int a = 0;a < 11;a++)
{
for (int c = 0; c < 11;c++)
cout << name[a][c] << " ";
cout << setw ( 6 );
cout << showpoint << fixed << setprecision ( 2 );
for (int b = 0; b < 6;b++)
cout << score[a][b] << " ";
cout << grade[a];
cout << endl;
}
}

void dataIn ( double score[][6],char name[][10] )
{
ifstream inData;
ifstream inData1;
inData1.open ( "inName.txt" );
inData.open ( "indata.txt" );
for (int j = 0; j < 11; j++)
inData1 >> name[j], 11;
for (int row = 0; row < 11;row++)
for (int col = 0; col < 5;col++)
inData >> score[row][col];
}

void grades ( double score[][6], char grade[11] ) //[row][column]
{
double sum = 0, sum1 = 0, avg, avg1;
int avg2;
for (int a = 0;a < 11;a++)
{
sum1 = 0;
for (int b = 0;b < 6;b++)
sum1 = sum1 + score[a][b];
avg = sum1 / 5;
score[a][5] = avg;
}
for (int b = 0;b < 11;b++)
sum = sum + score[b][6];
avg1 = sum / 10;
score[10][5] = avg1;
for (int q = 0;q < 12;q++)
{
avg2 = score[q][5];
switch (avg2)
{
case 100:
case 99:
case 98:
case 97:
case 96:
case 95:
case 94:
case 93:
case 92:
case 91:
case 90:
grade[q] = 'A';
break;
case 89:
case 88:
case 87:
case 86:
case 85:
case 84:
case 83:
case 82:
case 81:
case 80:
grade[q] = 'B';
break;
case 79:
case 78:
case 77:
case 76:
case 75:
case 74:
case 73:
case 72:
case 71:
case 70:
grade[q] = 'C';
break;
case 69:
case 68:
case 67:
case 66:
case 65:
case 64:
case 63:
case 62:
case 61:
case 60:
grade[q] = 'D';
break;
default:
grade[q] = 'F';
}
}
}

inName.txt:

Johnson
Aniston
Cooper
Gupta
Blair
Clark
Kennedy
Bronson
Sunny
Smith
Average

inData.txt

85 83 77 91 76 
80 90 95 93 48
78 81 11 90 73
92 83 30 69 87
23 45 96 38 59
60 85 45 39 67
77 31 52 74 83
93 94 89 77 97
79 85 28 93 82
85 72 49 75 63

代码输出

image

最佳答案

好的,我检查了您的代码,发现它充满了索引错误。许多循环使用的上限大于相应数组的大小。 main() 中有示例功能:q < 12 , w < 7 , z < 12这些将写在给定数组的允许范围之外。对此根本没有代码检查,当您覆盖边界时,它不一定会抛出运行时错误,而是通常在数组外的内存为 时显示错误访问以供使用。了解 C 或 C++ 程序的内存布局很重要。每个函数都有一个堆栈,值类型完全存储在堆栈中(就像数组一样)。因此,当您在数组边界外写入时,您正在破坏堆栈。这实际上就是缓冲区溢出攻击的执行方式,通过在允许的边界之外写入并覆盖 return pointer。值(value)。

无论如何,我已经检查了您的代码并设法解决了问题:

main() :

for (int q = 0;q < 11;q++)
for (int w = 0;w < 6;w++)
score[q][w] = 0;
for (int z = 0;z < 11;z++)
for (int x = 0;x < 10;x++)

dataIn(...) :

for (int j = 0; j < 10; j++) 
inData1 >> name[j], 11;
for (int row = 0; row < 10; row++)
for (int col = 0; col < 5;col++)

grades(...) :

for (int a = 0;a < 10;a++)
{
sum1 = 0;
for (int b = 0;b < 5;b++)
sum1 = sum1 + score[a][b];
avg = sum1 / 5;
score[a][5] = avg;
}
/* code between */
for (int b = 0;b < 10;b++)
sum = sum + score[b][5];
/* code between */
for (int q = 0;q < 11;q++)

最后但同样重要的是,解决您的第二个问题...

outPut(...) :

for (int c = 0; c < 10; c++)

了解 C++ 中的数组索引很重要。 size = 10 的数组在 [0-9] 之间编入索引和 10在数组的边界之外。那导致了你所有的问题。

我建议您设置值 11, 10 and 6作为文件开头定义的常量,例如:

#define I_COUNT 11 // number of instances
#define N_WIDTH 10 // name size
#define G_COUNT 6 // number of grades (including average for instance)

然后在循环中使用常量而不是数字:

double score[I_COUNT][G_COUNT];

这样您就可以轻松更改代码以包含更多实例和等级。而且你不会有这样的错误。


或者,我使用 std::vector 编写了一个程序以更清洁的方式做你正在做的事情。我还让它计算每个科目的平均值。 inName.txt必须删除 Average从最后一个条目(只是这样设计的)。它可以接受任意数量的实例(人名)及其相应的等级。如果您愿意,成绩也可以超过 5。但它们必须一致(每一行的数字相同)。

下面是带注释的代码:

#include <iostream>  
#include <iomanip>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>

// type aliases - just to make it easier to read
using Names = std::vector<std::string>;
using Grades = std::vector<std::vector<double>>;
using GradeLetters = std::vector<char>;
char get_grade_letter(double avg);

// function prototypes
Names read_names(const std::string& path);
Grades read_grades(const std::string& path);
GradeLetters calculate_averages(Grades& grades);
void print_out(const Names& names, const Grades& grades, const GradeLetters& grade_letters);

int main()
{
auto names = read_names("inName.txt");
auto grades = read_grades("inData.txt");

auto grade_letters = calculate_averages(grades);
print_out(names, grades, grade_letters);

return 0; // don't forget this
}

// takes file-path input, reads content and returns vector of strings
Names read_names(const std::string& path) {
std::ifstream in(path);
std::vector<std::string> names;
std::string name;
while (std::getline(in, name)) {
if (name != "") // in case there is empty line in the end
names.push_back(name);
}
names.push_back("Average"); // let the program add it instead of having it in file
return names;
}

// takes file-path input, reads grades and stores them in matrix-ish format
Grades read_grades(const std::string& path) {
std::ifstream in(path);
std::vector<std::vector<double>> grades;
std::string grade_line;
while (std::getline(in, grade_line)) {
std::stringstream ss(grade_line);
std::vector<double> p_grades;
double grade;
while (ss >> grade)
p_grades.push_back(grade);
grades.push_back(p_grades);
}
return grades;
}

// calculates averages (per instance, and overall) - returns letter grades vector
GradeLetters calculate_averages(Grades& grades) {
std::vector<char> grade_letters;
std::vector<double> averages; // seperate vector, not yet in grades

int grades_per_instance = grades.at(0).size(); // for avg calc
averages.resize(grades_per_instance + 1); // +1 for the average

for (size_t i = 0; i < grades.size(); i++) {
double i_sum = 0; // instance sum
for (size_t j = 0; j < grades[i].size(); j++) {
i_sum += grades[i][j];
averages[j] += grades[i][j]; /* sum for each subject, for all students
* average of this will be calculated in
* a seperate loop, see below */
}
double i_avg = i_sum / grades_per_instance;
grades[i].push_back(i_avg);

char grade_letter = get_grade_letter(i_avg);
grade_letters.push_back(grade_letter);
}

int total_instances = grades.size();
double all_sum = 0; // for average of averages
for (size_t i = 0; i < averages.size(); i++) {
averages[i] /= total_instances; // can't do this in first loop, it must be over before we do it
all_sum += averages[i];
}
double all_avg = all_sum / grades_per_instance;
averages[averages.size() - 1] = all_avg; // averages is now complete, add it to `grades`
grades.push_back(averages); // we did not add averages row until now

char all_avg_grade_letter = get_grade_letter(all_avg);
grade_letters.push_back(all_avg_grade_letter);

return grade_letters;
}

char get_grade_letter(double avg) {
int avg_simplified = (int)(avg / 10);
switch (avg_simplified)
{
case 10:
case 9:
return 'A'; // [90-100]
case 8:
return 'B'; // [80-90[
case 7:
return 'C'; // [70-80[
case 6:
return 'D'; // [60-70[
default:
return 'F'; // <60 || >100
}
}

void print_out(const Names& names, const Grades& grades, const GradeLetters& grade_letters) {
std::cout << std::showpoint << std::fixed << std::setprecision(2); // can be set just once

// print header
std::cout << std::setw(20) << std::left << "Name:" << '\t';
for (size_t i = 0; i < grades.at(0).size() - 1; i++)
std::cout << "Sub" << i << " ";
std::cout << std::setw(5) << "Avg" << " Letter" << std::endl;
std::cout << "------------------------------------------------------------------------" << std::endl;

// print content
for (size_t i = 0; i < grades.size(); i++) {
std::cout << std::setw(20) << std::left << names.at(i) << '\t';
for (size_t j = 0; j < grades.at(i).size(); j++)
std::cout << std::setw(5) << grades.at(i).at(j) << " ";
std::cout << grade_letters.at(i) << std::endl;
if(i == grades.size()-2)
std::cout << "------------------------------------------------------------------------" << std::endl;
}
}

输出:

Name:                   Sub0   Sub1   Sub2   Sub3   Sub4   Avg    Letter
------------------------------------------------------------------------
Johnson 85.00 83.00 77.00 91.00 76.00 82.40 B
Aniston 80.00 90.00 95.00 93.00 48.00 81.20 B
Cooper 78.00 81.00 11.00 90.00 73.00 66.60 D
Gupta 92.00 83.00 30.00 69.00 87.00 72.20 C
Blair 23.00 45.00 96.00 38.00 59.00 52.20 F
Clark 60.00 85.00 45.00 39.00 67.00 59.20 F
Kennedy 77.00 31.00 52.00 74.00 83.00 63.40 D
Bronson 93.00 94.00 89.00 77.00 97.00 90.00 A
Sunny 79.00 85.00 28.00 93.00 82.00 73.40 C
Smith 85.00 72.00 49.00 75.00 63.00 68.80 D
------------------------------------------------------------------------
Average 75.20 74.90 57.20 73.90 73.50 70.94 C

关于c++ - 找不到运行时检查失败的根源 #2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59098480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com