Динамический массив для чайников.
От: shvellerr Россия  
Дата: 10.02.08 21:27
Оценка:
Доброго всем времени суток. Извиняюсь заранее если чегото не так сказал.
В общем есь такая проблемка. Я только начинаю учить С++ читаю книжку дошел до динамических массивов вроде разобрался написал такой код (почти как в книжке) он работает но странно
программа должна выделять место под строки.

#include <iostream.h>
void main ()
{
    int dd,ss;
    cout << "Введите КОЛИЧЕСТВО строк массива" << endl;
    cin >> dd;
    cout << "Введите РАЗМЕР строки массива" << endl;
    cin >> ss;
    char **a; // Указатель указатель на
    a = new char *[dd];  // А содержит адрес массива строк [dd]
    if (a==0)
        {
        cout << "массив адресов не создан" << endl;
                delete []a; // удаляем массив указателей
        return;   // конец :)
        }
        for (int c=0; c<dd; ++c)
             {
             //a[c]=new char [ss];     // каждый элемнт массива [dd] содержит адрес строки
              *(a+c)=new char [ss];
             // (a+c) или a[c]обязательно                                   (массива) [ss] 
            if ((a+c)==0) // ПРоверка на создание строки        
            {             // проверяется адрес (а+с) без * !!!
            cout << "строка не создана" << endl;
                    delete []a;
            cout << "массив адресов удален" << endl;
            return;
            }
                
             }
         cout << "\nМАССИВ СОЗДАН\n\n...Заполнение массива...." << endl;
     // заполнение массива
     int v;
     for (c=0; c<dd; ++c)
        { 
         for (v=0; v<ss; ++v)
            {  
            a[c][v]='!';
            //*(*(a+c)+v)='!';
            }
        }
     cout << "Введите любую букву(режим паузы)" << endl;
         char tt;
     cin >> tt;

      // удаление массива
     for (c=0; c<dd; ++c)
        {
        delete a[c];
        }
        cout << "Строки удалены" << endl;
        delete []a;
             a=0;
        cout << "указатель удален" << endl;

  } //  это конец!

почти как в книжке... запускается нормально но работает со странностями при маленьких массивах работает вроде нормально к примеру 100 на 100..
при средних происходят сбои и ошибки например 6000 на 300
при больших или работает или происходит ошибка(**** вызвало ошибку защиты в модуле ****).
причем выделение памяти нестабильно может не выделить память для меньшего массива и выделить для большего про ограничение размеров массивов я ничего не нашел. Есть ли ограничения для динамических массвов? Есть ли какието правила для их создания? Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?
Re: Динамический массив для чайников.
От: alexeiz  
Дата: 10.02.08 22:13
Оценка: +5
Здравствуйте, shvellerr, Вы писали:

S>Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?


Самое первое, что можно посоветовать, — выкинь borland 3.1 нафиг. Ему уже 20 лед в обед. Ты скорее поколечишь им себя, чем чему-то научишься. Возьми современную среду, например, visual c++ express.

Да, и книжку, по которой ты учишься, выкинь тоже. Сдается мне, что она не намного моложе твоего borland'а. По твоему коду видно, что это в лучшем случае C++ circa конца 80-х, который не имеет никакого смысла в настоящее время.
Re: Динамический массив для чайников.
От: Erop Россия  
Дата: 10.02.08 23:14
Оценка: +2
Здравствуйте, shvellerr, Вы писали:


S>причем выделение памяти нестабильно может не выделить память для меньшего массива и выделить для большего про ограничение размеров массивов я ничего не нашел. Есть ли ограничения для динамических массвов? Есть ли какието правила для их создания? Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?


1) По крайней мере в строке
           if ((a+c)==0) // ПРоверка на создание строки        
            {             // проверяется адрес (а+с) без * !!!
ошибка.

a+c никогда не должно равняться 0! потому что это всё ещё указатель на указатель.
на 0 надо проверять a[c] или *(a+c), как у тебя везде написано.
На самом деле писать с квадратными скобочками намного понятнее. Лучше используй такую форму записи.

2) Вообще-то в BC 3.1 кажется ещё 16-битный код был. Соответсвенно оно компилировало не для плоской памяти, а для сегментной. Кроме того там, кажется, были модели памяти. Это набор соглашений, предписывающий ту или иную стратегию работы с указателями. Если у тебя какая-нибудь небольшая модель памяти (например small), то у тебя на всю кучу есть всего 65 килобайт памяти. Неудивительно, что у тебя её не хватает на таблицу 6000 х 300.
В целом присоединяюсь к совету взять какой-нибудь С++ поновее. Хотя бы MS VC 6.0 Там STL конечно архаичный очень, но С++ более или менее актуальный, да и отлаживаться проще будет.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Динамический массив для чайников.
От: shvonder Россия  
Дата: 11.02.08 00:21
Оценка: 1 (1)
Здравствуйте, shvellerr, Вы писали:

