我正在尝试编写一个程序,允许用户将数据输入到文本文件中以组织类分配。用户可以显示分配列表,在文件中输入分配,以及搜索到期的特定课程作业。我遇到一个问题,我遇到访问冲突写入位置错误,我不完全确定如何解决它。我已经查看了之前发布的讨论,但无法弄清楚我在代码中出错的地方。 这是taskList.cpp。 头文件taskList.h在它之后发布。 我正在使用VS2013。
当我调试时,错误发布在
下面的taskList.cpp文件的第55行list = new Task [capacity];
#include "taskList.h"
#include "mytools.h"
TaskList::TaskList()
{
capacity = CAP;
list = new Task[capacity];
size = 0;
}
TaskList::TaskList(char filename[])
{
capacity = CAP;
list = new Task[capacity];
size = 0;
//load from file.
ifstream inData;
Task aTask;
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
inData.open("task.txt");
if (!inData){
cout << "cannot open file";
exit(0);
}
inData.getline(tempName, MAXCHAR, ';');
while (!inData.eof())
{
inData.getline(tempDescription, MAXCHAR, '\n');
inData.getline(tempDate, MAXCHAR, '\n');
aTask.setName(tempName);
aTask.setDescription(tempDescription);
aTask.setDate(tempDate);
addTask(aTask);
inData.getline(tempName, MAXCHAR, ';');
}
inData.close();
;
TaskList::~TaskList()
{
if (list)
{
delete [] list;
list = NULL;
}
}
//Adds a video item to the list
void TaskList::addTask(Task aTask)
{
list[size++] = aTask;
}
//displays the list of videos
void TaskList::showList()
{
int i = 0;
for (i = 0; i < size; i++)
{
list[i].printTask();
}
}
void TaskList::searchList()
{
char searchName[MAXCHAR];
char tempName[MAXCHAR];
int i;
bool found = false;
cout << "Enter the name of the course to search for: ";
cin.getline(searchName, MAXCHAR);
for (i = 0; i < size; i++)
{
list[i].getName(tempName);
if (strstr(searchName, tempName) != NULL)
{
list[i].printTask();
found = true;
}
}
if (found == false)
cout << "No search results." << endl;
}
void TaskList::writeData()
{
ofstream outData;
outData.open("task.txt");
if (!outData)
{
cout << "cannot open file";
exit(0);
}
for (int i = 0; i < size; i++)
list[i].printToFile(outData);
outData.close();
}
//expand array function
void TaskList::expand()
{
char tempName[MAXCHAR];
char tempDescription[MAXCHAR];
char tempDate[MAXCHAR];
capacity += GROWTH;
Task *temp = new Task[capacity];
//copy from old array to new array
for (int i = 0; i < size; i++)
{
list[i].getName(tempName);
list[i].getDescription(tempDescription);
list[i].getDate(tempDate);
temp[i].setName(tempName);
temp[i].setDescription(tempDescription);
temp[i].setDate(tempDate);
}
//delete old array
delete [] list;
list = NULL;
//point ptr to temp
list = temp;
//set temp to NULL
temp = NULL;
}
头文件(taskList.h)
#include <iostream>
#include <fstream>
using namespace std;
const int CAP = 2;
const int GROWTH = 2;
//define class VideoList for array of Videos and its size.
class TaskList
{
private:
Task *list;
int size;
int capacity;
void expand();
public:
//constructors
TaskList();
TaskList(char filename[]);
//destructor
~TaskList();
//database functions
void addTask(Task aTask);
void showList();
void searchList();
void writeData();
};
#endif
为了确保一切都清楚,因为有3个头文件,4个源文件和一个文本文件,我包含task.h头文件和task.cpp源文件。
这是task.h:
#ifndef TASK_H
#define TASK_H
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string.h>
using namespace std;
const int MAXCHAR = 101;
class Task
{
private:
char *name;
char *description;
char *date;
public:
//defult constructor
Task();
//constructor with parameters
Task(char newName[], char newDescription[], char newDate[]);
//copy constructor
Task(const Task &otherTask);
//Accessor funct
void getName(char returnName[]);
void getDescription(char returnDescription[]);
void getDate(char returnDate[]);
//mutator function
void setName(char newName[]);
void setDescription(char newDescription[]);
void setDate(char newDate[]);
//print function to print a video
void printTask();
void printToFile(ofstream &outFile);
const Task& operator= (const Task& anItem);
};
#endif
这是task.cpp文件,不确定是否有必要但是为了清楚起见我添加它:
#include "task.h"
#include <iostream>
using namespace std;
//defult constructor
Task::Task()
{
strcpy(name, "no course name");
strcpy(description, "no task description");
strcpy(date, "no due date");
}
//constructor with parameters
Task::Task(char newName[], char newDescription[], char newDate[])
{
name = new char[strlen(newName) + 1];
description = new char[strlen(newDescription) + 1];
date = new char[strlen(newDate) + 1];
strcpy(name, newName);
strcpy(description, newDescription);
strcpy(date, newDate);
}
//copy constructor
Task::Task(const Task &otherTask)
{
//allocate memory and then copy name
this->name = new char[strlen(otherTask.name) + 1];
strcpy(name, otherTask.name);
//allocate memory and then copy description
this->description = new char[strlen(otherTask.description) + 1];
strcpy(description, otherTask.description);
//allocate memory and then copy date
this->date = new char[strlen(otherTask.date) + 1];
strcpy(date, otherTask.date);
}
//Accessor functions
void Task::getName(char returnName[])
{
strcpy(returnName, name);
}
void Task::getDescription(char returnDescription[])
{
strcpy(returnDescription, description);
}
void Task::getDate(char returnDate[])
{
strcpy(returnDate, date);
}
//mutator functions
void Task::setName(char newName[])
{
strcpy(name, newName);
}
void Task::setDescription(char newDescription[])
{
strcpy(description, newDescription);
}
void Task::setDate(char newDate[])
{
strcpy(date, newDate);
}
//prints a video item
void Task::printTask()
{
cout << name << ';' << description << ';' << date << endl;
}
void Task::printToFile(ofstream &outFile)
{
outFile << name << ';' << description << ';' << date << endl;
}
//assignment operator overloaded
const Task& Task::operator= (const Task& aTask)
{
strcpy(this->name, aTask.name);
this->description = aTask.description;
strcpy(this->description, aTask.description);
this->date = aTask.date;
strcpy(this->date, aTask.date);
return *this;
}
答案 0 :(得分:2)
问题在于:
char *name;
// ...
strcpy(name, "no course name");
第一行创建一个当前不指向任何位置的指针。然后你告诉strcpy
将该字符串复制到指针指向的位置,因此它将字符串写入&#34;无处&#34; (实际上:半随机存储器位置)。这会导致您的访问冲突。
要解决此问题,请将代码替换为:
std::string name;
// ...
name = "no course name";
对description
和date
执行相同的操作。请注意,这意味着您不需要复制构造函数或复制赋值运算符或析构函数;因为默认的行为正确。
当然你需要改变你的accssor函数(但是因为调用者不能阻止缓冲区溢出,所以它们设计得很糟糕):
std::string getName() const { return name; }
另外,将Task *list;
更改为std::vector<Task> list;
并停止使用new
和delete
。向量正确地为您管理内存。
在不使用指针或手动内存管理或C库函数(如strcpy
)的情况下执行此任务是最简单和最简单的。您将代码大小减半(至少),并且不太容易出错。
您可能需要#include <string>
和#include <vector>
。
答案 1 :(得分:0)
由于erroe在分配时发生,如果一个数组(list = new Task[capacity]
)我猜你的问题是在Task类的默认构造函数中。尝试使用这个构造函数一个liitle,我建议分配yor char数组(名称,描述和数据),以填充它们。
某些代码如name = new Char[14];
(当然其他两个代码相同)
答案 2 :(得分:0)
您未能遵守五条规则或零规则。
正确的事情(零规则)是用std::vector<Task>
来实现TaskList。
看到你的作业要求你使用动态阵列&#34;,也许他们不希望你使用std::vector
。这意味着您将无法进行手动内存管理。这意味着您需要正确实现或删除以下功能:
//You have these
TaskList::TaskList();
TaskList::TaskList(char filename[]);
TaskList::~TaskList();
//You are missing these, this is your problem:
TaskList::TaskList(TaskList const &o); //Copy constructor
TaskList &TaskList::operator=(TaskList const &o); //Copy assignment
TaskList::TaskList(TaskList &&o); //Move constructor
TaskList &TaskList::operator=(TaskList &&o); //Move assignment
如果您没有明确提供这些函数,编译器可能会自动生成它们,编译器生成的版本将不正确(对于您在TaskList
内手动管理资源的情况),因为它们会这样做成员方式移动或复制,而不是复制或移动底层资源。当您使用这些不正确的编译器生成的版本时,您的代码将有奇怪的行为。
对于Task
,您不应该同时管理多个资源。使用std::string
或以其他方式编写自己的字符串类,然后使用它来管理Task
的字符串成员。如果不这样做,您的代码几乎可以保证不正确(由于缺少异常安全性)。