我正在做一个程序来代表一个表#34;学生"。它具有属性' ID','名字'和'姓氏'。我做了一个二维数组,并将cout语句全部用于检查...正确的信息存储在正确的单元格中,但是我得到一个我不认识的错误。 .cpp文件的代码是:
#include "Table1.h"
#include <sstream>
#include <iostream>
using namespace std;
Table1::Table1(){
RowPos = 1;
ColPos = 0;
for(int i=1; i<16; i++)
{
for(int j=0; j<3 ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
}
string Table1::InsertStudent(string ID, string FN, string LN){
Students[0][0] = "StudentID";
Students[0][1] = "FirstName";
Students[0][2] = "LastName";
Students[RowPos][ColPos] = ID; //Assign ID to first column
ColPos++; //Move to next column
Students[RowPos][ColPos] = FN;
ColPos++;
Students[RowPos][ColPos] = LN;
ColPos++;
ColPos = 0;
RowPos++;
}
void Table1::Print(string Name){
if(Name == "students"){
for(int i=1; i<16; i++)
{
int j=0;
if(Students[i][j] == "FakeNull")
break;
else
cout<< "("<< Students[i][j]<< ",";
j++;
cout<< Students[i][j]<< ",";
j++;
cout<< Students[i][j]<< ")";
}
}
}
我的Table1.h是:
#include <iostream>
using namespace std;
#include <string>
#ifndef GRADE_HEADER
#define GRADE_HEADER
class Table1
private:
string Students[16][3];
string Grades[16][3];
int RowPos;
int ColPos;
public:
Table1();
string InsertStudent(string, string, string);
string InsertGrade(string, string, string, string);
void Print(string);
void Select(string, string, int);
void Select(string, string, string);
void Select(string, string, char);
void Join();
string Converter(int);
};
#endif
错误如下:
*** glibc detected *** ./a.out: double free or corruption (out): 0xbfbdeae0 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xeadee2]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0x9a951f]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b) [0x99099b]
/usr/lib/i386-linux-gnu/libstdc++.so.6(+0x909dc)[0x9909dc]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x2e)[0x990a4e]
./a.out[0x8049299]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xe514d3]
./a.out[0x8048a71]
======= Memory map: ========
003a0000-003ca000 r-xp 00000000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
003ca000-003cb000 r--p 00029000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
003cb000-003cc000 rw-p 0002a000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
005a5000-005a6000 r-xp 00000000 00:00 0 [vdso]
007c5000-007e5000 r-xp 00000000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
007e5000-007e6000 r--p 0001f000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
007e6000-007e7000 rw-p 00020000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
00900000-009d8000 r-xp 00000000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009d8000-009d9000 ---p 000d8000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009d9000-009dd000 r--p 000d8000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009de000-009e5000 rw-p 00000000 00:00 0
00c13000-00c2f000 r-xp 00000000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00c2f000-00c30000 r--p 0001b000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00c30000-00c31000 rw-p 0001c000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00e38000-00fdc000 r-xp 00000000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fdc000-00fde000 r--p 001a4000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fde000-00fdf000 rw-p 001a6000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fdf000-00fe2000 rw-p 00000000 00:00 0
08048000-0804a000 r-xp 00000000 00:19 52698567
0804a000-0804b000 r--p 00001000 00:19 52698567
0804b000-0804c000 rw-p 00002000 00:19 52698567
09df7000-09e18000 rw-p 00000000 00:00 0 [heap]
b77c9000-b77cc000 rw-p 00000000 00:00 0
b77de000-b77e3000 rw-p 00000000 00:00 0
bfbbe000-bfbdf000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
答案 0 :(得分:13)
答案 1 :(得分:3)
首先要修改Table1构造函数,如下所示:
Table1::Table1()
{
//
// C++ arrays are zero based, previous code skips the 0th row.
// The RowPos and starting value for i are now zero.
//
RowPos = 0;
ColPos = 0;
for(int i=0; i<16; i++)
{
for(int j=0; j<3 ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
}
下面有三个独特的编辑。请查看所有这些内容,以便更好地了解情况以及解决问题的可能方法。
开始编辑一个
Table1::InsertStudent(string ID, string FN, string LN)
无法确保RowPos的范围为0 <= RowPos < 16
。如果添加了第17个学生,则代码将访问不存在的阵列单元格。因此,将发生访问冲突/程序崩溃/意外行为。
结束编辑一个
开始编辑两个
16
和3
的硬编码值可以替换为标题最顶部附近的用户定义的宏,以便对修改学生和/或学生详细信息的最大数量进行简单修改。例如:
#define MAX_STUDENTS 25
#define MAX_COLUMNS 8
然后在标题和cpp中,宏在当前使用16
和3
的所有地方使用。然后,循环的构造函数如下所示:
for(int i=0; i<MAX_STUDENTS; i++)
{
for(int j=0; j<MAX_COLUMNS ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
结束编辑两个
开始编辑三
在创建一个只声明Table1的本地实例的唯一main.cpp后,在for循环体中调用Table1 :: InsertStudent,然后调用Table1 :: Print,以下建议应该有助于改进并希望解决的问题。因此,在观察一起运行的打印输出之后,对Table1构造函数,InsertStudent和Print成员函数的修改如下:
Table1头文件:
#ifndef GRADE_HEADER
#define GRADE_HEADER
//
// The first two lines are not necessary and should be deleted
// Note that "std::" must be used in front of the string class
//
// #include <iostream>
// using namespace std;
#include <string>
//
// Added three user defined macros to make modifications easy and to
// to have a single location for the signaling string value to stop
// printing student details to the cout stream.
//
#define MAX_STUDENTS 16
#define MAX_COLUMNS 3
#define EMPTY_CELL "FakeNull"
class Table1
{ // added
private:
std::string Students[MAX_STUDENTS][MAX_COLUMNS];
std::string Grades[MAX_STUDENTS][MAX_COLUMNS];
int RowPos;
int ColPos;
public:
Table1();
std::string InsertStudent(std::string ID, std::string FN, std::string LN);
void Print(std::string Name);
std::string InsertGrade(std::string, std::string, std::string, std::string);
void Select(std::string, std::string, int);
void Select(std::string, std::string, std::string);
void Select(std::string, std::string, char);
void Join();
std::string Converter(int);
};
#endif
Table1 cpp源码(类实现)。流操纵器setw
用于配置输出屏幕以显示列。强烈建议您在此处查看更多详细信息:std::setw。另请参阅Stroustrup书籍的副本。请注意,#include <iomanip>
对于定义输出宽度是绝对必要的。 Print方法正文中的逗号和括号消失了。任何演示样式都是可能的,Print方法修改是一个示例,指示了一种方法。许多其他方式都是可能的。请注意,此修改集不再具有分配给第零个位置的任何固定值字符串。所有学生数据均从索引零开始,有效期至MAX_STUDENTS - 1
索引位置。
#include "Table1.h"
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
Table1::Table1()
{
//
// C++ arrays are zero based, previous code skips the 0th row.
// The RowPos and starting value for i are now zero.
//
RowPos = 0;
ColPos = 0;
//
// Initialize the MAX_STUDENTS elements to a set string, indicating
// no data present. The use of the zeroth element as string constants
// is no longer necessary.
//
for(int i=0; i < MAX_STUDENTS; i++)
{
for(int j=0; j < MAX_COLUMNS; j++)
Students[i][j] = EMPTY_CELL; // fill the array with Null value
}
}
//
// Note that sOut is an additional local variable to provide a string output
// for success or failure. The range checking is new too.
//
string Table1::InsertStudent(string ID, string FN, string LN)
{
string sOut = "Successfully added student";
//
// Must be sure the RowPos index is never beyond the last element of the
// Students array!!!
//
if (RowPos < 0 || RowPos >= MAX_STUDENTS)
{
sOut = "Students array full. Cannot add any more students";
return sOut;
}
Students[RowPos][ColPos] = ID; //Assign ID to first column
ColPos++; //Move to next column
Students[RowPos][ColPos] = FN;
ColPos++;
Students[RowPos][ColPos] = LN;
//
// Incrementing this accomplishes nothing since it is set to zero next
//
// ColPos++;
ColPos = 0;
RowPos++;
return sOut;
}
void Table1::Print(string Name)
{
if(Name == "students")
{
cout << "StudentID" << setw(15) << "FirstName" << setw(17);
cout << "LastName" << endl;
//
// It is much more efficient to declare variables outside a loop and
// not within a loop body. To promote best practices, both variables
// are declared together. The reality is that j is the one which
// should be declared outside the for loop body (or at the same time
// as this: for (int i = 0, j; ...
// Keep in mind that j always has to be set to zero to start the loop body
//
int i, j;
for(i=0; i < MAX_STUDENTS; i++)
{
j=0;
if(Students[i][j] == EMPTY_CELL)
break;
else
{ // added
cout << setw(9) << Students[i][j] << setw(15);
j++;
cout << Students[i][j] << setw(18);
j++;
cout << Students[i][j] << endl;
} // added
}
}
}
此最新版本应解决已发布的问题。希望这些建议能够促进对iomanip
助手的进一步研究,以便只有数据存储在Students数组中。用于确认打印操作的字符串值(例如"students"
)也可以成为用户定义的宏。
结束编辑三