S>
S>#include <iostream.h>         //рекомендуется <iostream>
S>void main ()                     // Привет C!  Нужно int main(int argc,char * argv[]);
S>{
S>    int dd,ss;
    [..]
S>    char **a; 
S>    a = new char *[dd];  
S>    if (a==0)  //на многих компилчторах будет не0, а выброситься исключение bad_alloc 
S>        {
S>                delete []a; // Зачем удалять нулевой указатель ?
S>        return;   
S>        }
S>        for (int c=0; c<dd; ++c)
S>             {
S>              *(a+c)=new char [ss];
S>            if ((a+c)==0)   //как отметили выше, видимо имелось ввиду *(a+с)==0
S>            {             
S>                    delete []a;  //а кто будет удалять те элементы, которые создалиясь удачно ?
S>            return;
S>            }
S>     int v;
S>     for (c=0; c<dd; ++c)   //современные компиляторы не должны  компилировать, т.к. "c" нигде не объявлен
S>        { 
S>         for (v=0; v<ss; ++v)
S>            {  
S>            a[c][v]='!';
S>            }
S>        }
S>     for (c=0; c<dd; ++c)
S>        {
S>        delete a[c];//<-- ошибка ! нужно delete[] a[c], тк выделена new[]
S>        }
S>        delete []a;
S>             a=0;//необязательно
S>
S>  } 
 
S>


А книжка и компилятор действительно старые: так уже писать уже не модно
Re[2]: Динамический массив для чайников.
От: Erop Россия  
Дата: 11.02.08 00:27
Оценка:
Здравствуйте, shvonder, Вы писали:

S>>
S>>        delete a[c];//<-- ошибка ! нужно delete[] a[c], тк выделена new[]
S>

Конечно ошибка, но я не помню про BC 3.1 как там всё было. Мне кажется, что для POD пофиг было какой delete звать.
Так что падать должно из-за чего-то другого

S>А книжка и компилятор действительно старые: так уже писать уже не модно

Главное, что и запускать такие программы непросто
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Динамический массив для чайников.
От: BlackKite Украина www.os-it.com
Дата: 11.02.08 11:07
Оценка:
Здравствуйте, shvellerr, Вы писали:

S>Доброго всем времени суток. Извиняюсь заранее если чегото не так сказал.

S>В общем есь такая проблемка. Я только начинаю учить С++ читаю книжку дошел до динамических массивов вроде разобрался написал такой код (почти как в книжке) он работает но странно
S>программа должна выделять место под строки.

S>S>почти как в книжке... запускается нормально но работает со странностями при маленьких массивах работает вроде нормально к примеру 100 на 100..

S>при средних происходят сбои и ошибки например 6000 на 300
S>при больших или работает или происходит ошибка(**** вызвало ошибку защиты в модуле ****).
S>причем выделение памяти нестабильно может не выделить память для меньшего массива и выделить для большего про ограничение размеров массивов я ничего не нашел. Есть ли ограничения для динамических массвов? Есть ли какието правила для их создания? Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?


Да, ограничения есть. Смотри модели памяти (параметры компиляции) и far указатели. Скорее всего у тебя размер массива ограничен в 64к, от этого и такие проблемы.
Re[2]: Динамический массив для чайников.
От: Аноним  
Дата: 11.02.08 15:09
Оценка:
Здравствуйте, shvonder, Вы писали:

S>А книжка и компилятор действительно старые: так уже писать уже не модно


А как грамотно переписать эту программу в современном стиле?
Re[3]: Динамический массив для чайников.
От: shvonder Россия  
Дата: 11.02.08 17:11
Оценка:
Здравствуйте, Аноним, Вы писали:
А>А как грамотно переписать эту программу в современном стиле?
Проблема в том, что она ничего не делает, кроме демонстрации работы с памятью в старом стиле C, а это уже моветон Если считать, что задача программы — залить строки символом '!' при помощи доступа к индивидуалтному элементу, то как-то так:
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
   try{
        int str_cnt = 1000;
        int str_len = 10000;
        vector<string > v(str_len);
        for(int i = 0; i < str_cnt;++i){
            v[i].resize(str_len);
            for(int j = 0; j < v[i].size();++j)
               v[i][j] = '!';//доступ к отдельному элементу    
            }
   }catch(exception & e){
       cout << "Error with message:";
       cout <<e.what();
   };
   return 0;
}
Re[4]: Динамический массив для чайников.
От: Аноним  
Дата: 12.02.08 06:29
Оценка: :)
Здравствуйте, shvonder, Вы писали:

