方法返回后内存被破坏

时间:2013-04-28 06:06:15

标签: c++

我知道我只是错过了一些愚蠢的东西,但我很沮丧,我只是看不到它。当我针对其中包含3个字段的文件运行以下代码“field1; field2; field3”时,任务将在retrieveTasks方法中正确打印出来。当该方法返回main时,输出已损坏。我知道这是愚蠢的,我只是想念它。我已经尝试将CourseName,TaskDescription等更改为数组而不是char *。我已经尝试将fileString作为char *传递,我已尝试使用strcpy而没有。有人能指出我的方向吗?

const int MAX_STRING_LENGTH = 101;
const int MAX_TASK_ITEMS = 255;
const char NEWLINE = '\n';
const char DELIMETER[] = ";";
const char FILENAME[] = "tasks.txt";

struct Task {
  char* CourseName;
  char* TaskDescription;
  char* DueDate;
  char FileString[300];

  void printTask() {
    cout << CourseName << DELIMETER << TaskDescription << DELIMETER  << DueDate << endl;
  }

  void initializeFromFileString(char fileString[]) {
    strcpy(FileString, fileString);
    CourseName = strtok(FileString, DELIMETER);
    TaskDescription = strtok(NULL, DELIMETER);
    DueDate = strtok(NULL, DELIMETER);
  }
};

struct TaskList {
  Task Tasks[MAX_TASK_ITEMS];
  int TaskCount;

  void initialize() {
    TaskCount = 0;

    return;
  }

  void addTask(Task task) {
    Tasks[TaskCount] = task;
    TaskCount++;

    return;
  }

  void printTasks() {
    for(int TaskNum = 0; TaskNum < TaskCount; TaskNum++) {
      cout << TaskNum + 1 << ".      ";
      Tasks[TaskNum].printTask();
      cout << endl;
    }

    return;
  }

  // Load data from the file. Will return -1 if it fails for any reason.
  // Otherwise it returns the number of records read.
  int retrieveTasks(const char* fileName) {
    int isSuccessfulOpen = 0;
    int recordsRead = 0;
    ifstream inFile;

    isSuccessfulOpen = openFile(inFile, fileName);

    if(!isSuccessfulOpen) {
      return -1;
    }

    // Read input file and store in appropriate arrays
    while(inFile.eof() == false) {
      char fileLine[MAX_STRING_LENGTH * 3];
      Task task;

      inFile.getline(fileLine, MAX_STRING_LENGTH * 3, NEWLINE);
      inFile.ignore(UINT_MAX, NEWLINE);
      task.initializeFromFileString(fileLine);
      addTask(task);
      recordsRead++;
    }
    inFile.close();

    return recordsRead;
  }
};

int main() {
  bool isFinished = false;
  TaskList taskList;

  taskList.initialize();
  taskList.retrieveTasks(FILENAME);
  taskList.printTasks();

  return 0;
}



int openFile(ifstream& inFile, const char* fileName) {
  inFile.open(fileName);

  // Veryify that the file is valid. If not print error message.
  if(inFile.is_open() == false) {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }

  return 1;
}

// Open file for writing
int openFile(ofstream& outFile, const char* fileName) {
  outFile.open(fileName);

  // Veryify that the file is valid. If not print error message and exit.
  if(outFile.is_open() == false)
  {
    cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
    return 0;
  }

  return 1;
}

1 个答案:

答案 0 :(得分:4)

CourseNameTaskDescriptionDueDate都指向task循环内创建的while对象中存在的数组中的内存。由于此task对象是本地范围,因此在retrieveTasks执行完毕后它们包含垃圾。

需要更改

  1. 您的TaskCount总是比计数多一个 - 因此需要减少1个。

    for(int TaskNum = 0; TaskNum < TaskCount; TaskNum++) {
    

    更改为

    for(int TaskNum = 0; TaskNum < TaskCount -1 ; TaskNum++) {
    
  2. 从while循环中删除了Task对象。

  3. AddTask采用char *而不是Task。 AddTask调用initializeFromFileString,以便对数组的Task对象内的字符串执行strcpy。此字符串也会调用strtok

  4. 更改

    while(inFile.eof() == false) {
    

    while(inFile) {
    
  5. 删除

    inFile.ignore(UINT_MAX, NEWLINE);
    
  6. 固定代码

    struct Task {
      char* CourseName;
      char* TaskDescription;
      char* DueDate;
      char FileString[300];
    
      void printTask() {
        cout << CourseName << DELIMETER << TaskDescription << DELIMETER  << DueDate << endl;
      }
    
      void initializeFromFileString(char fileString[]) {
        strcpy(FileString, fileString);
        CourseName = strtok(FileString, DELIMETER);
        TaskDescription = strtok(NULL, DELIMETER);
        DueDate = strtok(NULL, DELIMETER);
      }
    
    };
    
    
    
    int openFile(ifstream& inFile, const char* fileName) {
      inFile.open(fileName);
    
      // Veryify that the file is valid. If not print error message.
      if(inFile.is_open() == false) {
        cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
        return 0;
      }
    
      return 1;
    }
    
    // Open file for writing
    int openFile(ofstream& outFile, const char* fileName) {
      outFile.open(fileName);
    
      // Veryify that the file is valid. If not print error message and exit.
      if(outFile.is_open() == false)
      {
        cout << "File " << fileName << " does not exist. Please provide a valid file path." << endl;
        return 0;
      }
    
      return 1;
    }
    
    struct TaskList {
      Task Tasks[MAX_TASK_ITEMS];
      int TaskCount;
    
      void initialize() {
        TaskCount = 0;
    
        return;
      }
    
      void addTask(char * t) {
        Tasks[TaskCount].initializeFromFileString(t);
        TaskCount++;
    
        return;
      }
    
      void printTasks() {
        for(int TaskNum = 0; TaskNum < TaskCount - 1; TaskNum++) {
          cout << TaskNum + 1 << ".      ";
          Tasks[TaskNum].printTask();
          cout << endl;
        }
    
        return;
      }
    
      // Load data from the file. Will return -1 if it fails for any reason.
      // Otherwise it returns the number of records read.
      int retrieveTasks(const char* fileName) {
        int isSuccessfulOpen = 0;
        int recordsRead = 0;
        ifstream inFile;
    
        isSuccessfulOpen = openFile(inFile, fileName);
    
        if(!isSuccessfulOpen) {
          return -1;
        }
    
        // Read input file and store in appropriate arrays
        while(inFile) {
          char fileLine[MAX_STRING_LENGTH * 3];
    
          inFile.getline(fileLine, MAX_STRING_LENGTH * 3, NEWLINE);
    
          addTask(fileLine);
            printTasks();
    
          recordsRead++;
        }
        inFile.close();
    
        return recordsRead;
      }
    };
    

    很明显,如果你在C++中编写它而不是在C inside classes中编写它,整个程序会更简单,更不容易出错。