Доброго всем времени суток. Извиняюсь заранее если чегото не так сказал.
В общем есь такая проблемка. Я только начинаю учить С++ читаю книжку дошел до динамических массивов вроде разобрался написал такой код (почти как в книжке) он работает но странно
программа должна выделять место под строки.
#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(например неправильно установил))?
Здравствуйте, shvellerr, Вы писали:
S>Что я сделал не правильно? Может ли глюкать среда разработки (Borland C++ 3.1 for Win(например неправильно установил))?
Самое первое, что можно посоветовать, — выкинь borland 3.1 нафиг. Ему уже 20 лед в обед. Ты скорее поколечишь им себя, чем чему-то научишься. Возьми современную среду, например, visual c++ express.
Да, и книжку, по которой ты учишься, выкинь тоже. Сдается мне, что она не намного моложе твоего borland'а. По твоему коду видно, что это в лучшем случае C++ circa конца 80-х, который не имеет никакого смысла в настоящее время.
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 конечно архаичный очень, но С++ более или менее актуальный, да и отлаживаться проще будет.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
S>> delete a[c];//<-- ошибка ! нужно delete[] a[c], тк выделена new[]
S>
Конечно ошибка, но я не помню про BC 3.1 как там всё было. Мне кажется, что для POD пофиг было какой delete звать.
Так что падать должно из-за чего-то другого
S>А книжка и компилятор действительно старые: так уже писать уже не модно
Главное, что и запускать такие программы непросто
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, 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>А книжка и компилятор действительно старые: так уже писать уже не модно
А как грамотно переписать эту программу в современном стиле?
Здравствуйте, Аноним, Вы писали: А>А как грамотно переписать эту программу в современном стиле?
Проблема в том, что она ничего не делает, кроме демонстрации работы с памятью в старом стиле 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 использовать не модно. )
Здравствуйте, shvonder, Вы писали:
S>Здравствуйте, Аноним, Вы писали: А>>А как грамотно переписать эту программу в современном стиле? S>Проблема в том, что она ничего не делает...
Точно-Точно. Грамотно и в современном стиле ЭТУ программу можно переписать так:
int main()
{
}
S>Если считать, что задача программы — залить строки символом '!' при помощи доступа к индивидуалтному элементу, то как-то так: S>
R>В этом примере не совсем понятно, для чего понадобился именно поэлементный доступ с двумя циклами. Как бы доступ ради доступа.
Я же ясно написал: S>>Если считать, что задача программы — залить строки символом '!' при помощи доступа к индивидуалтному элементу, то как-то так:
Задача исходной програмы — показать возню в матрице. Что вот мол умеем двумерные массивы делать. Вообще я тут подумал так и нужно на C без stl, поскольку в этом и есть задача программы. С правильными только заголовками и прочей мелочью. То что показывает вы (создание нескольких строк) не есть задача программы. всё имхо. короче яйцо выеденное.
блина.. я тока учусь.. чтобы пользоватся динамическими массивами и векторами их надо научится сначала правильно (безглючно делать) а цель то этой программы всего то создать массив, заполнить какимто хламом и не заглюкать по пути и все...
ладно научусь каданибудь..
спасибо всем
Здравствуйте, 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(например неправильно установил))?
Здравствуйте, 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 строки кода просто смысла не имеют.