S>Здравствуйте, Аноним, Вы писали:

А>>А как грамотно переписать эту программу в современном стиле?
S>Проблема в том, что она ничего не делает, кроме демонстрации работы с памятью в старом стиле C, а это уже моветон

А, ну это понятно. А то я испугался что cin, cout использовать не модно. )
Re[4]: Динамический массив для чайников.
От: rg45 СССР  
Дата: 13.02.08 08:38
Оценка: +1
Здравствуйте, shvonder, Вы писали:

S>Здравствуйте, Аноним, Вы писали:

А>>А как грамотно переписать эту программу в современном стиле?
S>Проблема в том, что она ничего не делает...
Точно-Точно. Грамотно и в современном стиле ЭТУ программу можно переписать так:
int main()
{
}


S>Если считать, что задача программы — залить строки символом '!' при помощи доступа к индивидуалтному элементу, то как-то так:

S>
S>#include <iostream>
S>#include <stdexcept>
S>#include <string>
S>#include <vector>
S>using namespace std;
S>int main(int argc, char* argv[])
S>{
S>   try{
S>        int str_cnt = 1000;
S>        int str_len = 10000;
S>        vector<string > v(str_len);
S>        for(int i = 0; i < str_cnt;++i){
S>            v[i].resize(str_len);
S>            for(int j = 0; j < v[i].size();++j)
S>               v[i][j] = '!';//доступ к отдельному элементу    
S>            }
S>   }catch(exception & e){
S>       cout << "Error with message:";
S>       cout <<e.what();
S>   };
S>   return 0;
S>}
S>

А почему бы здесь сразу не создать вектор строк в конечном виде?:
vector<string> v(str_cnt, string(str_len, '!'));

В этом примере не совсем понятно, для чего понадобился именно поэлементный доступ с двумя циклами. Как бы доступ ради доступа.
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: Динамический массив для чайников.
От: shvonder Россия  
Дата: 13.02.08 14:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, shvonder, Вы писали:

R>А почему бы здесь сразу не создать вектор строк в конечном виде?:
R>
R>vector<string> v(str_cnt, string(str_len, '!'));
R>

R>В этом примере не совсем понятно, для чего понадобился именно поэлементный доступ с двумя циклами. Как бы доступ ради доступа.

Я же ясно написал:
S>>Если считать, что задача программы — залить строки символом '!' при помощи доступа к индивидуалтному элементу, то как-то так:
Задача исходной програмы — показать возню в матрице. Что вот мол умеем двумерные массивы делать. Вообще я тут подумал так и нужно на C без stl, поскольку в этом и есть задача программы. С правильными только заголовками и прочей мелочью. То что показывает вы (создание нескольких строк) не есть задача программы. всё имхо. короче яйцо выеденное.
Re[6]: Динамический массив для чайников.
От: shvellerr Россия  
Дата: 14.02.08 19:30
Оценка: :)
блина.. я тока учусь.. чтобы пользоватся динамическими массивами и векторами их надо научится сначала правильно (безглючно делать) а цель то этой программы всего то создать массив, заполнить какимто хламом и не заглюкать по пути и все...
ладно научусь каданибудь..
спасибо всем
Re: Динамический массив для чайников.
От: _Jane_ Украина  
Дата: 21.02.08 16:04
Оценка:
Здравствуйте, shvellerr, Вы писали:

S>Доброго всем времени суток. Извиняюсь заранее если чегото не так сказал.

S>В общем есь такая проблемка. Я только начинаю учить С++ читаю книжку дошел до динамических массивов вроде разобрался написал такой код (почти как в книжке) он работает но странно
S>программа должна выделять место под строки.

