C ++: сбой программы при попытке печати массива const char *

У меня есть программа, в которой пользователь вводит свое имя, возраст и классы, которые он посещал. Эти классы хранятся в функции main () как двумерный массив символов, а затем передаются в функцию в классе Student, которая копирует этот массив в открытый член const char * array с именем m_CourseNames. С помощью отладчика в CLion я проверил, что этот процесс успешно завершен.

Тем не менее, я получаю exit code 11 и программа вылетает всякий раз, когда я пытаюсь перебрать массив m_CourseNames и вывести его содержимое на экран.

Я попытался распечатать массив на экране следующими способами:

  1. В основной функции:

    for (int count = 0 ; count < 9 ; count++)
    cout << student.m_CourseNames[count] << " ";
    
  2. В функции члена студенческого класса, позвонив через student.getCourses();:

    for (int count = 0 ; count < 9 ; count++)
    cout << m_CourseNames[count] << " ";
    
  3. Внутри перегруженной операторной функции с тем же методом, что и в 1) (см. Код, чтобы понять, почему я попробовал это здесь)

Все три способа вывести массив const char * на экран привели к следующему коду ошибки до завершения программы:

Если массив является публичной переменной-членом, я не знаю, почему он не будет повторяться. Отладчик проверил, что все классы правильно хранятся в нем, поэтому он не отвечает за функцию addCourses ().

См. Всю программу ниже (все, что закомментировано, является попыткой добиться вывода массива на экран):

--main.cpp--

#include <iostream>
#include "Student.h"
using namespace std;

int main()
{
char input[10][128] = {(0),(0)};
char name[128] = {0}, student_check = ' ';
int age = 0, count = 0;

cout << "\nPlease state your name and age:\n\n";
cout << "Name: ";
cin.getline(name, 128);
cout << "Age: ";
cin >> age;

cin.clear();
cin.ignore();

cout << "\n\nThanks!\n\nAre you a student? (Y/N): ";
cin.get(student_check);

switch (student_check)
{
case 'y':
case 'Y':
{
Student student;
student.setName(name);
student.setAge(age);
char course_check = ' ';
cout << "\n\nWhat course(s) are you taking?"<< " (Enter the course prefix and number without any spaces): \n\n";while (tolower(course_check) != 'n') {
cin.clear();
cin.ignore();

cout << "Course #" << count + 1 << ": ";
cin.getline(input[count], 128);
student.addCourse(input[count], count);if (student.addCourse(input[count], count))
{
cin.clear();

cout << "Do you want to enter another course? (Y/N): ";
cin.get(course_check);

count++;
}
else
{
cout << "You have exceeded the number of courses you are allowed to enter" << endl << endl;
course_check = 'n';
}
cout << student;
student.getCourses();
//for (int count = 0 ; count < 9 ; count++)
//  cout << student.m_CourseNames[count] << " ";
}}
default:
break;

}
}

--Student.h---

#ifndef PA2_STUDENT_H
#define PA2_STUDENT_H
#include "Person.h"#include <ostream>

class Student : public Person
{
public:
Student();
Student(const char* []);
bool addCourse(const char*, int);
void getCourses();
friend std::ostream& operator <<(std::ostream& os, const Student& student);
const char* m_CourseNames[10];
};

#endif

--student.cpp--
#include "Student.h"#include <iostream>

using namespace std;

Student::Student() {}

Student::Student(const char* m_CourseNames[])
{
m_CourseNames[10] = {0};
}

bool Student::addCourse(const char* course, int index)
{
if (index < 9)
{
m_CourseNames[index] = course;
return true;
}
if (index >= 9)
return false;
}

void Student::getCourses()
{
cout << ", Courses: ";
for (int count = 0 ; count < 9 ; count++)
cout << m_CourseNames[count] << " ";
}

std::ostream &operator<<(std::ostream& os, const Student& student) {
os << "Name: " << student.m_Name << ", Age: " << student.m_Age;// << ",     Courses: " << Student::m_CourseNames;

//cout << ", Courses: ";
// for (int count = 0 ; count < 9 ; count++)
// cout << m_CourseNames[count] << " ";
return os;
}

-1

Решение

Вы перебираете записи в массиве, который вы не заполнили. Вы хотите что-то вроде:

void Student::getCourses()
{
cout << ", Courses: ";
for (int count = 0 ; count < index ; count++)
cout << m_CourseNames[count] << " ";
}

Кроме того, как указал Арун, вы получаете доступ к массиву за пределами. Вы не можете получить доступ к одиннадцатому элементу массива из десяти записей, и запись 10 является одиннадцатым элементом (так как 0 является первым).

Ваш код действительно плох, хотя по многим причинам. Основная проблема заключается в том, что ваш Person тайники класса указатели к памяти он не принадлежит, что делает класс очень сложным в использовании. Почему бы не использовать std::string?

3

Другие решения

В Student::Student(const char* m_CourseNames[]), вы переступаете через массив m_CourseNames[10] = {0}; //Index is in [0..9] range

Кроме того, где вы выделяете место для массива const char * m_CourseNames указатели?

Пожалуйста, рассмотрите возможность использования std::array а также std::string вместо массива и указателей С-типа.

1

student.m_CourseNames это массив указателей на char. Это означает, что вы получите кучу указателей. У вас нет места для хранения, на которое можно указать, поэтому, если указатель не указан на какое-то действительное хранилище, программа будет запущена в сорняки. Там, кто знает, что произойдет. Может быть, найти потерянное пиратское сокровище. Возможно быть съеденным драконами. Вероятно, сбой программы.

student.m_CourseNames устанавливается student.addCourse(input[count], count); который предоставляет указатель (который будет перезаписан следующим учеником, так что это плохая идея) и индекс, по которому m_CourseNames будет обновлен. Это тоже плохая, но не фатальная идея. Одной из целей занятий является то, что они контролируют свои собственные данные, поэтому ученик должен поддерживать этот индекс.

Допустим, мы добавили три курса: A, B и C. for (int count = 0 ; count < 9 ; count++) будет пытаться напечатать 9 (индексы с 0 по 8), так что это означает, что есть не менее шести выстрелов в неопределенное поведение, чтобы вызвать сбой программы.

Решения:

Не используйте массивы символов. Используйте std :: string.

Если вам нужно использовать массивы символов, предоставьте хранилище и скопируйте источник в хранилище. Таким образом, вы знаете, что это безопасно и не будет перезаписано, если вы не захотите или не сделаете что-то глупое.

Не используйте массивы указателей. Используйте std :: vector (и для реальных данных, а не для указателей на данные). Вектор изменяется по мере добавления и всегда знает, сколько элементов в нем содержится. Если вы не можете использовать векторы, используйте массивы, но не массивы указателей. Если возможно, используйте массивы std :: string.

Следите за количеством элементов, хранящихся в ваших списках, чтобы вы не выходили за пределы. Вектор делает это для вас.

Инкапсулируйте данные вашего класса. Студент должен знать все вещи и управлять ими. Никто не должен говорить Студенту, где его курсы, только что у него есть курсы. Если вы хотите распечатать данные ученика, попросите ученика распечатать их для вас.

1
По вопросам рекламы [email protected]