0

我知道我只是错过了一些愚蠢的东西,但我很沮丧,我只是看不到它。当我针对其中包含 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;
}
4

1 回答 1

4

CourseName, TaskDescription,DueDate都指向循环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,以便strcpy对数组的 Task 对象内的字符串完成。并且strtok也在这个字符串上被调用

  4. 改变

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

    while(inFile) {
    
  5. 已移除

    inFile.ignore(UINT_MAX, NEWLINE);
    

固定代码

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;
  }
};

很明显,如果你用 inC++而不是用C inside classes.

于 2013-04-28T06:21:16.477 回答