S>
S>#include <iostream.h>
S>void main ()
S>{
S>    int dd,ss;
S>    cout << "Введите КОЛИЧЕСТВО строк массива" << endl;
S>    cin >> dd;
S>    cout << "Введите РАЗМЕР строки массива" << endl;
S>    cin >> ss;
S>    char **a; // Указатель указатель на
S>    a = new char *[dd];  // А содержит адрес массива строк [dd]
S>    if (a==0)
S>        {
S>        cout << "массив адресов не создан" << endl;
S>                delete []a; // удаляем массив указателей             /*это, похоже, лишнее*/
S>        return;   // конец :)
S>        }
S>        for (int c=0; c<dd; ++c)
S>             {
S>             //a[c]=new char [ss];     // каждый элемнт массива [dd] содержит адрес строки
S>              *(a+c)=new char [ss];
S>             // (a+c) или a[c]обязательно                                   (массива) [ss] 
S>            if ((a+c)==0) // ПРоверка на создание строки        
S>            {             // проверяется адрес (а+с) без * !!!
S>            cout << "строка не создана" << endl;
                        /*а удалить предыдущие созданные строки? утечка памяти.*/
S>                    delete []a; 
S>            cout << "массив адресов удален" << endl;
S>            return;
S>            }
                
S>             }
S>         cout << "\nМАССИВ СОЗДАН\n\n...Заполнение массива...." << endl;
S>     // заполнение массива
S>     int v;
S>     for (c=0; c<dd; ++c)
S>        { 
S>         for (v=0; v<ss; ++v)
S>            {  
S>            a[c][v]='!';
S>            //*(*(a+c)+v)='!';
S>            }
S>        }
S>     cout << "Введите любую букву(режим паузы)" << endl;
S>         char tt;
S>     cin >> tt;

S>      // удаление массива
S>     for (c=0; c<dd; ++c)
S>        {
S>        delete a[c]; /* здесь ведь тоже был массив? delete[] a[c]; */
S>        }
S>        cout << "Строки удалены" << endl;
S>        delete []a;
S>             a=0;
S>        cout << "указатель удален" << endl;

S>  } //  это конец!
S>


Borland C++ 3.1 для изучения просто языка C++ без наворотов вполне себе нормален. Хотя уметь пользоваться современной средой тоже полезно.
Да, есть ограничения на память для этого и существуют способы проверить, была ли действительно выделена память после new (либо исключение bad_alloc, либо возвращается NULL). "Ошибка защиты" выглядит довольно странно, не было ли там на самом деле исключения? Такая ошибка может быть при обращению к "чужой" памяти, но ничего подобного в коде не увидела — может, и просмотрела.

S>почти как в книжке... запускается нормально но работает со странностями при маленьких массивах работает вроде нормально к примеру 100 на 100..

S>при средних происходят сбои и ошибки например 6000 на 300
S>при больших или работает или происходит ошибка(**** вызвало ошибку защиты в модуле ****).
S>причем выделение памяти нестабильно может не выделить память для меньшего массива и выделить для большего про ограничение размеров массивов я ничего не нашел. Есть ли ограничения для динамических массвов? Есть ли какието правила для их создания? Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?
Jane
Re: Динамический массив для чайников.
От: Аноним  
Дата: 22.02.08 13:06
Оценка:
Здравствуйте, shvellerr, Вы писали:

S>

S>    if (a==0)
S>        {
S>        cout << "массив адресов не создан" << endl;
S>                delete []a; // удаляем массив указателей
S>


PS
Удаление нулевого указателя — UB.
Re[2]: Динамический массив для чайников.
От: ArtDenis Россия  
Дата: 22.02.08 13:32
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Удаление нулевого указателя — UB.


Ну да? С чего бы это
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[3]: Динамический массив для чайников.
От: Аноним  
Дата: 22.02.08 14:08
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, <Аноним>, Вы писали:


А>>Удаление нулевого указателя — UB.


AD>Ну да? С чего бы это


Попробуй в VC 6
Re[4]: Динамический массив для чайников.
От: Аноним  
Дата: 22.02.08 14:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, ArtDenis, Вы писали:


AD>>Здравствуйте, <Аноним>, Вы писали:


А>>>Удаление нулевого указателя — UB.


AD>>Ну да? С чего бы это


А>Попробуй в VC 6


Перепутал с повторным удалением.
Re[5]: Динамический массив для чайников.
От: Аноним  
Дата: 22.02.08 14:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Перепутал с повторным удалением.


Вобще нулевой указатель удалять нет смысла, эти 4 строки кода просто смысла не имеют.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.