Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проход по массиву объектов 
:(
    Опции темы
aspirin2003
Дата 15.12.2009, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 111
Регистрация: 18.3.2007
Где: Саратов

Репутация: нет
Всего: нет



Цитата(xvr @ 15.12.2009,  11:34)
В коде КУЧА ошибок (но не с tapes++)
Код


int main(int argc, char *argv[])
{

    char *str = new char[1024]; <<< *2

    // Счетчик цикла
    int i = 0;
    // Цикл "пока в потоке есть данные"
    while(file.good())
    {
        // Читаем из потока одну строку и записываем ее в str.
        // Если в строке больше чем 1024 символа, она обрезается до 1024
        file.getline(str, 1024);
        tapes[i].parse(str);
    }
!!! Баг №1 - i в цикле не инкрементируется - все данные будут сложенны в tapes[0]

    tapes++; // <<< *1

    // Освобождаем память, выделенную под массив из n объектов
    delete [] tapes;
!!! Баг №2 - Указатель tapes передвинут на 2й элемент массива, который вернул new. Делать к нему delete нельзя (см *1)
    return 0;
}

Videotape::Videotape()
{
    // Выделяем память под поля класса
    nazvanie = new char[255];
    regisser = new char[50];
    kinokompaniya = new char[50];
    producer = new char[50];
    annotation = new char[255];
}
!!! Баг №3 - Поле nomer не проинициализированно, а вы его пытаетесь печатать (после tapes++)

void Videotape::parse(char *str)
{
    // Разбиваем переданную сюда строку по разделителю
    // и записываем полученные подстроки в соответствующие поля класса
    nomer = atoi(strtok(str, "::"));
    nazvanie = strtok(NULL, "::");
    regisser = strtok(NULL, "::");
    kinokompaniya = strtok(NULL, "::");
    year = atoi(strtok(NULL, "::"));
    producer = strtok(NULL, "::");
    annotation = strtok(NULL, "::");
}
!!! Баг № 4 и 5 - Все поля, выделенные через new char[] переписанны значениями из strtok, которые в свою очередь указывают на один и тот же буфер, выделенные с помощью new char [] в main (*2).
Итого - memory leak + все экземпляры Videotape ссылаются на одну и ту же строку (которую многократно переписали в main)

Videotape::~Videotape()
{
    // Освобождаем память
    delete nazvanie;
    delete regisser;
    delete kinokompaniya;
    delete producer;
    delete annotation;
}
!!! Баг №6 (следствие бага №5) - делать delete для этих указателей нельзя - они все ссылаются на внутренности *2 из main

Как тогда сделать правильно, подскажите, пожалуйста. Что еще нужно тут изменить?
Код

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include "main.h"

using namespace std;

int main(int argc, char *argv[])
{
    // По заданию число сортируемых элементов, т.е. строк в файле, заранее известно.
    // Будем хранить это значение в переменной n
    int n = 7;
    // Создаем новую переменную, которая будет хранить текущую прочитанную из файла строку
    // и выделяем под нее 1024 байта
    char *str = new char[1024];
    // Создаем указатель на массив объектов типа Videotape, и выделяем память под n элементов
    Videotape *tapes = new Videotape[n];
    // Создаем новый поток, который открывает файл на чтение
    ifstream file("data.txt", ios::in);
    // Если файла нет, или его не удалось открыть, выводим ошибку
    if (!file)
        cout << "Can't open file!\n";
    // Счетчик цикла
    int i = 0;
    // Цикл "пока в потоке есть данные"
    while(file.good())
    {
        // Читаем из потока одну строку и записываем ее в str.
        // Если в строке больше чем 1024 символа, она обрезается до 1024
        file.getline(str, 1024);
        tapes[i].parse(str);
        i++;
    }
    //int y = sizeof(tapes[0]);
    //tapes += sizeof(tapes[0]);
    //tapes++;
    //int mynum = tapes[0].getNomer(); 

    //MergeSort(tapes, n);
    // Закрываем поток и освобождаем выделенные ресурсы
    file.close();

    getch();
    // Освобождаем память, выделенную под массив из n объектов
    delete [] tapes;
    return 0;
}

Videotape::Videotape()
{
    nomer = 0;
    year = 0;
    // Выделяем память под поля класса
    nazvanie = NULL;//new char[255];
    regisser = NULL;//new char[50];
    kinokompaniya = NULL;//new char[50];
    producer = NULL;//new char[50];
    annotation = NULL;//new char[255];
}

Videotape::~Videotape()
{
    // Освобождаем память
    delete nazvanie;
    delete regisser;
    delete kinokompaniya;
    delete producer;
    delete annotation;
}

void Videotape::parse(char *str)
{
    // Разбиваем переданную сюда строку по разделителю
    // и записываем полученные подстроки в соответствующие поля класса
    nomer = atoi(strtok(str, "::"));
    nazvanie = strtok(NULL, "::");
    regisser = strtok(NULL, "::");
    kinokompaniya = strtok(NULL, "::");
    year = atoi(strtok(NULL, "::"));
    producer = strtok(NULL, "::");
    annotation = strtok(NULL, "::");
}

const int Videotape::getNomer()
{
    return this->nomer;
}

PM MAIL   Вверх
xvr
Дата 15.12.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата

Что еще нужно тут изменить?

Все ??? = strtok(NULL, "::"); поменять на strcpy(???,strtok(NULL, "::")); (а еще лучше на strncpy, что бы переполнения строк не произошло)

В Videotape::Videotape() для этих полей оставить new char[]

А еще лучше воспользоваться std::string

PM MAIL   Вверх
aspirin2003
Дата 15.12.2009, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 111
Регистрация: 18.3.2007
Где: Саратов

Репутация: нет
Всего: нет



Еще один вопрос почему если после этого куска кода
Код

  Videotape *tapes1 = new Videotape[n];
  for(int i=0; i<n; i++)
    tapes1[i]=tapes[i];

написать delete[n] tapes;  то в tapes1 тоже получается какая-то фигня? Вроде же копируются значения а не указатели
PM MAIL   Вверх
mes
Дата 15.12.2009, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(aspirin2003 @  15.12.2009,  14:38 Найти цитируемый пост)
 то в tapes1 тоже получается какая-то фигня? Вроде же копируются значения а не указатели 

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



Это сообщение отредактировал(а) mes - 15.12.2009, 16:30


--------------------
PM MAIL WWW   Вверх
bsa
Дата 16.12.2009, 01:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



aspirin2003, забудь о new/delete, используй std::vector, std::string и прочее из STL. Чтобы этим пользоваться нужно меньше книжек читать.  smile 
PM   Вверх
aspirin2003
Дата 16.12.2009, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 111
Регистрация: 18.3.2007
Где: Саратов

Репутация: нет
Всего: нет



Цитата(mes @ 15.12.2009,  16:29)
а Вы определили (правильный) конструктор копирования ? Т.к как если среди дата членов есть указатели, то по умолчанию они (указатели, а не то, на что они указывают) просто копируются,
в результате получается что разные объекты ссылаются на один участок памяти, и при удалении одного из объектов,  указатели второго считаются невалидными.

Именно так, спасибо!

Добавлено через 44 секунды
Цитата(bsa @ 16.12.2009,  01:10)
aspirin2003, забудь о new/delete, используй std::vector, std::string и прочее из STL. Чтобы этим пользоваться нужно меньше книжек читать.  smile

С STL все конечно гораздо проще но задание было сделать по возможности без STL.

Добавлено через 1 минуту и 51 секунду
Книжки читать полезнее smile
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0851 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.