Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.10.2011, 10:47   #1
pinkiller
Форумчанин
 
Регистрация: 29.10.2011
Сообщений: 141
По умолчанию студенческие вопросы

есть динамический массив, который рискует переполниться.
чтобы избежать этого использую незамысловатую операцию:
"if ((u-d)<c)
{
z=z*2
int *te2 = new int[z];
for (int p; p<=z;p++) {
te2[p]=te[p];
}
delete te;
te=te2;
)"
проблема в том что в основном тексте програамы этот массив te[] называеться term[] а операция выше находиться внутри функции... вопрос как сделать так чтобы term поменял свой адрес в мейне, а не только внутри этой функции....
pinkiller вне форума Ответить с цитированием
Старый 29.10.2011, 11:15   #2
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Сделайте массив term[] глобальным. Тогда любая функция сможет менять его размер.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 29.10.2011, 12:01   #3
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Сообщение от Smitt&Wesson Посмотреть сообщение
Сделайте массив term[] глобальным. Тогда любая функция сможет менять его размер.
"Вредные советы" от Smitt&Wesson.

В C++ (да и в других языках) при передаче параметра в функцию без дополнительных уточнений, он передаётся "по значению" - то есть, для функции создаётся персональная копия объекта, с которой она может делать всё, что угодно. В случае массива, "объект массива" int* (int[]) - это переменная содержащая адрес начала массива - поэтому
Код:
void ChangeContent(int* array){
  array[3]=0;
}

void CallFunction(void){
  int* original = new int[20];
  original[3]=1;
  ChangeContent(original);
  //Здесь original[3] равно 0
  delete[] original;
}
Кстати, обращаю внимание, что, если адрес памяти, записанной в указатель, был получен с помощью формы new[] оператора new, освобождать её надо с помощью delete[].

А как поменять сам original? Для этого нужно передать в функцию не значение переменной, а её адрес. В C++ есть два способа для этого. Первый выглядит очень просто:
Код:
void ChangeArray(int*& array){
  int* newArray = new int[40];
  newArray[3]=array[3];
  delete[] array;
  array=newArray;
}

void CallFunction(void){
  int* original = new int[20];
  original[3]=1;
  ChangeArray(original);
  //original изменился, и теперь можно сделать так:
  original[33]=2;
  delete[] original;
}
В конец типа аргумента функции приписывается & - и аргумент будет передаваться в функцию по ссылке, а не по значению; синтаксис работы с ним при этом совершенно не изменится. Это удобно, но это опасно: попробуйте при чтении кода понять, меняет ли DoSomethingWithArray(original) свой аргумент?
Но есть второй способ, подчёркивающий, что аргумент передаётся по ссылке и может меняться внутри функции.
Код:
//Функция принимает указатель на указатель на int
void ChangeArray(int** array){
  int* newArray = new int[40];
  //Унарная * - оператор разыменования указателя, "вытащить то, адрес чего хранится в переменной"
  newArray[3]=(*array)[3];
  delete[] (*array);
  *array=newArray;
}

void CallFunction(void){
  int* original = new int[20];
  original[3]=1;
  //В явном виде передаём в функцию адрес original
  ChangeArray(&original);
  //original изменился, и теперь можно сделать так:
  original[33]=2;
  delete[] original;
}
Первый способ обычно используется с другой целью: если в функцию нужно передать здоровый объект, копирование которого является долгой операцией.
Abstraction вне форума Ответить с цитированием
Старый 29.10.2011, 13:04   #4
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
"Вредные советы" от Smitt&Wesson.
Согласен. Вредный. Но если прога небольшая, ничего в этом страшного нет. А написание кода упрощается в разы.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 01.11.2011, 12:06   #5
pinkiller
Форумчанин
 
Регистрация: 29.10.2011
Сообщений: 141
По умолчанию

как же блин все сложно и непонятно((
pinkiller вне форума Ответить с цитированием
Старый 01.11.2011, 12:41   #6
An1ka
C++,DirectX/OpenGL
Форумчанин
 
Регистрация: 09.01.2011
Сообщений: 422
По умолчанию

Что сложного ? Поставить одну закорючку амперсанд в аргументе функции ? =)
An1ka вне форума Ответить с цитированием
Старый 01.11.2011, 12:45   #7
pinkiller
Форумчанин
 
Регистрация: 29.10.2011
Сообщений: 141
По умолчанию

Охохохо) Разыменование) вообще я не понял где вот тут:

Код:
//Функция принимает указатель на указатель на int
void ChangeArray(int** array){
  int* newArray = new int[40];
  //Унарная * - оператор разыменования указателя, "вытащить то, адрес чего хранится в переменной"
  newArray[3]=(*array)[3];
  delete[] (*array);
  *array=newArray;
}

void CallFunction(void){
  int* original = new int[20];
  original[3]=1;
  //В явном виде передаём в функцию адрес original
  ChangeArray(&original);
  //original изменился, и теперь можно сделать так:
  original[33]=2;
  delete[] original;
}

увеличение размера. то ради чего все затевалось(
pinkiller вне форума Ответить с цитированием
Старый 01.11.2011, 12:48   #8
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

До вызова ChangeArray размер массива original был 20. После вызова стал 40, что проиллюстрировано обращением к 34-му элементу.
Abstraction вне форума Ответить с цитированием
Старый 01.11.2011, 12:53   #9
pinkiller
Форумчанин
 
Регистрация: 29.10.2011
Сообщений: 141
По умолчанию

Код:
//Функция принимает указатель на указатель на int

int z; // глобальный параметр
void ChangeArray(int** array){
  int* newArray = new int[z*2];
  //Унарная * - оператор разыменования указателя, "вытащить то, адрес чего хранится в переменной"
  newArray[3]=(*array)[3];
  delete[] (*array);
  *array=newArray;
}

void CallFunction(void){
  z=20;
  int* original = new int[z];
  original[3]=1;
  //В явном виде передаём в функцию адрес original
  ChangeArray(&original);
  //original изменился, и теперь можно сделать так:
  original[33]=2;
  delete[] original;
}
так можно сделать?
pinkiller вне форума Ответить с цитированием
Старый 01.11.2011, 13:08   #10
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Можно. Только нужно изменить само z, а то повторный вызов ChangeArray оставит размер 40, вместо удвоения.
Хотя правильней таскать z вместе с массивом, с глобальными параметрами риск что-нибудь напутать слишком быстро растёт при увеличении объёмов кода
(и стоит в программе появиться двум-трём расширяемым массивам, как головная боль при "глобальном" подходе гарантирована). Т.е. в простейшем случае нужно добавить в ChangeArray второй параметр, указатель на длину массива. Там его и менять.
Ещё более правильный способ - образовать структуру из массива и его длины и передавать его единым объектом. Но если Вы пока не разбирались со структурами, пока сойдёт и так.
Abstraction вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопросы по БД Rost93 PHP 9 28.06.2011 22:18
Вопросы BubbleBee Общие вопросы C/C++ 2 08.06.2011 02:37
Вопросы по if, else? molodoyy Помощь студентам 5 21.03.2010 15:34
Вопросы по if, else? molodoyy Общие вопросы C/C++ 1 25.10.2008 18:55
вопросы MAcK Win Api 7 21.07.2007 18:08