0

ばかげたことを見逃していることはわかっていますが、それが見えないほどイライラしています。「field1;field2;field3」という 3 つのフィールドを持つファイルに対して以下のコードを実行すると、タスクが retrieveTasks メソッドで正しく出力されます。メソッドがメインに戻ると、出力が壊れています。私はそれがばかげていることを知っています、そして私はそれが恋しいだけです。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

CourseNameTaskDescription、すべてループ内で作成されたオブジェクトDueDateに存在する配列内のメモリを指します。このオブジェクトはローカル スコープであるため、実行が完了するとガベージが含まれます。taskwhiletaskretrieveTasks

必要な変更

  1. TaskCount は常にカウントよりも 1 つ多いため、これを 1 減らす必要があります。

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

    に変更

    for(int TaskNum = 0; TaskNum < TaskCount -1 ; TaskNum++) {
    
  2. while ループから Task オブジェクトを削除しました。

  3. AddTaskTask の代わりに char * を取ります。配列の Task オブジェクト内の文字列に対して実行されるようにAddTask呼び出します。そして、この文字列でも呼び出されますinitializeFromFileStringstrcpystrtok

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

C++明らかに、このプログラム全体は、 で記述する代わりに で記述した方が、はるかに単純でエラーが発生しにくくなりますC inside classes

于 2013-04-28T06:21:16.477 に答える