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

Поиск:

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


Шустрый
*


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

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



Здравствуйте!
Есть некоторый класс:
Код

class Videotape {
private:
    int nomer;
    char *nazvanie;
    char *regisser;
    char *kinokompaniya;
    int year;
    char *producer;
    char *annotation;
public:
    Videotape();
    ~Videotape();
    const int getNomer();
    const char * getNazvanie();
    const char * getRegisser();
    const char * getKinokompaniya();
    const int getYear();
    const char * getProducer();
    const char * getAnnotation();
    void parse(char *str);
};

И есть массив из объектов данного класса:
Код

int n = 7;
Videotape *tapes = new Videotape[n];
// далее массив заполняется данными

Как мне пройти по этому массиву, используя указатель на его первый элемент?
Т.е. сделать так, как работает, например, с массивом чисел типа double:
Код

    double *gfg = new double[3];
    gfg[0] = 1;
    gfg[1] = 2;
    gfg[2] = 3;
    gfg++;
    // Здесь gfg будет указывать на элемент, равный двум

Я пытаюсь делать так...
Код

tapes += sizeof(tapes[0]); // sizeof(tapes[0]) == 28

но тогда tapes указывает на какую-то чушь, а не на второй элемент
PM MAIL   Вверх
azesmcar
Дата 14.12.2009, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Цитата(aspirin2003 @  14.12.2009,  17:02 Найти цитируемый пост)
но тогда tapes указывает на какую-то чушь, а не на второй элемент 

также как и в случае с double. Почитай про арифметические операции с указателями.
Код

(tapes++)->parse("");


Добавлено через 1 минуту и 49 секунд
читай
http://www.viva64.com/terminology/Address_...hmetic_rus.html
Цитата

Согласно стандартам языка Си и Си++, при арифметике с указателями, результирующий адрес должен оставаться строго на границе единичного объекта массива (или следовать сразу за ним). Сложение или вычитание указателя сдвигает его на величину, кратную размеру того типа данных, на который он указывает. Пример. Пусть есть указатель на массив 4-байтных целых. Инкремент этого указателя приведет к увеличению его значения на 4 (размер элемента). Такой эффект часто используется для увеличения указателя для того, чтобы он указывал на следующий элемент в смежном массиве целых чисел.

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


Шустрый
*


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

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



Пока не понял, почему работает такой вариант:
Код

int mynum = (tapes++)->getNomer(); 

и не работает такой:
Код

tapes++;
int mynum = tapes->getNomer(); 


PM MAIL   Вверх
djamshud
Дата 14.12.2009, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

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



Про арифметику прочитали? Теперь читайте про постфиксный и префиксный инкремент.smile

Проблема в том, что types однажды вылазит из рамок массива или "tapes->getNomer()" обращается по левому адресу.

Это сообщение отредактировал(а) djamshud - 14.12.2009, 17:48


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
aspirin2003
Дата 14.12.2009, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(djamshud @ 14.12.2009,  17:46)
Про арифметику прочитали? Теперь читайте про постфиксный и префиксный инкремент.smile

Проблема в том, что types однажды вылазит из рамок массива или "tapes->getNomer()" обращается по левому адресу.

Про инкремент я в курсе, просто не увидел, что (tapes++)->getNomer() возвращает значение из первого элемента, а не из второго
Вопрос в том почему это не работает:
Код

tapes++;
int mynum = tapes->getNomer();

Я понимаю, что что-то где-то вылазит за рамки массива, но как сделать правильно тогда?
PM MAIL   Вверх
djamshud
Дата 14.12.2009, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

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



Videotape *tmp=tapes++;
tmp->...

И вообще вы пытаетесь изменить изначально правильный вариант.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
aspirin2003
Дата 15.12.2009, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(djamshud @ 14.12.2009,  19:58)
Videotape *tmp=tapes++;
tmp->...

И вообще вы пытаетесь изменить изначально правильный вариант.

Вы сами с инкрементом напутали,
Код

Videotape *tmp=tapes++;

в tmp будет указатель на первый элемент, а нужен на второй.
Вопрос по прежнему не решен...

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


uploading...
****


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

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



Цитата(aspirin2003 @  15.12.2009,  09:39 Найти цитируемый пост)
Вопрос по прежнему не решен...

какой вопрос?

