C ++ Куча массив указателей на объекты, как я могу передать строку для конкретного объекта? Есть код, пожалуйста, посмотрите: - PullRequest
0 голосов
/ 26 октября 2019

Как я могу просто передать эту строку текста функции-члену? Это все, что я спрашиваю ... Есть функция-член Student: Populate (std :: string), которую я хотел бы подключить к конкретному экземпляру Student к данным определенной строки файла ... Я незнаю, как сделать это синтаксически.

это для школьного задания, поэтому я должен использовать ручное распределение новых / удалений, никаких умных указателей и векторов, поэтому просто исключаю их.

int main(){
std::stringstream stream;
std::string current;
Student temp;
Student *database = new Student[50];

inFile.open("students.dat", std::ifstream::in);
outFile.open("FullReport.txt",std::ofstream::out);

while(getline(inFile,current)){
   for(int i = 0; i < 50; i++){
        Student[i] = new Student(current); //this line doesn't work when it's compiled

        outFile << Student[i] <<std::endl; //neither does this one

       //there is a Student Populate(std::string); function I would like to pass the data to... How can I do that? 

   }
   inFile.close();
   outFile.close();
}

ОШИБКИ КОМПИЛЕРА:

ошибка: ожидаемый неквалифицированный идентификатор перед маркером '[' Student [i] = new Student (current);^ main.cpp: 26: 27: ошибка: ожидаемое первичное выражение перед маркером '[' outFile << Student [i]

Ответы [ 2 ]

2 голосов
/ 26 октября 2019

Итак, пара вещей.

Во-первых, нет Student[i]. Student это имя класса. Классы не имеют доступа к operator[], если вы не перегружаете его (возможно, будущую тему в вашем классе), и даже тогда он, вероятно, не будет статичным, а это означает, что Student[i] не имеет реального значения.

Однако существует database[i], что, вероятно, то, что вам нужно.

Во-вторых, database[i] не является указателем, поэтому нет смысла выделять с помощью new. Вы уже сделали это выше со строкой Student *database = new Student[50];, поэтому даже что-то вроде database[i] = new Student(current); бессмысленно. Вместо этого попробуйте следующее:

database[i] = Student(current);

Это назначит новый экземпляр Student на database[i]. Нет необходимости в new.

Наконец, обратите внимание, что это присвоит новый экземпляр Student для database[i], то есть вызовет конструктор. Если у вас нет конструктора, который принимает std::string, он не скомпилируется. Он также не будет вызывать Populate().

Если вы хотите вызвать Student::Populate(), для этого вам нужно вызвать его для экземпляра объекта. Вот так:

database[i].Populate(current);

Надеюсь, это то, о чем вы спрашивали.


PS Я должен также упомянуть, что по общему правилу вы не должны использовать new. Стандартная библиотека шаблонов гораздо лучше.

Конечно, большинство школьных заданий этого не позволяют, поэтому иногда вам приходится использовать new. Но, думаю, мне все же стоит упомянуть об этом.

1 голос
/ 26 октября 2019

Пойдемте, подумайте, что это бит за шагом

int main()
{   
    std::stringstream stream;

stream здесь не используется. А пока давайте избавимся от этого. Однако он вернется позже.

    std::string current;
    Student temp;
    Student *database = new Student[50];

Это создаст 50 Student с.

    inFile.open("students.dat", std::ifstream::in);
    outFile.open("FullReport.txt",std::ofstream::out);

Открывает файлы. Можно сделать немного лучше, но правильно.

    while(getline(inFile,current))
    {   

Отлично. Получил строку из файла.

        for(int i = 0; i < 50; i++)

С этой одной строкой из файла сделайте то же самое 50 раз. Спросите у резиновой утки , считает ли это, что это имеет смысл.

        {   
            Student[i] = new Student(current);

Student - это тип, а не переменная. Вы не можете хранить в типе. Скорее всего, вы должны использовать database, но это массив Student с, а new Student(current) предоставляет указатели на Student с.

            outFile << Student[i] <<std::endl;
        }
        inFile.close();
        outFile.close();

Закрытие файлов слишком рано. Вы еще не прочитали всех студентов.

    }
}

Как исправить:

int main()
{
    std::string current;
    Student **database = new Student*[50];

database - это массив из 50 указателей на Student с, все готовопринять new Student с. Но об этом позже.

    std::ifstream inFile("students.dat");
    std::ofstream outFile("FullReport.txt");

Если мы определим здесь файловые потоки и укажем направление (ifstream, ofstream), нам не нужно его указывать снова. Плюс мы можем открыть файл прямо в конструкторе. Кому нужны грязные звонки на open? Наконец, поскольку файлы являются локальными переменными, они будут автоматически уничтожены и закрыты в конце функции. Не нужно беспорядочно звонить на close. (См. Что подразумевается под Resource Acquisition под инициализацией (RAII)? , чтобы узнать больше об этой концепции). Код, который вам не нужно писать, не содержит ошибок. И если это так или иначе, они не ваша вина.

    int count = 0;

count - гораздо более описательное имя, чем i

    while (std::getline(inFile, current))
    {

, здесь ничего не изменилось. Это фантастика. Есть знаменитый вопрос о переполнении стека, который известен тем, что многие ошибаются. Престижность. Вы правильно поняли.

        database[count] = new Student(current);

новый Student выделен и добавлен в базу данных. Подробнее об этом позже.

        outFile << *database[count] << std::endl;

И записано в выходной файл. Обратите внимание на *, чтобы разыменовать указатель и получить значение, на которое он указывает, чтобы его можно было печатать с помощью обычного оператора << (который, кстати, вы должны указать). Без * программа распечатает содержимое указателя: адрес.

        count++;
    }
}

И еще раз без объяснения причин простого чтения кода

int main()
{
    std::string current;
    Student **database = new Student*[50];

    std::ifstream inFile("students.dat");
    std::ofstream outFile("FullReport.txt");

    int count = 0;

    while (std::getline(inFile, current))
    {

        database[count] = new Student(current);

        outFile << *database[count] << std::endl;

        count++;
    }
}

ОК, это позже. Вы не хотите

Student **database = new Student*[50];

Это довольно грубо по нескольким причинам.

  1. Современные компьютеры отлично умеют мыслить прямолинейно. Если данные находятся на одной прямой линии, они могут прочитать вперед и подготовить данные, прежде чем они вам понадобятся. Массивы данных потрясающие. Массивы указателя на данные не позволяют компьютеру набрать скорость. Он читает один Student, затем должен найти другой указатель, чтобы найти следующий Student. Это может быть медленно. Калеки медленно. С массивом Student с, когда вы используете Student 0, компьютер загружает (или уже загрузился, когда загрузил Student 0) следующую связку Student с.
  2. КаждыйДинамическое распределение имеет стоимость. Программа должна запросить у ОС блок памяти. ОС должна его найти. Это может быть дорого. Намного лучше получить один большой блок памяти и разделить его на массив Student с.
  3. Каждое динамическое распределение должно быть убрано. Выделите 50 Student с, и вам нужен код, который убирает 50 Student с. Выделите массив из Student s, вы уберете один массив из Students

Вы хотите что-то более похожее на

int main()
{
    std::string current;
    Student *database = new Student[50];

    std::ifstream inFile("students.dat");
    std::ofstream outFile("FullReport.txt");

    int count = 0;

    while (std::getline(inFile, current))
    {
        database[count] = Student(current);
        outFile << *database[count] << std::endl;
        count++;
    }
}

И, конечно же, вы действительно хотите

int main()
{
    std::string current;
    std::vector<Student> database;

    std::ifstream inFile("students.dat");
    std::ofstream outFile("FullReport.txt");

    while (std::getline(inFile, current))
    {
        database.emplace_back(current);
        outFile << database.back() << std::endl;
        count++;
    }
}

Но это даст хороший круглый ноль от инструктора. Первое правило школы - дать учителю то, что он хочет, и пройти курс. Второе правило - прочитайте кучу других вещей, чтобы узнать, чему вас не учили, так что вы не будете бесполезны после выпуска.

...