Цитата(aspirin2003 @  14.12.2009,  17:02 Найти цитируемый пост)
Как мне пройти по этому массиву, используя указатель на его первый элемент?

Цитата(azesmcar @  14.12.2009,  17:07 Найти цитируемый пост)
также как и в случае с double



Цитата(aspirin2003 @  14.12.2009,  17:31 Найти цитируемый пост)
Пока не понял, почему работает такой вариант:
int mynum = (tapes++)->getNomer(); 

и не работает такой:
tapes++;
int mynum = tapes->getNomer(); 


потому что это разные вещи. Почему
Код

int i = 0;
std::cout << i++ << std::endl;

выведет 0 а
Код

int i = 0;
i++;
std::cout << i << std::endl;

единицу? ответ был дан выше

Цитата(djamshud @  14.12.2009,  17:46 Найти цитируемый пост)
читайте про постфиксный и префиксный инкремент


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


Шустрый
*


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

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



Зачем Вы мне про инкремент рассказываете? Я в курсе что это такое и как работает i++ и ++i
Вопрос - почему не работает
Код

tapes++;
int mynum = tapes->getNomer();

По идее после выполнения tapes++   tapes должен указывать на второй элемент, а указывает на какую-то фигню
PM MAIL   Вверх
djamshud
Дата 15.12.2009, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

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



>Вы сами с инкрементом напутали,

Нет, все правильно. Приведенный мной пример идентичен (someptr++)->somefnc();

Добавлено @ 10:42
>По идее после выполнения tapes++   tapes должен указывать на второй элемент, а указывает на какую-то фигню 

Он и указывает на второй элемент. А там может не быть валидного объекта.

Это сообщение отредактировал(а) djamshud - 15.12.2009, 10:43


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
azesmcar
Дата 15.12.2009, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



aspirin2003

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


Шустрый
*


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

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



Не знаю, чем это поможет...
main.h
Код

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <iostream>
#include <math.h>

class Videotape {
private:
    int nomer;
    char *nazvanie;
    char *regisser;
    char *kinokompaniya;
    int year;
    char *producer;
    char *annotation;
public:
    Videotape();
    ~Videotape();
    const int getNomer();
    const char * getNazvanie();
    const char * getRegisser();
    const char * getKinokompaniya();
    const int getYear();
    const char * getProducer();
    const char * getAnnotation();
    void parse(char *str);
};

main.cpp
Код

#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);
    }
    //int y = sizeof(tapes[0]);
    //tapes += sizeof(tapes[0]);
    tapes++;
    int mynum = tmp->getNomer(); 

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

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

Videotape::Videotape()
{
    // Выделяем память под поля класса
    nazvanie = new char[255];
    regisser = new char[50];
    kinokompaniya = new char[50];
    producer = new char[50];
    annotation = 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;
}


Добавлено через 2 минуты и 56 секунд
Цитата(djamshud @ 15.12.2009,  10:41)
>Вы сами с инкрементом напутали,

Нет, все правильно. Приведенный мной пример идентичен (someptr++)->somefnc();


Videotape *tmp=tapes++;
tmp->...

никак не может указывать на второй элемент. Я не поленился и проверил, хотя это и так очевидно, что ++ выполнится только после присваивания, и в tmp будет указатель на первый элемент

Добавлено через 4 минуты и 38 секунд
Естесственно не 
Код

tapes++;
    int mynum = tmp->getNomer();

а 
Код

tapes++;
    int mynum = tapes->getNomer();

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


uploading...
****


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

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



Цитата(aspirin2003 @  15.12.2009,  11:15 Найти цитируемый пост)
Не знаю, чем это поможет...

чем то да поможет.

вот ошибка
Код

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

ты все время заливаешь информацию в первый объект, ну а используешь второй.
PM   Вверх
xvr
Дата 15.12.2009, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



В коде КУЧА ошибок (но не с 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


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


Шустрый
*


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

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



Цитата(azesmcar @ 15.12.2009,  11:34)
Цитата(aspirin2003 @  15.12.2009,  11:15 Найти цитируемый пост)
Не знаю, чем это поможет...

чем то да поможет.

вот ошибка
Код

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

ты все время заливаешь информацию в первый объект, ну а используешь второй.

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

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

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

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

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


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

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


 




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


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

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