Wake of Gods Forum | Форум Во Имя Богов
С++, общая тема - Printable Version

+- Wake of Gods Forum | Форум Во Имя Богов (http://wforum.heroes35.net)
+-- Forum: Общие Форумы (/forumdisplay.php?fid=100)
+--- Forum: Софт и железо (/forumdisplay.php?fid=137)
+--- Thread: С++, общая тема (/showthread.php?tid=3420)


С++, общая тема - Berserker - 23.10.2011 21:32

GNU C++, код:

Code:
string s;
s = "hellow";
string a;
string b;

Code:
:
  LEA EAX,[DWORD EBP-28]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],-1
  CALL REMOTE.0040A950
  MOV [DWORD ESP+4],REMOTE.0040D01B
  LEA EAX,[DWORD EBP-28]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],2
  CALL REMOTE.0040AF70
  LEA EAX,[DWORD EBP-38]
  MOV [DWORD ESP],EAX
  CALL REMOTE.0040A950
  LEA EAX,[DWORD EBP-48]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],1
  CALL REMOTE.0040A950
  LEA EAX,[DWORD EBP-48]
  MOV [DWORD ESP],EAX
  CALL REMOTE.0040AE10
  LEA EAX,[DWORD EBP-38]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],2
  CALL REMOTE.0040AE10
  LEA EAX,[DWORD EBP-28]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],-1
  CALL REMOTE.0040AE10
  MOV [DWORD EBP-80],0
  JMP L055
  LEA EBP,[DWORD EBP+18]
  MOV EAX,[DWORD EBP-78]
  MOV EDX,[DWORD EBP-74]
  MOV [DWORD EBP-88],EDX
  CMP EAX,1
  JE L043
  MOV EAX,[DWORD EBP-88]
  MOV [DWORD EBP-84],EAX
  LEA EAX,[DWORD EBP-38]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],0
  CALL REMOTE.0040AE10
  MOV EDX,[DWORD EBP-84]
  MOV [DWORD EBP-88],EDX
L043:
  MOV EAX,[DWORD EBP-88]
  MOV [DWORD EBP-8C],EAX
  LEA EAX,[DWORD EBP-28]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],0
  CALL REMOTE.0040AE10
  MOV EDX,[DWORD EBP-8C]
  MOV [DWORD EBP-88],EDX
  MOV EAX,[DWORD EBP-88]
  MOV [DWORD ESP],EAX
  MOV [DWORD EBP-78],-1
  CALL REMOTE.004068A0
L055:
  LEA EAX,[DWORD EBP-7C]
  MOV [DWORD ESP],EAX
  CALL REMOTE.004062C0
  MOV EAX,[DWORD EBP-80]
  LEA ESP,[DWORD EBP-C]
Здравствуй 100 килобайтный файл, медленная компиляция и простыня асм-кода. Это STL.


RE: Строки в с++ - Efrit - 23.10.2011 21:35

Угу.


RE: Строки в с++ - Berserker - 23.10.2011 22:42

Передача строки в функцию генерирует ещё 12-15 команд ассемблера. Очевидно, голое копирование. Выходит, нет-таки копирования на лету и подсчёта ссылок. Или я ошибаюсь?


RE: Строки в с++ - packa - 01.11.2011 21:56

Не подскажите как вызвать функцию void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)

Внутри функции void __fastcall TForm1::Button1Click(TObject *Sender)
И притом дважды?

Я не знаю как это делать, но предполагаю что как то так:
Code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
            FormMouseDown(Form1, int X, int Y);
            FormMouseDown(Form1, int X, int Y);
}
//[C++ Error] Unit1.cpp(38): E2188 Expression syntax



RE: Строки в с++ - Berserker - 01.11.2011 22:16

Ну дык. Вместо int X, int Y нужны две переменные или два значения.


RE: Строки в с++ - Efrit - 01.11.2011 22:16

packa, если тебе нужен простой щелчок левой кнопкой мыши, то так:
   
P.S. Чуток переименовал тему.



RE: С++, общая тема - packa - 01.11.2011 22:48

Вроде бы работает теперь... в общем ошибок больше не выскакивает.
Но я надеялся что он "притормозит" на этих функциях и подождет пока я не кликну два раза.
Ан нет, проскакивает и все по 0.

Code:
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
        i=0;
        bh[i]=X;
        gh[i]=Y;
        i++;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    FormMouseDown(Sender, mbLeft , TShiftState() << ssLeft, bh[0], gh[0]);
    FormMouseDown(Sender, mbLeft , TShiftState() << ssLeft, bh[1], gh[1]);
    Form1->Canvas->Rectangle(bh[0],gh[0],bh[1],gh[1]);
    Edit1->Text= IntToStr(bh[0])+" "+IntToStr(gh[0])+" "+IntToStr(bh[1])+" "+IntToStr(gh[1]);
}



RE: С++, общая тема - Efrit - 02.11.2011 12:06

packa, ты бы лучше вообще написал, что именно ты хочешь от программы. Чтобы она реагировала на нажатие кнопки лишь с третьей попытки, что ли?

"Притормаживать на этих функциях" данный код и не должен - поскольку там именно функции, а не события...


RE: С++, общая тема - packa - 02.11.2011 12:27

Проблемы решилась так(если интересно кому):
Оказалось то что я у вас тут спрашивал совершенно другое) По крайней мере я предпологал что работать будет совершенно иначе...
---
Теперь все что я рисую на Canvas сбрасывается при нажатии на любую кнопку, и\или сворачивание окна.
Какие способы есть предотвратить это кроме как сохранение всего что творится в файл и воссоздание из него все заново?


RE: С++, общая тема - Efrit - 02.11.2011 13:04

packa Wrote:Какие способы есть предотвратить это кроме как сохранение всего что творится в файл и воссоздание из него все заново?

Глянь на событие OnPaint - оно срабатывает тогда, когда что-то на форме перерисовывается (в том числе и "при нажатии на любую кнопку, и\или сворачивание окна"). Если тебе нужно, чтобы твой прямоугольник "держался" на форме всегда - тогда рисуй его внутри обработчика этого события....


RE: Свободная тема - Efrit - 04.11.2011 15:29

Разумеется, всё вышеописанное верно именно для борландовского Билдера.


RE: С++, общая тема - Efrit - 11.11.2011 20:13

Возможно, кто-то данный прикол и видел - а вот я только узнал 4
В общем, для VС++: создаём h-файл со следующим содержимым: (Click to View)
   
... и инклудим его к своему проекту. После этого Ваш код приобретает новый, абсолютно неповторимый "боярский" стиль! Sm
Например, исходник программы-калькулятора отныне будет выглядеть так:
   



RE: С++, общая тема - packa - 11.11.2011 20:46

А к билдеру также можно.? Sm


RE: С++, общая тема - Efrit - 11.11.2011 21:03

Вряд ли, он наверняка с кириллицей внутри дефайнов не дружит Ab Хотя насчёт новых версий Билдера я не уверен...


RE: С++, общая тема - Sav - 11.11.2011 21:36

А "аминь1" и "спасихоспади1" как получилось? И "какбе" с "ага".


RE: С++, общая тема - packa - 11.11.2011 21:38

А если транслитом?)


RE: С++, общая тема - Efrit - 11.11.2011 21:47

Sav Wrote:А "аминь1" и "спасихоспади1" как получилось? И "какбе" с "ага".
Да, там какой-то неполный инклуд хидер. Но принцип понятен Ab Насколько я понимаю, "аминь1" - это точка с запятой. А "какбе" и "ага", очевидно, фигурные скобки.

packa Wrote:А если транслитом?)
Тады конечно 118


RE: С++, общая тема - Sav - 11.11.2011 22:17

"спасихоспади1", видимо, тоже точка с запятой. А вообще - хитренько так сделано: для значков-то define`ов нет никаких (значки арифметических операций там тоже не определены). Я плохо знаю C++, но, мне кажется, что с именами для значков геморроя побольше будет, чем просто определить слово. Sm


RE: С++, общая тема - Solmyr2000 - 12.11.2011 00:01

(11.11.2011 22:17)Sav Wrote:  "спасихоспади1", видимо, тоже точка с запятой. А вообще - хитренько так сделано: для значков-то define`ов нет никаких (значки арифметических операций там тоже не определены). Я плохо знаю C++, но, мне кажется, что с именами для значков геморроя побольше будет, чем просто определить слово. Sm
Нет, знаки тоже дефайнятся.


RE: С++, общая тема - Efrit - 12.11.2011 00:05

Развивая эту идею: забавно бы смотрелись define-ы на "гоповской" сленг - тогда бы понятие "быдлокод" приобрело новый смысл Ab

Например, такой фрагмент бессмысленного кода: (Click to View)
путём нехитрой define-замены (Click to View)
   
... превратится в следующий код (Click to View)
   
Причём, если предварительно подключить iostream.h - то полученный код прекрасно скомпилируется 148
Воистину, С++ "велик и могуч" ))


RE: С++, общая тема - Berserker - 12.11.2011 01:24

Воистину примитивная глобальная замена текста без учёта семантики и контекста рулит.
Молитва в предыдущем посте зачётная.


RE: С++, общая тема - packa - 25.11.2011 17:30

Возможно ли стандартными средствами с++ builder работать с *gif и прочими граф.файлами с прозрачностью?
Бмп насколько я знаю не прозрачен)


RE: С++, общая тема - Efrit - 25.11.2011 18:01

Так Билдер, вроде бы, вполне себе умеет работать с гифами? Прямо в дефолтной конфигурации. Это не JPG, где нужно какой-то хидер инклудить.

И почему это BMP не прозрачен? Rolleyes Ставь свойство transparent в true, и радуйся жизни 118


RE: С++, общая тема - packa - 25.11.2011 18:22

Quote:Так Билдер, вроде бы, вполне себе умеет работать с гифами? Прямо в дефолтной конфигурации.
Гуглил.
Везде предлагают подключать веббраузер или инклудить библиотеку.
Если не сложно, распиши как вывести гиф на экран...
Quote:И почему это BMP не прозрачен? Rolleyes Ставь свойство transparent в true, и радуйся жизни 118
Хм, не знал) но все равно не самый лучший выход.
1) Остался небольшой муар
2) Глаза стали прозрачными
3) Некоторые картинки выводятся канвой, а как в ней установить transparent я не знаю Bad
Code:
Graphics::TBitmap * richag = new Graphics::TBitmap;
        richag->LoadFromFile("r2.bmp");
        Form1->Canvas->Draw(464, 144-57, richag);



RE: С++, общая тема - GrayFace - 26.11.2011 21:10

Как-раз ставь richag->Transparent. По умолчанию он, как я помню, сделает прозрачным цветом тот, что в левом-нижнем пикселе картинки.

(25.11.2011 17:30)packa Wrote:  Возможно ли стандартными средствами с++ builder работать с *gif и прочими граф.файлами с прозрачностью?
Бмп насколько я знаю не прозрачен)
GifImage, например. Но я его использовал только для генерации палитр. Для png - PngImage. Вот для полупрозрачности png использовать стоит, а для простой прозрачности bmp хватит. Gif вообще не стоит, т.к. 256 цветов.


RE: С++, общая тема - Efrit - 26.11.2011 21:30

Quote:По умолчанию он, как я помню, сделает прозрачным цветом тот, что в левом-нижнем пикселе картинки.

Левом-верхнем.


RE: С++, общая тема - packa - 26.11.2011 22:54

Quote:GifImage, например. Но я его использовал только для генерации палитр. Для png - PngImage.
Спасибо, попробую.
Quote:Вот для полупрозрачности png использовать стоит, а для простой прозрачности bmp хватит. Gif вообще не стоит, т.к. 256 цветов.
Ну так картинка с прозрачностью еще и бегать планирует))
Менять бмпшки по таймеру накладно по ресурсам, и не есть хорошо


RE: С++, общая тема - GrayFace - 27.11.2011 12:36

(26.11.2011 21:30)Efrit Wrote:  
Quote:По умолчанию он, как я помню, сделает прозрачным цветом тот, что в левом-нижнем пикселе картинки.

Левом-верхнем.
В левом-нижнем. Проверил в Delphi 2006.

(26.11.2011 22:54)packa Wrote:  Ну так картинка с прозрачностью еще и бегать планирует))
Менять бмпшки по таймеру накладно по ресурсам, и не есть хорошо
Накладно только по памяти при хранении.


RE: С++, общая тема - Efrit - 27.11.2011 13:21

Quote:В левом-нижнем. Проверил в Delphi 2006.

А причём тут Делфи? Проверь в С++ - убедишься, что в левом верхнем...


RE: С++, общая тема - FBX - 27.11.2011 18:06

(26.11.2011 22:54)packa Wrote:  Ну так картинка с прозрачностью еще и бегать планирует))
Менять бмпшки по таймеру накладно по ресурсам, и не есть хорошо

Ну так, сделать PNG-спрайт из размещённых в ряд картинок, и отрисовывать разные части в разные моменты времени. Можно сделать красивую полупрозрачность. GIF слишком убог. Слишком-слишком-слишком. Есть конечно APNG, но это не совсем ещё освоенная технология.


RE: С++, общая тема - packa - 27.11.2011 18:19

Ну а как поступать то если на рисунке присутствуют элементы с цветом фона?


RE: С++, общая тема - Efrit - 27.11.2011 19:24

packa, покажи уж рисунок, что ли. А то ничего непонятно...


RE: С++, общая тема - GrayFace - 27.11.2011 23:12

(27.11.2011 13:21)Efrit Wrote:  
Quote:В левом-нижнем. Проверил в Delphi 2006.

А причём тут Делфи? Проверь в С++ - убедишься, что в левом верхнем...
Так классы единые.

(27.11.2011 18:19)packa Wrote:  Ну а как поступать то если на рисунке присутствуют элементы с цветом фона?
Сменить цвет фона.


RE: С++, общая тема - Efrit - 28.11.2011 17:19

Quote:Так классы единые.

Значит, не совсем единые. Проще уж проверить и убедиться, что в TImage пиксель (0; 0) - именно левый верхний...


RE: С++, общая тема - Berserker - 28.11.2011 18:07

0; 0 = левый верхний везде.


RE: С++, общая тема - GrayFace - 23.12.2011 12:03

Проверил и в С++ Builder'е на TImage - нижний левый используется.


RE: С++, общая тема - packa - 13.01.2012 22:30

В с++ builder аналог Scale из visual Basic?

Он задает свою координатную систему - например scale(-10,10)-(10,-10) (точно не помню) создаст сетку от х -10 до 10 и тажке с у.

хочу сделать вот это: Image: 3427fff4105at.jpg
8х8

Спрашиваю здесь, потому что не в состоянии сформулировать адекватный запрос в поисковик


RE: С++, общая тема - Efrit - 14.01.2012 11:40

Не, такого нету. Вроде бы, у всех стандартных VCL-ных элементов нумерация идёт с нуля (отрицательных чисел в координатах быть не может), и никакой сетки они не рисуют. Но ты можешь создать свой, наследовав его, например, от TPaintBox: в конструктор прописать генерацию сетки, ну и прописать собственные функции для рисования функций...

P.S. Хотя нет, среди компонентов Samples есть некий TPerfomanceGraph - это то, что тебе нужно?


RE: С++, общая тема - packa - 14.01.2012 17:33

Пока совсем не разобрался - везде на формах задают вопросы об этом компоненте, но нигде еще не встречал ни одного ответа))) Странно.

Но где то в сорсах откопал

Code:
bcppb
PerformanceGraph1->StepSize=3
PerformanceGraph1->Scale=100
думаю как раз то!

Спасибо!


RE: С++, общая тема - packa - 18.01.2012 20:38

Quote:Image: b875b9a1d96bt.jpg

Имеется поле 8х8 нарисованное по массиву слева, через Канву.
Канвой же заливается тот цвет, который означает каждая цифра.

В последствии вместо цвета планирую добавить картинки. Внимание вопрос:
Как можно реализовать "перетаскивание" этих блоков, чтобы собирать 3 в ряд?
Сейчас это через 4 Edit'а, что достаточно уныло)

Я вижу только 1 способ - отлов координат мыши щелчка, и в соответствии с координатами (если х>100 && x<120, y>30, y<50 то блок 1)
Но это достаточно кривое решение, у вас есть идеи?


RE: С++, общая тема - Efrit - 18.01.2012 21:21

какой ужас на заднем фоне ))

Как именно реализовано это поле? Через канву главной формы? Если да, то решать приведённую тобой задачу не имеет смысла - ведь коли ты планируешь "вместо цвета добавить картинки", то код в любом случае придётся переписывать...

Могу уж тогда написать решение для перетаскивания картинок, что ли.

P.S. Почему это "квадратистое" поле имеет размеры 8*7, тогда как "числовое поле" - 8*8? Rolleyes


RE: С++, общая тема - packa - 18.01.2012 22:11

Quote:P.S. Почему это "квадратистое" поле имеет размеры 8*7, тогда как "числовое поле" - 8*8?
Блин.
Это пакка-квадрат. Если говорится о фигуре 8х8, то будет 8х7, аналогично 6х6 - 6х5 Rolleyes
Кстати, нужно будет поменять, на пакка квадрат 8х9

Quote:Могу уж тогда написать решение для перетаскивания картинок, что ли.
Был бы рад получить небольшой кусок кода, отрисовки картинки.
Просто ранее часто сталкивался с проблемой всяких очисток переменных и т.д. Тем более в цикле вообще сплошные баги из за этого.

Вот с цветными квадратами
Code:
for(i = 1 ;i < 9; i++)
        {
        for(j = 1 ;j < 9; j++)
                {
                a=bh[i][j];
switch (a)
{
  //case 1   : Form1->Canvas->Brush->Color = RGB(0, 0, 0);
  case 0   : Form1->Canvas->Brush->Color = (TColor)RGB(33,22,145);  break;
  case 1   : Form1->Canvas->Brush->Color = clGray;        break;
  case 2   : Form1->Canvas->Brush->Color = clGreen;      break;
  case 3   : Form1->Canvas->Brush->Color = clWhite;       break;
  case 4   : Form1->Canvas->Brush->Color = clYellow;      break;
  case 5   : Form1->Canvas->Brush->Color = clRed;         break;
  case 6   : Form1->Canvas->Brush->Color = clBlue;        break;
  case 7   : Form1->Canvas->Brush->Color = (TColor)RGB(133,222,145);   break;
      default:
                ;
}
                Form1->Canvas->Rectangle(gh[j], k+30, gh[j]+40, k+70);

                }
            k=k+40;
        }
}



RE: С++, общая тема - Efrit - 21.01.2012 23:26

только сейчас добрался до домашнего компа...

Пакка, мой тебе совет - для начала научись пользоваться динамическим созданием компонентов, это куда лучше статического. Плюс, всегда отделяй GUI-логику приложения от "независимых" расчётов: для них, привязка к каким-то конкретным GUI-компонентам - это зло (если нужно использовать какое-то значение свойства компонента, просто передавай его в функцию по значению).

А уже после этого, можно реализовывать всякие "интерфейсные" фичи вроде перетаскивания картинок, если сама структура программы грамотная. Например, для твоей программы может подойти такая реализация:
   
   
P.S. Разумеется, нужно предварительно иметь "пустую" форму с одной-единственной кнопкой Button1 (ну и bmp-картинки для рисования квадратиков).
P.P.S. Вверху никакой не PHP Ab Надеюсь, что с кодом разберёшься...


RE: С++, общая тема - packa - 21.01.2012 23:48

К сожалению это очень далеко от базиса, так что доберусь не скоро (((

Я пока нашел другой путь (уж извини, тут долго ответа не было) )

Но никак не пойму что не так...
Image: d211e7aab0e9t.jpg

Вот двойной цикл заполнения картинками
1) case 0 должен работать, не понимаю что не так
2) Последняя строчка должна заполняться по циклу, а не пустыми изображениями (это видно из-за первого массива, но если его поменять, опять же ошибка вылазит )

Первый массив определяет цифру каждой ячейку, впоследствии кейзами ставится соответствующая картинка
Code:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
randomize();
for(int i = 0 ;i < 8; i++)
        {
        for(int j = 1 ;j < 9; j++)
                {
                bh[i][j]=random(8);
                }
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
int ProhodMassiva=0;
int OtstupVniz = 0;
NumImg=8;
Img=new TImage*[NumImg];
for(int j=0;j<NumImg;j++)
{
        for(int i=0;i<NumImg;i++)
        {
        Label7->Caption=Label7->Caption+bh[i][j] ;
        Label8->Caption=Label8->Caption+ProhodMassiva ;
        ProhodMassiva=ProhodMassiva++;
        switch (bh[i][j])
                {
                //case 1   : Form1->Canvas->Brush->Color = RGB(0, 0, 0);
                //case 0   : Img[i]->Picture->LoadFromFile("18.bmp"); break;
                case 1   : Img[i]->Picture->LoadFromFile("11.bmp"); break;
                case 2   : Img[i]->Picture->LoadFromFile("12.bmp"); break;
                case 3   : Img[i]->Picture->LoadFromFile("13.bmp"); break;
                case 4   : Img[i]->Picture->LoadFromFile("14.bmp"); break;
                case 5   : Img[i]->Picture->LoadFromFile("15.bmp"); break;
                case 6   : Img[i]->Picture->LoadFromFile("16.bmp"); break;
                case 7   : Img[i]->Picture->LoadFromFile("17.bmp"); break;
                //case 8   : Img[i]->Picture->LoadFromFile("18.bmp"); break;
                default: ;
                }
        Img[i]=new TImage(this);
        Img[i]->Picture->LoadFromFile("18.bmp");
        Img[i]->Parent=this;
        Img[i]->Left=25+i*45;
        Img[i]->Top=10+OtstupVniz;
        Img[i]->Visible=true;

        }
OtstupVniz=OtstupVniz+49;
Label7->Caption=Label7->Caption+" " ;
Label8->Caption=Label8->Caption+" " ;
}delete Img;
}

Весь день, менял,менял,менял...
из чего сделал вывод, что я просто что то не знаю, потому что проверил вроде бы все возможные варианты
1)задаю в двумерном массиве bh[0 - 8] [0 - 8]
Теперь программа вылетает на первом символе отличным от нуля
Image: 4e0ad324f196t.jpg
2) меняю i=0 на i=1, в массиве изображений, результат не изменился
3) расширил NumImg=8 до NumImg=9; результат не изменился
4) Поместил в комментарий свич (!) Все циклы сработали исправно. Все 64 клетки заполнились рандомными цифрами
5) вернул массиву i с 1 до 9 j с 1 до 9 (так хоть работает), массиву изображений поставил j=1, i=1
опять ошибка на первом отличном от нуля символе

Я что только не делал, но так и ничего не нашел. Задал этот вопрос на парочке форумов программистов, естественно проигнорировали, помогает только личное обращение.

Только если будет неохото, или времени мало, то напиши чтобы я не ждал Sm

Спасибо за внимание

http://zalil.ru/32549967


RE: С++, общая тема - Efrit - 22.01.2012 17:16

Пакка, сразу несколько рекомендаций:

1) Если ты вводишь какую-то целочисленную переменную, которая не может быть отрицательной - всегда пиши в названии слово unsigned. Например, "индекс массива" всегда неотрицателен, поэтому его следует объявлять как unsigned int. И поверь, это ничуть не излишество.
Зачем это нужно? А вот зачем: (Click to View)
   
2) Если ты уверен, что твоя переменная не может принимать каких-то "больших" значений - то не стоит объявлять её тип как int, лучше пользуйся short int (диапазон из 216 значений) или даже char (диапазон из 28 значений). Это позволяет экономить оперативную память, поскольку значения таких типов занимают в ней меньше места - особенно, если они составляют собой массив.

3) Никогда не используй нумерацию каких-либо элементов (массива, списка, STL-контейнера) с единицы, как в строке 6 твоего кода. Только с нуля! Это часто может привести к ошибке исполнения - особенно, если приходится работать непосредственно с памятью (через указатели). Вот, кстати, за что мне ещё не нравится Borland VCL - в ней нумерация букв в String-овой строке идёт именно с единицы, прям как в Паскале каком-то. Хорошо хоть, std::string мне никто пользоваться не запрещает Sm

4) Если какая-то последовательность действий представляет собой логический блок, то есть ты можешь выделить его в какую-то функцию - то выделяй. Например, "заполнение массива bh случайными числами" - это и есть логический блок, и поэтому его лучше вынести в отдельную функцию. Плюс такого решения в том, что если тебе понадобилось обратиться к такому "блоку" снова - ты просто вызываешь функцию снова, а не тупо копипастишь код.

Более того, подобные функции нужно стараться делать как можно более "универсальными". Например, для вышеуказанного примера - чтобы функция "заполнения массива случайными числами" могла работать не только с массивом bh, а с любым массивом вообще. Это избавит тебя от необходимости написания новых функций для каждого массива - поскольку "универсальная" функция для подобных целей у тебя уже есть. Правда, при работе с массивами возникают сложности, связанные с тем, что для корректной работы с ними сторонних функций, необходимо каждый раз указывать размер массива. В связи с этим, возникает пятый пункт.

5) Вообще не используй статические массивы ("обычные"), а юзай динамические. Лучше всего - std::vector, он наиболее прост для понимания, плюс совместим с С-шными функциями, работающими со статическими массивами. У динамических массивов его размер всегда хранится "внутри" массива, плюс его (размер) в любой момент можно изменить (со статическим такой фокус не пройдёт).
   
   

   
   
Теперь ещё раз посмотри в мой код. Он всё ещё кажется тебе таким сложным? Давай я его объясню.

Первые три строки - это объявление динамического массива, о которых я говорил выше. Первая строка подключает библиотечный файл для работы с ними (её нужно писать лишь один раз внутри всего проекта). Типом "динамический массив" здесь является std::vector, а в фигурных скобках указан тип его элементов (например, "динамический массив элементов типа int" описывается как std::vector<int>). Но так как массив у нас двумерный, то в фигурных скобках записан "он сам". Надеюсь, теперь понятно, откуда взялась запись std::vector< std::vector<unsigned short> > ? Но так как всё время писать такую длинную конструкцию не очень красиво, то с помощью служебной команды typedef мы вводим для этой конструкции слово-синоним TMatrix (учти, что эта команда работает лишь с типами, это тебе не #define). Наконец, в третьей строке мы вводим сам динамический массив bh на основе только что созданного типа TMatrix.

Потом я объявляю две строковые константы. EXE_PATH - это просто путь к папке, где хранится экзешник твоей программы. Далее, функция GenerateMatrix заполняет твой массив bh случайными числами. Обрати внимание, что параметр "input" передаётся в неё по ссылке - таким образом, эту функцию можно использовать для любого массива, имеющего тип TMatrix - а не только для bh. Если что, в ней resize(...) - изменяет размер динамического массива. Всё остальное, думаю, понятно.

Функция DrawingMatrix рисует матрицу из Label-ов, как на скриншоте в твоём сообщении №40. Она работает по такому принципу: вначале она ищет Label-ы с именами вида "Label_i_j" (где i и j меняются) на форме form, и если не находит какие-то из них - то она их создаёт. После этого, она меняет их заголовок на нужное "число", взятое из массива input (в данном случае, массива bh). Текущий Label всегда хранится в указателе current, указывающем на только что найденный Label. Его поиск производится в этой строчке:

TLabel* current = dynamic_cast<TLabel*>(form->FindComponent(name));

Что она означает? Смотри справа налево. FindComponent - это метод формы form, который ищет компонент на этой форме по его имени (переменная name). Этот метод возвращает значение типа *TComponent, то есть указатель на тип TComponent. Для того, чтобы работать с ним, как с Label-ом, этот указатель нужно привести к типу *TLabel - то есть нужно сделать так, чтобы он указывал именно на Label. Для этого вызывается шаблонная функция dynamic_cast<TLabel*>(...) (то бишь, сама функция называется "dynamic_cast", а в фигурных скобках записан новый тип параметра, к которому и будет приводить указатель, записанный в круглых скобках). После всего этого, справа от знака равенства у нас будет указатель на TLabel, который и можно присвоить переменной current. Остальное просто.

Наконец, функция DrawingSquares создаёт/изменяет картинки (TImage), подгружая в них информацию из соответствующих файлов. Загрузка содержимого картинки из файла "обёрнута" в конструкцию try-catch - это блок "обработки исключений" в C++ (поскольку файл может отсутствовать, и тогда функция LoadFromFile сгенерирует исключение, которое и будет поймано catch). Всё остальное в ней аналогично предыдущей функции. Все эти три функции вызываются в самом низу, в обработчике нажатия кнопки Button1.

P.S. Надеюсь, что не зря распинался4


RE: С++, общая тема - gamecreator - 22.01.2012 18:33

(22.01.2012 17:16)Efrit Wrote:  Пакка, сразу несколько рекомендаций:
хотелось бы добавить
6) не стоит злоупотреблять STL


RE: С++, общая тема - Efrit - 22.01.2012 18:40

угу, стоит злоупотреблять бустом))

Согласен, что не стоит. Как и любой из известных библиотек. Но и изобретать свой велосипед там, где он уже давно есть в стандартных библиотеках, не стоит также. И уж то, что динамический массив почти всегда лучше статического - по-моему, очевидно.

Да и в любом случае, до шестого пункта Пакка ещё явно не дорос 118


RE: С++, общая тема - gamecreator - 22.01.2012 19:29

(22.01.2012 18:40)Efrit Wrote:  Но и изобретать свой велосипед там, где он уже давно есть в стандартных библиотеках, не стоит также.
если в стандартной библиотеке вездеход, то еще неизвестно что лучше


RE: С++, общая тема - Efrit - 22.01.2012 20:36

Quote:если в стандартной библиотеке вездеход, то еще неизвестно что лучше

Что из используемого мною выше является вездеходом? std::vector - это вездеход? Или, может быть, dynamic_cast? (хоть это и не STL, но тоже шаблоны)


RE: С++, общая тема - packa - 22.01.2012 21:49

Спасибо за рекомендации, запомню.
Quote:Никогда не используй нумерацию каких-либо элементов (массива, списка, STL-контейнера) с единицы, как в строке 6 твоего кода.
В том и соль, если начну с нуля код не работает... А с единицы начинает хотя бы хромать

Но почему вы плавно ушли от прямого вопроса? Sm

Почему_данный_код_не_работает!
Я просто не могу понять что в нем может быть не правильно... Перепробовал, кажется, все

Попробую воспользоваться твоим, но вопрос мой не отменяет Sm))
О гуру! Что же там поменять чтобы все таки работало?

Quote:это блок "обработки исключений" в C++ (поскольку файл может отсутствовать, и тогда функция LoadFromFile сгенерирует исключение, которое и будет поймано catch)
Не может Sm Это же игра, как ты представляешь игру без какой то картинки?))) По мне так лучше вообще не запускать не работающую, следовательно и исключения - лишний вес пригодный только для теста Sm



RE: С++, общая тема - gamecreator - 22.01.2012 21:57

если хочешь, то вектор. особенно вектор векторов - это вообще зло. и все лишь для того, чтобы создать двумерный массив неизвестного заранее размера. а вся функциональность вектора будет висеть мертвым грузом. ладно бы еще vector<bool>, тут какая-нибудь экономия памяти еще пригодилась бы. возможно.


RE: С++, общая тема - FBX - 22.01.2012 22:30

Иногда помогает метод "удалить всё и заново переписать". Особенно, покурив перед этим другой какой способ реализации.


RE: С++, общая тема - packa - 22.01.2012 22:57

Quote:Иногда помогает метод "удалить всё и заново переписать". Особенно, покурив перед этим другой какой способ реализации.
Да цель уже не заставить работать, а найти почему не работает! О боги, неужели мой код не работает только потому что он тупой?)


RE: С++, общая тема - Efrit - 22.01.2012 22:58

gamecreator Wrote:если хочешь, то вектор. особенно вектор векторов - это вообще зло. и все лишь для того, чтобы создать двумерный массив неизвестного заранее размера. а вся функциональность вектора будет висеть мертвым грузом. ладно бы еще vector<bool>, тут какая-нибудь экономия памяти еще пригодилась бы. возможно.
Неужели ты хочешь, чтобы я рассказывал Пакке про работу с указателями и адресную арифметику, дабы он смог нормально писать свои функции для работы с многомерными массивами? Он же всего этого ещё не поймёт. Или, что ещё хуже, рассказывать ему про boost::multi_array? Юзать вектор - самое оптимальное для него решение: он и интуитивно понятен, и синтаксис обращения к элементу у него такой же, как в C (не рассказывать же Пакке про итераторы, в конце концов).


packa Wrote:Почему_данный_код_не_работает!
Я просто не могу понять что в нем может быть не правильно... Перепробовал, кажется, все
Частично я уже указал тебе на твою ошибку, смотри пункт 3 моих рекомендаций. Ты не заполняешь в массиве bh элементы вида bh[i][0] числами, и поэтому они принимают значение по умолчанию - то бишь 0. Поэтому, строчка с case 0 всегда срабатывает уже для самого первого элемента массива bh (то бишь, для bh[0][0]). А что в ней происходит? Ты пытаешься (через указатель) обратиться к элементу, который ещё не создан! Ты создаёшь его лишь ниже, командой Img[i]=new TImage(this);

Вот в этом всё и дело. Учти, что "создание указателя на объект" - вовсе не то же самое, что "создание объекта". Указатель может указывать и в "пустоту", как в твоём случае. А "изображение" - это уже объект. Ты же пытаешься обратиться к объекту через указатель (путём вызова компонентной функции LoadFromFile), а сам объект создаёшь лишь после этого. Вот где собака зарыта...

P.S. Что не отменяет того факта, что весь твой код лучше переписать Ab


RE: С++, общая тема - packa - 22.01.2012 23:28

Quote:Частично я уже указал тебе на твою ошибку, смотри пункт 3 моих рекомендаций. Ты не заполняешь в массиве bh элементы вида bh[i][0] числами, и поэтому они принимают значение по умолчанию - то бишь 0. Поэтому, строчка с case 0 всегда срабатывает уже для самого первого элемента массива bh (то бишь, для bh[0][0])
Да это так, извини немного тебя запутал. Большая проблема кроется в том, что изменив bh-массив
Quote:randomize();
for(int i = 0 ;i < 8; i++)
    {
    for(int j = 0 ;j < 8; j++)
    {
    bh[i][j]=random(8);
    }
    }
Код приводит к ошибке на первом объекте, каким бы он ни был (цикл проходит только один раз, после чего ошибка),
А с единицей хоть рисуется что то Sm

Quote:P.S. Что не отменяет того факта, что весь твой код лучше переписать Ab
Так я не спорю, я буду его переделывать, но мне очень важно знать что не так.
Хотя бы потому, что я потратил 2 чистых дня на тест и безрезультатную отладку.
Ну и, конечно, чтобы не бить себя этими граблями дважды.


RE: С++, общая тема - packa - 23.01.2012 00:06

Quote:void __fastcall TForm1::FormCreate(TObject *Sender)
{
randomize();
for(int i = 0 ;i < 8; i++)
    {
    for(int j = 0 ;j < 8; j++)
    {
    bh[i][j]=random(8);
    }
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
int ProhodMassiva=0;
int OtstupVniz = 0;
NumImg=8;
Img=new TImage*[NumImg];
for(int j=0;j<NumImg;j++)
{
    for(int i=0;i<NumImg;i++)
    {
    Label7->Caption=Label7->Caption+bh[i][j] ;
    Label8->Caption=Label8->Caption+ProhodMassiva ;
    ProhodMassiva=ProhodMassiva++;
    Img[i]=new TImage(this);
    switch (bh[i][j])
    {
    case 0 : Img[i]->Picture->LoadFromFile("18.bmp"); break;
    case 1 : Img[i]->Picture->LoadFromFile("11.bmp"); break;
    case 2 : Img[i]->Picture->LoadFromFile("12.bmp"); break;
    case 3 : Img[i]->Picture->LoadFromFile("13.bmp"); break;
    case 4 : Img[i]->Picture->LoadFromFile("14.bmp"); break;
    case 5 : Img[i]->Picture->LoadFromFile("15.bmp"); break;
    case 6 : Img[i]->Picture->LoadFromFile("16.bmp"); break;
    case 7 : Img[i]->Picture->LoadFromFile("17.bmp"); break;
    default: ;
    }
    //Img[i]=new TImage(this);
    Img[i]->Parent=this;
    Img[i]->Left=25+i*45;
    Img[i]->Top=10+OtstupVniz;
    Img[i]->Visible=true;

    }
OtstupVniz=OtstupVniz+49;
Label7->Caption=Label7->Caption+" " ;
Label8->Caption=Label8->Caption+" " ;
}delete Img;
}

Отбой тревоги( Оказалось еще тупее ошибка чем я мог представить...
Шуруп помог.


RE: С++, общая тема - gamecreator - 23.01.2012 00:45

(22.01.2012 22:58)Efrit Wrote:  Неужели ты хочешь, чтобы я рассказывал Пакке про работу с указателями и адресную арифметику, дабы он смог нормально писать свои функции для работы с многомерными массивами?
про какую еще работу с указателями? как выделить память и как ее освободить? на работу с указателями не тянет. а адресной арифметики там нет и в помине. или борландовский компилятор настолько убог, что не позволяет обращаться к элементу динамического массива напрямую? вот так:
Code:
int main()
{
    int **a;
    const m=8;
    const n=9;
    a=new int*[m];
    for(int i=0;i<m;i++)
    {
        a[i]=new int[n];
    }
    a[m/2][n/2]=-1;
    for(int i=0;i<m;i++)
    {
        delete[] a[i];
    }
    delete[] a;
    return 0;
}
(22.01.2012 22:58)Efrit Wrote:  Или, что ещё хуже, рассказывать ему про boost::multi_array?
с boost не знаком и не хочу, поэтому не могу сказать.
(22.01.2012 22:58)Efrit Wrote:  он и интуитивно понятен, и синтаксис обращения к элементу у него такой же, как в C
какое совпадение, у динамического массива синтаксис такой же. наверно Страуструп сплагиатил у авторов STL.


RE: С++, общая тема - Efrit - 23.01.2012 07:47

packa Wrote:Отбой тревоги( Оказалось еще тупее ошибка чем я мог представить...
Шуруп помог.
Пакка, ты внимательно читаешь мои сообщения? Rolleyes Я же прямо указал тебе в сообщении 55, что ошибка связана со строкой Img[i]=new TImage(this) - она слишком низко стоит, ты создаёшь объект после обращения к нему. Даже пурпурным цветом её тогда выделил Ab Кстати, а ты вообще понимаешь, что именно делает эта строка?


gamecreator Wrote:про какую еще работу с указателями? как выделить память и как ее освободить? на работу с указателями не тянет. а адресной арифметики там нет и в помине.
Ну-ка напиши мне функцию транспонирования квадратной матрицы без использования адресной арифметики. Или же, ещё лучше - какую-нибудь функцию с неизвестным числом переменных (желательно строковых). Неужели, по-твоему, C++-программист не должен знать про адресную арифметику?

gamecreator Wrote:с boost не знаком и не хочу
Откуда такая категоричность?

gamecreator Wrote:какое совпадение, у динамического массива синтаксис такой же. наверно Страуструп сплагиатил у авторов STL.
Не пиши глупости. Далеко не у всех STL-ных контейнеров оператор "квадратные скобки" перегружен также, как у вектора... Я это и имел в виду.


RE: С++, общая тема - Solmyr2000 - 23.01.2012 11:35

Ох какие вы няши.
Эфрит прав. Давайте теперь вместо того, чтобы делать что-нибудь полезное, заменять STL и буст велосипедами. Зло, не зло, это всё очень абстрактно и бездоказательно, я погуглил и нашёл, что ВСЁ во ВСЕХ языках программирования - зло. Деньги, кстати, тоже зло. Такие дела.


RE: С++, общая тема - etoprostoya - 23.01.2012 11:58

(23.01.2012 07:47)Efrit Wrote:  Ну-ка напиши мне функцию транспонирования квадратной матрицы без использования адресной арифметики.

Code:
for(int i = 0; i < 32; i++)
     for(int k = 0; k < 32; k++)
     {
          int tmp = arr[i][k];
          arr[i][k] = arr[k][i];
          arr[k][i] = tmp;
     }
Никаких адресов, только индексы.Rolleyes


RE: С++, общая тема - Efrit - 23.01.2012 12:30

etoprostoya, ну и где здесь функция? Spiteful


RE: С++, общая тема - packa - 23.01.2012 13:51

Quote:Пакка, ты внимательно читаешь мои сообщения? Rolleyes Я же прямо указал тебе в сообщении 55, что ошибка связана со строкой Img[i]=new TImage(this) - она слишком низко стоит, ты создаёшь объект после обращения к нему. Даже пурпурным цветом её тогда выделил Ab
Гм, не знаю по какой причине, но я прочитал только это))) :

Quote:Частично я уже указал тебе на твою ошибку, смотри пункт 3 моих рекомендаций. Ты не заполняешь в массиве bh элементы вида bh[i][0] числами, и поэтому они принимают значение по умолчанию - то бишь 0. Поэтому, строчка с case 0 всегда срабатывает уже для самого первого элемента массива bh (то бишь, для bh[0][0]). А что в ней происходит? Ты пытаешься (через указатель) обратиться к элементу, который ещё не создан!
Вследствие чего не совсем допонял, и сделал неправильный вывод.
Quote:Кстати, а ты вообще понимаешь, что именно делает эта строка?

Теперь да, тогда нет Sm
Точнее догадаться мог, это довольно просто, но я просто не обращал на нее внимания. Да, мне стыдно...


RE: С++, общая тема - etoprostoya - 23.01.2012 14:20

(23.01.2012 12:30)Efrit Wrote:  etoprostoya, ну и где здесь функция? Spiteful

А по существу? Добавь оболочку для функции, которая не влияет на саму возможность обращаться к элементам массивов без использования адресной арифметики.
Code:
void function(void)
{
     for(int i = 0; i < 32; i++)
          for(int k = 0; k < 32; k++)
          {
               int tmp = arr[i][k];
               arr[i][k] = arr[k][i];
               arr[k][i] = tmp;
          }
}



RE: С++, общая тема - Efrit - 23.01.2012 14:37

packa, теперь всё понятно Ab
И всё-таки, ради интереса ответь - что же именно, на твой взгляд, делается в той строке 118

etoprostoya, а где в твоей функции массив-то? arr - это какой-то конкретный глобальный массив, он не в счёт. А я, разумеется, имел в виду реализацию функции, которая транспонирует любой входной двумерный массив (любого размера)...


RE: С++, общая тема - packa - 23.01.2012 15:58

Quote:NumImg=8;
Img=new TImage*[NumImg];
Резервируем место под 8 элементов
Quote:Img[i]=new TImage(this);
Создаем картинку (пустую), на данном элементе (на форме)
Quote:case 4 : Img[i]->Picture->LoadFromFile("14.bmp"); break;
Заполняем картинку картинкой)

Вот так я понял


RE: С++, общая тема - etoprostoya - 23.01.2012 16:08

Про любой размер массива речи не было:
Quote:Ну-ка напиши мне функцию транспонирования квадратной матрицы без использования адресной арифметики.
Вот тебе код для двумерного массива любого размера:
Code:
int **arr;
void function(int H, int W)
{
      for(int i = 0; i < H; i++)
           for(int k = 0; k < W; k++)
           {
                int tmp = arr[i][k];
                arr[i][k] = arr[k][i];
                arr[k][i] = tmp;
           }
}
Опять придерёшься к чему-то, что не было оговорено? Sm


RE: С++, общая тема - gamecreator - 23.01.2012 17:23

(23.01.2012 07:47)Efrit Wrote:  Ну-ка напиши мне функцию транспонирования квадратной матрицы без использования адресной арифметики.
Code:
void foo(int **arr, int n)
{
     int tmp;
     for(int i = 0; i < n; i++)
          for(int k = i + 1; k < n; k++)
          {
               tmp = arr[i][k];
               arr[i][k] = arr[k][i];
               arr[k][i] = tmp;
          }
}
(23.01.2012 07:47)Efrit Wrote:  Или же, ещё лучше - какую-нибудь функцию с неизвестным числом переменных
а это тут причем? у Пакки в программе ими и не пахнет.
(23.01.2012 07:47)Efrit Wrote:  желательно строковых
так это только упрощает задачу
(23.01.2012 07:47)Efrit Wrote:  Неужели, по-твоему, C++-программист не должен знать про адресную арифметику?
почему в начальных классах не рассказывают матан?
(23.01.2012 07:47)Efrit Wrote:  Откуда такая категоричность?
плохое впечатление
(23.01.2012 11:35)Solmyr2000 Wrote:  я погуглил и нашёл, что ВСЁ во ВСЕХ языках программирования - зло. Деньги, кстати, тоже зло.
но в яп нет денег Bad


RE: С++, общая тема - Efrit - 23.01.2012 18:23

packa, ты понял не совсем правильно. Команда new не просто "создала картинку" - она вызвала конструктор класса TImage, который как раз и создал объект "картинка", и затем вернула указатель на этот объект. Пойми, что Img - это массив указателей (причём ты его весьма коряво создаёшь, ну да ладно), а не массив объектов. А дальше ты просто обращаешься к объекту "картинка" (созданному конструктором) через указатель на него.
надеюсь, ты вообще знаешь, что такое "указатель"? Sm

etoprostoya, опять придерусь. Ну неужели ты так и не понял, что что функция должна транспонировать входной массив - то есть он должен как-то описываться среди входных параметров функции? Я же недаром даже выделил слово "входной" жирным (в своём предыдущем сообщении)... Ты же всё упорно пытаешься транспонировать какой-то левый глобальный массив arr - а нужно, чтобы функция транспонировала любой массив, а не только его (о чём я также писал выше).

gamecreator, ты пробовал запускать свою функцию? Напиши-ка ещё инициализацию входного массива и строчку вызова самой функции, ну чисто ради интереса Rolleyes

gamecreator Wrote:а это тут причем? у Пакки в программе ими и не пахнет.
Это я привёл пример, в реализации которого без указателей и адресной арифметики ну никак не обойтись. Или оспоришь? Spiteful

Quote:так это только упрощает задачу
Да ну! Ну давай, реализуй4

Quote:почему в начальных классах не рассказывают матан?
Если человек хочет хорошо знать математику, то матан ему учить придётся. То же самое и здесь. Тем более, что работа с указателями - это не такая уж и сложная штука. То же истанцирование шаблонов - куда сложнее.

Quote:плохое впечатление
И что же там такого плохого? Неужели ты смотрел весь Буст целиком?


RE: С++, общая тема - packa - 23.01.2012 18:24

Quote:Пакки
Респект дружище!)))

Quote:надеюсь, ты вообще знаешь, что такое "указатель"?
Слышал где то Rolleyes


RE: С++, общая тема - gamecreator - 23.01.2012 18:50

(23.01.2012 18:23)Efrit Wrote:  ты пробовал запускать свою функцию?
честно - не пробовал. но не сомневаюсь в отсутствии семантических ошибок.
(23.01.2012 18:23)Efrit Wrote:  Напиши-ка ещё инициализацию входного массива и строчку вызова самой функции, ну чисто ради интереса Rolleyes
инициализация была в предыдущем куске кода. а foo(a,8); и писать нечего.
(23.01.2012 18:23)Efrit Wrote:  Это я привёл пример, в реализации которого без указателей и адресной арифметики ну никак не обойтись.
пример должен быть уместен. напомню, ты начал доказывать, что без вектора Пакке понадобится знать операции с указателями и адресную арифметику. доводов в подтверждение этого я еще не услышал.
(23.01.2012 18:23)Efrit Wrote:  Да ну!
ну да. указатель-то всегда 4 байта.
(23.01.2012 18:23)Efrit Wrote:  Ну давай, реализуй4
ок, будет.
(23.01.2012 18:23)Efrit Wrote:  Если человек хочет хорошо знать математику, то матан ему учить придётся.
но перед тем, как учить матан, необходимо еще много узнать. дай Пакке сначала научиться программировать, а потом уже учи его особенностям языка.
(23.01.2012 18:23)Efrit Wrote:  И что же там такого плохого? Неужели ты смотрел весь Буст целиком?
мне хватило попытки знакомства.


RE: С++, общая тема - Solmyr2000 - 23.01.2012 19:00

(23.01.2012 17:23)gamecreator Wrote:  но в яп нет денег Bad
:D Ну я имел в виду, что деньги-то зло, а всё равно нужны Sm


RE: С++, общая тема - gamecreator - 23.01.2012 19:09

(23.01.2012 18:23)Efrit Wrote:  Ну давай, реализуй4
Code:
#include <stdio.h>
#include <string.h>

void multicat(char *dest, int n, ...)
{
    char **next = (char**) (&n + 1);
    dest[0] = 0;
    for(int i=0; i<n; i++, next++)
    {
        strcat(dest,*next);
    }
}

int main()
{
    char result[15];
    multicat(result,4,"123","45","6789","0");
    printf("%s\n",result);
    return 0;
}



RE: С++, общая тема - Efrit - 23.01.2012 19:36

gamecreator Wrote:честно - не пробовал. но не сомневаюсь в отсутствии семантических ошибок.
инициализация была в предыдущем куске кода. а foo(a,8); и писать нечего.
Увы, ошибка.

Quote:пример должен быть уместен. напомню, ты начал доказывать, что без вектора Пакке понадобится знать операции с указателями и адресную арифметику. доводов в подтверждение этого я еще не услышал.
Как это "не услышал"? Сам же и написал функцию, которая принимает на входе указатель 96-copy

Quote:но перед тем, как учить матан, необходимо еще много узнать. дай Пакке сначала научиться программировать, а потом уже учи его особенностям языка.
Дык это ж не просто "особенность", это одна из его ключевых фич. "Особенности" - это уже больше свойства каких-то конкретных бибилиотек, типа той же STL (вот в ней у каждого контейнера есть свои особенности).

Но в целом соглашусь, действительно ещё Пакке рановато в указатели вникать. Но я ему хотя бы глаза на них открыл Ab Пусть знает, что рано или поздно ему придётся с ними плотно познакомиться.

Quote:мне хватило попытки знакомства.
Ну и что именно-то тебе в нём не понравилось? 105 Блин, словно клещами информацию из тебя выжимаю...

P.S. За реализацию "второй" функции - респект, всё правильно.


RE: С++, общая тема - Efrit - 23.01.2012 20:07

А нет, Игродел - вру, не ошибка. Но твоя функция транспонирования работает лишь в том случае, если объявлять массив a так:

Code:
int **a;
const m = 5;
const n = 5;
a = new int*[m];
for(int i = 0; i < m; i++) a[i] = new int[n];

Но в реальности так массивы объявляют редко. Намного чаще объявление происходит как:

Code:
int a[5][5] = {
{0, 1, 2, 3, 4},
{6, 0, 1, 2, 3},
{7, 6, 0, 1, 2},
{8, 7, 6, 0, 1},
{9, 8, 7, 6, 0}};

это я сразу же данный массив заполнить решил, хотя можно было и просто int a[5][5]; написать
Вот для такого объявления твой код работать не будет...

P.S. И ты ещё говоришь, будто "указателей в моём коде нету" - а сам при этом инициализируешь массив через new Ab
P.S. Да и вообще, пусть Пакка узнает, что понятие "массив" в С++ - это почти то же самое, что и "указатель" Ab (а вот обратное неверно)


RE: С++, общая тема - gamecreator - 23.01.2012 21:20

(23.01.2012 19:36)Efrit Wrote:  Как это "не услышал"? Сам же и написал функцию, которая принимает на входе указатель 96-copy
не просто указатель, а массив. да и это тут ни при чем. параметром функции он от этого быть не перестанет. а указатель там или что-то другое - без разницы, суть та же.
(23.01.2012 19:36)Efrit Wrote:  Ну и что именно-то тебе в нём не понравилось?
почем я помню? помню, что не понравилось
(23.01.2012 20:07)Efrit Wrote:  Вот для такого объявления твой код работать не будет...
надо было явно сказать что для статического. но арифметика указателей от этого не появится. хотя в универсальной функции уже будет не обойтись без работы с указателями:
Code:
void foo(void *p, int n, bool dynamic_array)
{
    int tmp;
    if(dynamic_array)
    {
        int **arr = (int**) p;
        for(int i = 0; i < n; i++)
        {
            for(int k = i + 1; k < n; k++)
            {
                tmp = arr[i][k];
                arr[i][k] = arr[k][i];
                arr[k][i] = tmp;
            }
        }
    }
    else
    {
        int *arr = (int*) p;
        int i1, i2;
        for(int i = 0; i < n; i++)
        {
            for(int k = i + 1; k < n; k++)
            {
                i1 = i*n+k;
                i2 = k*n+i;
                tmp = arr[i1];
                arr[i1] = arr[i2];
                arr[i2] = tmp;
            }
        }
    }
}
(23.01.2012 20:07)Efrit Wrote:  И ты ещё говоришь, будто "указателей в моём коде нету" - а сам при этом инициализируешь массив через new Ab
пруф. я такого не говорил. я говорил что выделение и освобождение памяти за работу с указателями не считаю.
(23.01.2012 20:07)Efrit Wrote:  Да и вообще, пусть Пакка узнает, что понятие "массив" в С++ - это почти то же самое, что и "указатель" Ab (а вот обратное неверно)
да-да, все массивы - указатели. а вот насчет обратного - я бы сказал, что это зависит от задач. в тех же функциях с произвольным числом параметров указатель, не являвшийся массивом, может им стать.


RE: С++, общая тема - Solmyr2000 - 23.01.2012 23:41

Quote:почем я помню? помню, что не понравилось
:D
Впечатление с первого взгляда зачастую обманчиво. Нужно взлянуть повторно и хотя бы немного разобраться, чтобы могло "понравиться".
Если ты даже НЕ ПОМНИШЬ, почему тебе не понравилось - это просто глупый предрассудок. Если были бы какие-то объективные аргументы - тогда ладно Sm

Причём это опять не только к ЯП применимо, так везде - нельзя судить ни в коем случае по первому впечатлению, всё следует внимательно и подробно осмотреть/проанализировать. Многое из того, что мне сейчас нравится, с первого взгляда не понравилось (включая буст, хех).


RE: С++, общая тема - gamecreator - 24.01.2012 02:39

но сейчас мне тот буст даром не нужен, зачем с ним разбираться? понадобится - разберусь.


RE: С++, общая тема - packa - 04.02.2012 22:34

Как сделать четко прозрачную картинку? Без всяких муаров и рамочек

Image: c0aae5706b91t.jpg
Получилось только так.. Блин, весь день убил на эту ерунду. Самая главная проблема в том, что когда сохраняю в БМП графические редакторы его портят и создают то что вы видите на картинке (белую обводку по краям)

Поступал так:
1) Открыл картинку в GIMP
2) Выделил элипсом, скопировал на новый слой
    а) Сохранил в PNG с прозрачными краями
    б) Сохранил в БМП с белыми краями
    в) Сохранил в БМП с зелеными краями
    г) Сохранил в JPG c белыми краями

3) Открывал поочередно в билдере - TImage, \ Transparent = true
Результат далек от оригинала

4) Открыл паинт
    а) Сохранил в БМП с прозрачными краями (с заменой на белое, нынешний вариант)
    б) Сохранил в БМП с белыми краями
    в) Сохранил в БМП с зелеными краями
    г) Сохранил в БМП c белыми краями

5) Открывал поочередно в билдере - TImage, \ Transparent = true
Результат далек от оригинала

Ну как??? Как сделать четко?


RE: С++, общая тема - GreyGhost - 04.02.2012 23:04

packa
а AlphaBlend=true случайно не поможет?

просто не понял вопроса ((( .


RE: С++, общая тема - etoprostoya - 04.02.2012 23:09

Из перечисленных тобой форматов прозрачность поддерживает только PNG.
MS Paint (не Paint.NET) не поддерживает прозрачность, точнее там есть какое-то подобие прозрачности.
Quote:Как сделать четко прозрачную картинку? Без всяких муаров и рамочек
Тебе нужно сделать картинку или отобразить её в твоей программе? Это всё-таки разные вещи.


RE: С++, общая тема - FBX - 04.02.2012 23:30

Quote:Как сделать четко прозрачную картинку? Без всяких муаров и рамочек

Никак. Взять фотошоп, сделать негрубое выделение и скопировать на прозрачный фон. Сохранить в PNG. Научиться выводить PNG с полупрозрачностью.


RE: С++, общая тема - gamecreator - 04.02.2012 23:32

(04.02.2012 23:30)FBX Wrote:  Научиться выводить PNG с полупрозрачностью.
через GDI+, к примеру


RE: С++, общая тема - packa - 04.02.2012 23:49

Quote:Тебе нужно сделать картинку или отобразить её в твоей программе?
Ну картинку то легко - в ПНГ.
А вот чтобы БМП был однородным - не знаю ( БМП нужен как раз для того чтобы отобразить в программе, ибо с ПНГ сложнее.
Quote:Никак. Взять фотошоп, сделать негрубое выделение и скопировать на прозрачный фон. Сохранить в PNG.
Ну это все готово


RE: С++, общая тема - FBX - 05.02.2012 21:57

БМП изначально не поддерживает прозрачность, хотя в нём могло бы быть место ей. ГИФ, как и масочная прозрачность с одним каким-то "цветом прозрачности" - прошлый век и ещё и плодит кучу ненужных проблем. Можно порекомендовать формат TGA, поскольку его можно прочитать вручную без особых сложностей.

Но, похоже, тут всё настолько запущено...


RE: С++, общая тема - Efrit - 05.02.2012 23:01

packa, юзай формат png и библиотеку pngimage. Я как-то имел с ней дело - всё отлично сработало, никаких проблем не возникло.


RE: С++, общая тема - packa - 05.02.2012 23:15

Quote:Но, похоже, тут всё настолько запущено...
Вот только не надо так, это достаточно оскорбительно.

Efrit, спасибо, посмотрю.


RE: С++, общая тема - packa - 11.02.2012 11:47

Как сделать 2 Активных окна?
Равноправных так сказать.

Удалось только вывести 2 сразу, но одна неактивная, серая.


RE: С++, общая тема - gamecreator - 11.02.2012 18:21

напиши свою ось, в которой активных окон может быть больше одного (или только два). но мне почему-то кажется, что проблема не такая сложная, какой ты ее представляешь. зачем тебе это вообще?


RE: С++, общая тема - GreyGhost - 11.02.2012 21:33

активное окно это -
    окно на переднем плане(в большинстве случаев)
    окно ПОЛУЧАЮЩЕЕ сообщения от КЛАВИАТУРЫ(за редким исключением)
    ...
так что, packa, твое желание неосуществимо.

PS: у тебя есть хэндлы открытых окон, используй их для вывода


RE: С++, общая тема - packa - 13.02.2012 20:54

Неудобно тут уже спрашивать)
Но что делать =)

Простая подсветка кнопки. Думал что сделаю за 10 минут, ушел с головой на пару часов, так ничего путного не сделал.
Накостылял такой код
Code:
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
DoubleBuffered = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton1MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
SpeedButton1-> Glyph ->LoadFromFile("notme_2.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
SpeedButton1-> Glyph ->LoadFromFile("notme.bmp");
}

Он рабочий, но мне совсем не нравится его исполнение.
И к тому же, если перескочить быстро с кнопки на другую кнопку, форммув не сработает и кнопка останется подсвеченной.

Any Ideas?


RE: С++, общая тема - gamecreator - 13.02.2012 21:47

не легче ли определять какая кнопка находится под указателем и ее подсвечивать?


RE: С++, общая тема - packa - 13.02.2012 22:10

Нет) Я не могу сообразить как такое провернуть.
Например если делать через форммаусмув то координаты на кнопке прекращаются, а где они прекратились - тот еще геммор определить - многотонные Иф.
Это как я вижу.


RE: С++, общая тема - Efrit - 13.02.2012 22:39

packa Wrote:Нет) Я не могу сообразить как такое провернуть.

http://bit.ly/xoDRO9

Ну и плюс - событие OnMouseMove для всех кнопок сделай единым. Например, назначь его всем кнопкам как SpeedButton1MouseMove, а внутри него обращайся не к Button1, а к Sender (приведённому к классу TSpeedButton с помощью static_cast или dynamic_cast).


RE: С++, общая тема - gamecreator - 13.02.2012 23:15

и static TObject *previousSender чтобы возвращать картинку у предыдущей кнопки. главное проверять чтобы кнопка изменялась и не грузить попусту картинки.


RE: С++, общая тема - packa - 29.03.2012 19:59

Загружаю изображение, рисую его его на канве (Canvas->Drow)
Какими способами его можно повернуть?

Для упрощения - вид сверху, машинка поворачивает.


RE: С++, общая тема - Efrit - 29.03.2012 20:28

Насколько я помню, у VCL нету стандартных функций для "поворота канвы" (равно как и для "поворота картинки").
Так что - либо написать свою функцию поворота (это нетрудно), либо пользоваться сторонними библиотеками типа DirectX.


RE: С++, общая тема - gamecreator - 29.03.2012 21:29

если можно перейти к контексту устройства, то через GDI можно повернуть с помощью PlgBlt


RE: С++, общая тема - packa - 01.04.2012 18:29

Это снова я)

Нужно передать в функцию Двумерный массив int enemy_group[4][3]

void zahvat (массив, int a){
//Некоторые действия с массивом
a++;
}

На выход нужно переменную а.

Просто с переменными получалось, хоть и тяжело, а с массивом вообще ни в какую...
Гуглил, находил, ничего не понял.


RE: С++, общая тема - Efrit - 01.04.2012 18:47

Вот поэтому, Пакка, я и рекомендовал тебе читать про указатели - без них в C++ никуда. Знал, что понадобится...
Или, если бы ты юзал динамические массивы вместо статических (что я также рекомендовал) - то тебе бы и указатели не понадобились (а лишь ссылки).

Попробуй для начала написать функцию, которая меняет передаваемую в неё переменную. То есть: была у тебя какая-то int value = 5, затем ты вызвал функцию - и, вуаля, value стала равна уже не 5. Для этого тебе нужно прочитать про "передачу аргументов в функцию по значению, по указателю и по ссылке".

Если сможешь это сделать - то затем попробуй провернуть то же непотребство с одномерным массивом. Подсказка: помимо самого массива, в функцию также нужно будет передавать его размерность. И вот лишь затем, вернись к своему исходному двумерному массиву.

P.S. Я, конечно, могу и тупо написать необходимую тебе строчку вызова функции - но работать с этим массивом внутри самой функции ты вряд ли сможешь. Иначе бы ты уже заметил, что Игродел в сообщении #76 сделал именно то, что тебе и нужно 118


RE: С++, общая тема - gamecreator - 01.04.2012 19:23

массивы всегда передаются по ссылке из-за своей указательной природы. но! если одномерный массив можно передать как написав int *array, так и int array[], то n-мерный статический массив нельзя передать, не указав размеры n-1 его измерений, а в памяти он все равно выглядит как указатель на одномерный массив. я не пробовал, но может сработает шаблон:
Code:
template<int m, int n> void foo(int array[m][n])
{
// код функции
}



RE: С++, общая тема - packa - 02.04.2012 18:59

Вот что получилось, а получилось ничего Bad

PHP Code:
TForm1 *Form1;
void kakaya_to_functcia(int *[], int g); // объявляю функцию
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
        : 
TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
int kakoy_to_massiv[5]; // объявляю массив с 6 элементами
for (int i=0i<6i++){
     
kakoy_to_massiv[i]=i;  // присваиваю каждому значения 
}
kakaya_to_functcia(&kakoy_to_massiv6);  // вызываю функцию. Ссылка на адрес 1го элемента массива, 6 - длина
for (int i=0i<6i++){
Label1->Caption=Label1->Caption+kakoy_to_massiv[i];  // вывожу на экран
}
}
//----------------
void kakaya_to_functcia(int *[], int g){  // а - указатель на массив(не уверен насчет нужности квадратных скобок) и переменная длины массива
for (int i=0i<g,i++){
*(
a[]+i)=i+1;  // увеличиваю все элементы на 1, чтобы проверить
}
}
//--------------------------------------------------------------------------- 


Кстати не подскажите зачем сначала объявлять функцию
void kakaya_to_functcia(int *a [], int g);

а потом когда вызывать, по новой инициализировать указатель и переменную, или это я неправильно делаю?
void kakaya_to_functcia(int *a [], int g){}

gamecreator, спасибо, но шаблонов пока нет перспективе изучения


RE: С++, общая тема - Efrit - 02.04.2012 19:34

Пакка, про шаблоны пока забудь, рано тебе ещё в них копаться Ab И без них можно писать хороший код.

packa Wrote:Кстати не подскажите зачем сначала объявлять функцию
void kakaya_to_functcia(int *a [], int g);

а потом когда вызывать, по новой инициализировать указатель и переменную, или это я неправильно делаю?
void kakaya_to_functcia(int *a [], int g){}

Да, объявление функции должно повторять её "заголовок" (в большинстве случаев). Хотя я бы первым её параметром поставил одиночный указатель, а затем два int-параметра размерности двумерного массива... Не, можно и "указатель на указатель" передавать - если хочется внутри функции "как с массивом" работать. Как правило, это зависит от того, где именно у тебя объявлен массив - в стеке, или же в куче. Игродел почему-то любит создавать всё в куче, хотя создание чего-то в стеке - более правильный вариант.

И, блин, не просто int - а unsigned int! Moral Что, неужели я вот в этом сообщении зря распинался?

Да, зря ты меня опять не послушал Bad Я же недаром написал - вначале научись с помощью функций менять сторонние переменные, затем - одномерный массивы, и только потом - двумерные и N-мерные.
Серьёзно, Пакка. Если ты научишься делать это - то потом сам наверняка всё поймёшь. А то сейчас ты пытаешься сесть за руль гоночного болида, хотя ещё толком не научился ездить на обычном автомобиле...
(да, утрирую, но суть именно такова)



RE: С++, общая тема - packa - 02.04.2012 20:23

Quote:Что, неужели я вот в этом сообщении зря распинался?
Прошло слишком много времени (для меня) без практики, поэтому такие тонкости давно забыл Bad

Quote:Да, зря ты меня опять не послушал Bad Я же недаром написал - вначале научись с помощью функций менять сторонние переменные, затем - одномерный массивы, и только потом - двумерные и N-мерные.
Почему, как раз таки послушал)
Менять переменные через функцию меня Шуруп научил Sm (за что ему огромное спасибо)
Через ссылки.
Потом я несколько раз перечитал главы "Указатели и ссылки", "Передача указателей и ссылок в функции".
Конечно не идеально понял, но какое-то представление составил точно (для этого я писал комментарии в коде)
Попытался собрать передачу массива в функцию.

А вот двумерые массивы действительно пока не трогаю )

Да кстати, там можно легко передать массив через значения, но раз уж коснулся указателей, то хочу именно через них.


RE: С++, общая тема - gamecreator - 02.04.2012 21:27

(02.04.2012 18:59)packa Wrote:  а - указатель на массив(не уверен насчет нужности квадратных скобок)
сравни варианты записи:
int *a - указатель на начало массива (в данном примере). можно работать как с массивом
int a[] - массив (= указатель), по сути то же, что и выше, но я не знаю, можно ли его использовать как указатель
int *a[] - указатель на переменную, которая содержит указатель на начало массива (или адрес массива). для статических массивов бесполезен, т.к. им нельзя присвоить другую область памяти, а разыменовывать указатель все равно придется.
(02.04.2012 18:59)packa Wrote:  Кстати не подскажите зачем сначала объявлять функцию а потом когда вызывать, по новой инициализировать указатель и переменную?
не понял вопроса. что значит "по новой инициализировать" параметры функции?
(02.04.2012 19:34)Efrit Wrote:  Да, объявление функции должно повторять её "заголовок" (в большинстве случаев).
я бы сказал не "в большинстве случаев", а "по большей части". в объявлении функции можно указать только типы переменных, а имена им дать уже в определении.
(02.04.2012 19:34)Efrit Wrote:  затем два int-параметра размерности двумерного массива.
речь об одномерном массиве
(02.04.2012 19:34)Efrit Wrote:  Игродел почему-то любит создавать всё в куче
я люблю использовать подходящие вещи. если мне нужен массив неизвестной или переменной длины (или возможность управлять указателями на массивы), то я выделяю память. если определенной длины - объявляю массив.

(02.04.2012 20:23)packa Wrote:  Да кстати, там можно легко передать массив через значения
массив по значению нельзя передать. это указатель. элементы массива при изменении в функции будут меняться везде.


RE: С++, общая тема - Efrit - 02.04.2012 22:04

packa Wrote:Прошло слишком много времени (для меня) без практики, поэтому такие тонкости давно забыл Bad
Это не "тонкости", это вообще должно быть на уровне гигиены Ab Как "помыть руки перед едой". Если переменная содержит размер чего-либо (неважно чего), или же переменная является индексом массива - то её обязательно нужно объявлять как unsigned.

packa Wrote:Менять переменные через функцию меня Шуруп научил Sm (за что ему огромное спасибо) Через ссылки.
Передача по ссылке - это хорошо, но попробуй и передачу переменной (обычной переменной, не массива) через указатель.
Объясняю, что при этом произойдёт: (Click to View)
   
   
gamecreator Wrote:речь об одномерном массиве
Сорри, не заметил.

gamecreator Wrote:если мне нужен массив неизвестной или переменной длины (или возможность управлять указателями на массивы), то я выделяю память. если определенной длины - объявляю массив.
Создавать объекты в куче без особой надобности плохо, потому что это часто приводит к утечкам памяти. Например, после такой инициализации нельзя делать return - будет явная утечка памяти, равно как и при break с continue. Именно поэтому и придумали смарт-пойнтеры, чтобы вообще с кучей не работать...

P.S. Кстати, призываю всех пользоваться тегами [рhр][/рhр] для сишного кода - он его очень хорошо понимает, читать код с подсветкой намного приятнее.


RE: С++, общая тема - gamecreator - 02.04.2012 22:32

(02.04.2012 22:04)Efrit Wrote:  Это не "тонкости", это вообще должно быть на уровне гигиены Ab Как "помыть руки перед едой". Если переменная содержит размер чего-либо (неважно чего), или же переменная является индексом массива - то её обязательно нужно объявлять как unsigned.
я считаю, что это хоть и правильный способ, но слишком муторный. в С++ он оправдан, но в языках с более строгим приведением типов может доставлять неудобства в надобности явно приводить переменную к беззнаковому типу (к тому же, большинство таких языков отслеживают выход за рамки массива).
(02.04.2012 22:04)Efrit Wrote:  Создавать объекты в куче без особой надобности плохо, потому что это часто приводит к утечкам памяти.
только если потом эти массивы куда-нибудь переприсваивать, возвращать в результате функции и т.п. "открывающая скобка" new и "закрывающая скобка" delete для меня как для тебя индексы и размеры беззнаковых типов.
(02.04.2012 22:04)Efrit Wrote:  Например, после такой инициализации нельзя делать return - будет явная утечка памяти, равно как и при break с continue.
почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.


RE: С++, общая тема - Berserker - 02.04.2012 22:35

Вирт в Оберонах вообще убрал беззнаковый тип. Для 32 бит хватает и двухгигового размера, а для 64 знаковый тип неисчерпаем.

Quote:почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.
Всегда.


RE: С++, общая тема - gamecreator - 02.04.2012 22:40

если использовать goto - да, всегда. хотя контрпример привести не могу.


RE: С++, общая тема - Berserker - 02.04.2012 22:53

Дейкстра доказал, что любая программа может быть переписана без goto. Break/continue/return/raise - это goto разной степени ограниченности. У меня любой исходник без указанных. Размеры - до 15 килострок (Эра и WiseEval).


RE: С++, общая тема - gamecreator - 02.04.2012 23:05

хм, точно, так и есть.


RE: С++, общая тема - Efrit - 03.04.2012 10:55

gamecreator Wrote:почти всегда алгоритм можно построить таким образом, что он будет иметь ровно одну точку входа и одну точку выхода.
Да, я знаю.
Но это может привести к ухудшению читаемости кода: (Click to View)
   
   
Berserker Wrote:Вирт в Оберонах вообще убрал беззнаковый тип.
Ну и зря. Например, я хочу написать свой класс - динамический массив типа наподобие std::vector, с перегруженной операцией "квадратные скобки". И при этом, я хочу иметь нумерацию его элементов именно с нуля - дабы программист не мог обратиться к "отрицательному" элементу. И как же мне сделать это в Обероне, если там нету беззнакового типа?


RE: С++, общая тема - gamecreator - 03.04.2012 15:50

(03.04.2012 10:55)Efrit Wrote:  Согласись ведь, что такой код выглядит значительно лучше, чем если бы он составлялся без goto-подобных switch и return?
ай-яй-яй! как ты мог забыть про статический массив? он тут как нельзя кстати (и зачем вообще указатель передавать, это ведь не позволит передавать в функцию обычные значения; и почему это вдруг цифра (у тебя!!!) потребовала 32 бита?):
PHP Code:
charname_of_digit(unsigned char digit)  // функция возвращает название цифры в десятичной системе
{
   static 
char names[10][] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
   if (
digit >=&& digit <=9) return names[digit];
   else return 
0;

(03.04.2012 10:55)Efrit Wrote:  И как же мне сделать это в Обероне, если там нету беззнакового типа?
одна проверка, одно исключение


RE: С++, общая тема - Efrit - 03.04.2012 16:05

gamecreator Wrote:ай-яй-яй! как ты мог забыть про статический массив? он тут как нельзя кстати (и зачем вообще указатель передавать, это ведь не позволит передавать в функцию обычные значения; и почему это вдруг цифра (у тебя!!!) потребовала 32 бита?)
А причём здесь всё это? Как захотел объявить функцию, так и объявил. Понятное дело, что в реальности я всегда передаю обычные числа по значению... Ты смотри не на сигнатуру функции, а внутрь неё.
А приведённый тобой код содержит return Spiteful

gamecreator Wrote:одна проверка, одно исключение
Да я это прекрасно понимаю. Только в таком случае, ошибка будет обнаружена лишь на этапе исполнения программы. В то время как при использовании unsigned - уже на этапе компиляции!


RE: С++, общая тема - gamecreator - 03.04.2012 16:14

(03.04.2012 16:05)Efrit Wrote:  А приведённый тобой код содержит return Spiteful
ой. но это легко решаемо (тем более, что оказывается в многомерных массивах символов таки нужно указывать все размеры Bad хотя это логично, учитывая что в памяти они будут одномерными; более того, функция должна возвращать указатель на константу):
PHP Code:
const charname_of_digit(unsigned char digit)  // функция возвращает название цифры в десятичной системе
{
   static 
char names[11][6] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine",0};
   if (
digit <|| digit >10digit=10;
   return 
names[digit];



(03.04.2012 16:05)Efrit Wrote:  В то время как при использовании unsigned - уже на этапе компиляции!
только если ты напрямую впишешь туда отрицательную константу


RE: С++, общая тема - gamecreator - 03.04.2012 16:25

кстати в таком случае при ошибке возвратится не нулевой указатель, а пустая строка.
для возвращения нулевого указателя придется объявить переменную:
PHP Code:
const charname_of_digit(unsigned char digit)  // функция возвращает название цифры в десятичной системе
{
   static 
char names[10][6] = {"Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
   
char *result 0;
   if (
digit >=&& digit <=9result names[digit];
   return 
result;




RE: С++, общая тема - Efrit - 03.04.2012 17:08

Ну и чем твой получившийся код лучше моего? Ab Тебе приводится вводить не только дополнительную переменную, но и целый двумерный массив (кстати, нафига он static?) - и всё лишь ради того, чтобы избежать дублирования return-ов. Мне же проще использовать shared_ptr - и создавать ВСЁ в стеке, не парясь про утечки памяти при return-ах.


gamecreator Wrote:только если ты напрямую впишешь туда отрицательную константу

Да хотя бы и так. Всё равно, я получу сообщение об ошибке уже на этапе компиляции, и гарантированно исправлю её - в то время как ты узнаешь об ошибке лишь тогда, когда пользователь доберётся до критичной строчки кода. А это может случиться через сто лет, если код большой и всевозможных ситуаций много. Есть разница?

К тому же - сейчас, даже если вписать на место unsigned-переменной просто int-переменную (не обязательно константу) - то нормальные компиляторы всегда выдадут варнинг. То есть ошибка в любом случае будет замечена...


RE: С++, общая тема - packa - 03.04.2012 17:11

Ну вот я кажется уже неплохо стал ориентироваться в ссылках и указателях (за что всем спасибо)
Но все же вопросы остались.

Состряпал код, который внезапно работал только на половину.
Входной массив 012345, выходной 123455.
В функции прибавляю к каждому значению ячейки 1 (как видите последний не захотел)

После долгих попыток заставить работать последний адрес массива я решил попробовать вывести этот самый злосчастный адрес на форму, и посмотреть на него (может прозрение случилось бы,не сидеть же сложа руки =) ).
Корректно вывести не получилось(как мне кажется он неверен.) (Кстати не подскажите как?)
Но код внезапно заработал! Почему?
P.S. В книге "Моя первая программа на C/C++ - Нейбауэр А. " хорошо написано, а вот в справочнике "Программирование в C++ Builder А. Я. Архангельский" я недостаточно понял =(


RE: С++, общая тема - Efrit - 03.04.2012 17:50

Пакка, ещё бы твой пример работал Ab У тебя массив kakoy_to_massiv состоит лишь из 5 элементов, в то время как ты пытаешься "пройтись" вплоть до шестого его элемента (индексы от 0 до 5 включительно, то бишь всего 6 штук).

Да и объявлена функция kakaya_to_functcia как-то коряво. По уму, она должна принимать два элемента: первый - это адрес первого элемента массива, а второй - это размерность этого массива (в данном случае - число 5). В подобных функциях размерность массива должна всегда быть одним из её параметров, учти это.

Кстати, скажу тебе по секрету: запись &kakoy_to_massiv[0] эквивалентна записи kakoy_to_massiv 118 Поскольку "имя массива" в С - это и есть адрес его первого элемента.
Вот тебе отличная статья про массивы и указатели.

P.S. А вообще здорово, что ты пытаешься разобраться с указателями. Это, возможно, самый сложный шаг в освоении C++.


RE: С++, общая тема - Berserker - 03.04.2012 18:08

Quote:выглядит значительно лучше, чем если бы он составлялся без goto-подобных switch и return?
char* result = "error";
switch ...
case ... result = ...
case ... result = ...
return result.

В Обероне массивы начинаются с нуля, отрицательные константные смещения запрещены, границы проверяются во время выполнения.


RE: С++, общая тема - Efrit - 03.04.2012 18:20

Berserker Wrote:char* result = "error";
switch ...
case ... result = ...
case ... result = ...
return result.
Ну так switch-то ты в итоге никуда и не дел Ab

Berserker Wrote:В Обероне массивы начинаются с нуля, отрицательные константные смещения запрещены, границы проверяются во время выполнения.
Так я же говорил про свой класс "массива", а не про "встроенные" обероновские массивы... В C++ я увижу подобную ошибку уже при компиляции, а в Обероне - лишь при исполнении.


RE: С++, общая тема - packa - 03.04.2012 18:25

Quote:У тебя массив kakoy_to_massiv состоит лишь из 5 элементов, в то время как ты пытаешься "пройтись" вплоть до шестого его элемента (индексы от 0 до 5 включительно, то бишь всего 6 штук).
Наследие со школы <_< там мне не давали использовать нулевую ячейку...
Спасибо, долго бы еще ломал моцк...
Quote:Да и объявлена функция kakaya_to_functcia как-то коряво.
Да, так изначально так и было. После ошибки развернул баталию по отлову, для чего и включил указатель на 5-ый элемент.
Quote:Кстати, скажу тебе по секрету: запись &kakoy_to_massiv[0] эквивалентна записи kakoy_to_massiv Поскольку "имя массива" в С - это и есть адрес его первого элемента.
Да,читал про это Sm Только вот невнимательно, из-за чего написал &kakoy_to_massiv и схлопотал ошибку Sm

---
А есть не сложное объяснение почему оно все таки отображает то что мне нужно?
И как в этом помогает бесполезный код по выводу адреса? С ним даже
PHP Code:
//*g=7; //Попытка изменить 5-ый элемент вручную 

   начинает работать
Что происходит при присвоении kakoy_to_massive[5]? Ведь ее как бы не существует, сама создается? (или переходит снова на 0 элемент, затирая старое значение?)

Да, статья хорошая, только поздно ее увидел Sm

Quote:P.S. А вообще здорово, что ты пытаешься разобраться с указателями. Это, возможно, самый сложный шаг в освоении C++.
P.S.Я больше директив и классов боюсь =) Пока толком не подошел ни к чему.


RE: С++, общая тема - gamecreator - 03.04.2012 18:29

(03.04.2012 17:08)Efrit Wrote:  Ну и чем твой получившийся код лучше моего? Ab
одной точкой выхода
(03.04.2012 17:08)Efrit Wrote:  Тебе приводится вводить не только дополнительную переменную
одна переменная в 4 байта ничего не решает.
(03.04.2012 17:08)Efrit Wrote:  но и целый двумерный массив
у тебя он тоже есть, хоть и занимает немного меньше места. и его существование не очевидно.
(03.04.2012 17:08)Efrit Wrote:  кстати, нафига он static?
чтобы существовал после выхода из функции
(03.04.2012 17:08)Efrit Wrote:  и всё лишь ради того, чтобы избежать дублирования return-ов.
ты поставил задачу - я ее выполнил. нечего ставить задачи в отрыве от контекста
(03.04.2012 17:08)Efrit Wrote:  Мне же проще использовать shared_ptr - и создавать ВСЁ в стеке, не парясь про утечки памяти при return-ах.
мне же проще использовать сборщик мусора и создавать ВСЁ в куче, не парясь про утечки памяти при чем-угодно.
(03.04.2012 17:08)Efrit Wrote:  в то время как ты узнаешь об ошибке лишь тогда, когда пользователь доберётся до критичной строчки кода.
в отладочной (а может и не только) сборке программа скажет в какой строке какого файла произошло исключение и покажет стек вызовов. более того, в режиме отладки среда отловит исключение и перенесет меня к той строке кода, которая его вызвала.
(03.04.2012 17:08)Efrit Wrote:  К тому же - сейчас, даже если вписать на место unsigned-переменной просто int-переменную (не обязательно константу) - то нормальные компиляторы всегда выдадут варнинг.
ты этого никогда не сделаешь в силу своих правил выбора типов переменных. так и кто-либо другой не выберет беззнаковый тип из-за отсутстия у него этих правил. более того, через отрицательный индекс можно реализовать дополнительную функциональность, например доступ к элементу с конца массива.


RE: С++, общая тема - Berserker - 03.04.2012 18:38

Quote:Ну так switch-то ты в итоге никуда и не дел
Переключатель - структурная конструкция и может быть развёрнута в if-elsif-else-end.

Quote:Так я же говорил про свой класс "массива", а не про "встроенные" обероновские массивы... В C++ я увижу подобную ошибку уже при компиляции, а в Обероне - лишь при исполнении.
Отрицательный константный индекс будет запрещён при компиляции.
Наличие знаковых типов ведёт к неизбежным преобразования знаковых к беззнаковым. То есть int и uint - числа из разных плоскостей. Избыточная сложность изучения, применения и использования при работе более одного автора проигрывает простому решению в стиле Калашникова.


RE: С++, общая тема - gamecreator - 03.04.2012 18:38

(03.04.2012 18:20)Efrit Wrote:  Ну так switch-то ты в итоге никуда и не дел Ab
так он и не противоречит единственности точки выхода
(03.04.2012 18:25)packa Wrote:  Что происходит при присвоении kakoy_to_massive[5]? Ведь ее как бы не существует, сама создается? (или переходит снова на 0 элемент, затирая старое значение?)
нет, ты обращаешься к левой памяти (в данном случае ты попал на допустимый адрес, но в реальности не все 2 ГБ виртуальной страницы имеют свой физический аналог и ты также легко мог бы попасть на несуществующий адрес и получил бы что-то типа "память не может быть "written"").
(03.04.2012 18:25)packa Wrote:  P.S.Я больше директив и классов боюсь =)
ну там все проще


RE: С++, общая тема - Efrit - 03.04.2012 19:14

packa Wrote:Что происходит при присвоении kakoy_to_massive[5]? Ведь ее как бы не существует, сама создается? (или переходит снова на 0 элемент, затирая старое значение?)
Ты пытаешься обратиться к &kakoy_to_massive[4] + sizeof(int) адресу памяти. В данном случае тебе повезло, но в реальности по этому адресу может лежать всё что угодно.

packa Wrote:Я больше директив и классов боюсь =)
Каких ещё "директив" - компиляторных, что ли? Их и не нужно всё помнить, лишь с десяток самых распространённых. На классы пока забей - лучше вначале хорошо выучи "чистый" С, без "плюсовых" фич.


gamecreator Wrote:одной точкой выхода
Спасибо, кэп. Я про читабельность говорил.

gamecreator Wrote:у тебя он тоже есть, хоть и занимает немного меньше места. и его существование не очевидно.
Неправда, у меня никакого двумерного массива нету. Из всех char-строчек типа "Zero" инициализируется лишь одна - та, что и будет в итоге возвращена.

gamecreator Wrote:чтобы существовал после выхода из функции
Это я знаю. Я не понимаю, зачем ему "после выхода из функции" нужно существовать 118

gamecreator Wrote:мне же проще использовать сборщик мусора и создавать ВСЁ в куче, не парясь про утечки памяти при чем-угодно.
Это не "сборщик мусора" - это ты, наоборот, руками всё убираешь. Я и не говорю, что это плохо (сам так постоянно делаю), но при громоздкой классовой структуре для меня проще работать со смарт-пойнтерами.

gamecreator Wrote:в отладочной (а может и не только) сборке программа скажет в какой строке какого файла произошло исключение и покажет стек вызовов. более того, в режиме отладки среда отловит исключение и перенесет меня к той строке кода, которая его вызвала.
А причём тут отладка? Ведь всё равно нет 100% гарантии того, что в ней тебе удастся создать такую ситуацию, при которой исполнится незаметная на первый взгляд, но критичная строчка. Придётся писать юнит-тесты, в то время как компилятор даст тебе 100% уверенность в своей правоте.

gamecreator Wrote:более того, через отрицательный индекс можно реализовать дополнительную функциональность, например доступ к элементу с конца массива.
Дык и я смогу. У меня здесь просто будет варнинг, но я его пропущу. Я же и не говорю, что варнинг - это плохо...


Berserker Wrote:Отрицательный константный индекс будет запрещён при компиляции.
Кем запрещён? С какого это перепугу, кто-то запретит указывать мне отрицательный индекс в операторе "квадратных скобок" в моём собственном классе?


RE: С++, общая тема - Berserker - 03.04.2012 19:21

В Обероне. И там нет перегрузки операторов.


RE: С++, общая тема - Efrit - 03.04.2012 19:46

Плохо, что нету - это очень удобная штука.

Да даже и без перегрузки. Вот пример на C++: (Click to View)
   
Как видно - никаких сложностей, ошибка будет обнаружена сразу. А что в Обероне будет? Rolleyes Ведь в нём в сигнатуре функции get_value_of_array должен стоять int...


RE: С++, общая тема - Berserker - 03.04.2012 20:25

Там будет ловушка на этапе выполнения.


RE: С++, общая тема - Efrit - 03.04.2012 20:29

Вот видишь - на этапе выполнения. А некоторые ошибки на этапе выполнения хрен отловишь, в то время как ошибки при компиляции видны сразу.
Поэтому unsigned - это гуд. И чего в нём такого "сложного", мне решительно непонятно.


RE: С++, общая тема - gamecreator - 03.04.2012 21:07

(03.04.2012 19:14)Efrit Wrote:  Я про читабельность говорил.
компактность, прозрачность.
(03.04.2012 19:14)Efrit Wrote:  Неправда, у меня никакого двумерного массива нету. Из всех char-строчек типа "Zero" инициализируется лишь одна - та, что и будет в итоге возвращена.
но они-то все равно в памяти хранятся все. вот если бы ты это через шаблон делал - тогда да, одна строка.
(03.04.2012 19:14)Efrit Wrote:  Я не понимаю, зачем ему "после выхода из функции" нужно существовать 118
чтобы возвращаемый указатель указывал на строку, а не на мусор
(03.04.2012 19:14)Efrit Wrote:  Это не "сборщик мусора" - это ты, наоборот, руками всё убираешь. Я и не говорю, что это плохо (сам так постоянно делаю), но при громоздкой классовой структуре для меня проще работать со смарт-пойнтерами.
спасибо, я знаю, что в с++ нет сборщика мусора. к сожалению Bad
(03.04.2012 20:29)Efrit Wrote:  Поэтому unsigned - это гуд. И чего в нём такого "сложного", мне решительно непонятно.
никто и не говорил, что в нем "что-то сложное"


RE: С++, общая тема - Efrit - 03.04.2012 22:21

gamecreator Wrote:чтобы возвращаемый указатель указывал на строку, а не на мусор
Ну ё-моё. Да не нужен там никакой static Ab Ты ведь производишь копирование для указателя result, созданного в куче... Не веришь мне - запусти код без static и убедись.

gamecreator Wrote:спасибо, я знаю, что в с++ нет сборщика мусора. к сожалению
Тогда не стоит писать "мне же проще использовать сборщик мусора и создавать ВСЁ в куче" Rolleyes

gamecreator Wrote:никто и не говорил, что в нем "что-то сложное"
Как это "никто"? Берс это говорил, прямым текстом...


RE: С++, общая тема - gamecreator - 03.04.2012 22:43

(03.04.2012 22:21)Efrit Wrote:  Ты ведь производишь копирование для указателя result, созданного в куче...
где там куча? куча не используется
(03.04.2012 22:21)Efrit Wrote:  Не веришь мне - запусти код без static и убедись.
хм... интересно, я думал код будет транслироваться по-другому.
(03.04.2012 22:21)Efrit Wrote:  Тогда не стоит писать "мне же проще использовать сборщик мусора и создавать ВСЁ в куче" Rolleyes
так мне же проще на c# писать, чем на с++
(03.04.2012 22:21)Efrit Wrote:  Как это "никто"? Берс это говорил, прямым текстом...
а, точно. ничего сложного в изучении нет, здесь согласен


RE: С++, общая тема - Berserker - 03.04.2012 22:52

А при проектировании интерфейсов, структур и функций есть. Если использована int, то uint не подходят. Если uint, то любое int-рассчитанное значение не подходит. При сравнении/присваивании нужны либо проверки времени исполнения, либо потеря безопасности.


RE: С++, общая тема - gamecreator - 03.04.2012 23:55

не всегда. если значения укладываются в диапазон от 0 до 231-1, то разницы нет.


RE: С++, общая тема - Berserker - 04.04.2012 00:05

И как это проверить? Проверками времени исполнения.


RE: С++, общая тема - gamecreator - 04.04.2012 00:25

нет, алгоритмически


RE: С++, общая тема - Berserker - 04.04.2012 00:38

Ты о формальном доказательстве программ и о людях, которые не ошибаются и о надёжных данных внешних? )


RE: С++, общая тема - gamecreator - 04.04.2012 01:07

я о том, что если нормальные значения переменной не могут выходить за тот диапазон, то будь то int или uint - диапазон нормальных значений не изменится.


RE: С++, общая тема - NIKr0m@nceR - 04.04.2012 10:03

Дайте я тоже поучаствую в споре: хотите не обращаться куды попало - юзайте вектор, например. при попытке лезть в отрицательные элементы получите исключение.


RE: С++, общая тема - Efrit - 04.04.2012 12:47

gamecreator Wrote:так мне же проще на c# писать, чем на с++
А причём здесь C#? Тема-то про С++, а не про него. До этого ты про него ни слова не говорил, а потом вдруг сказал про сборку мусора Rolleyes

Berserker Wrote:А при проектировании интерфейсов, структур и функций есть. Если использована int, то uint не подходят. Если uint, то любое int-рассчитанное значение не подходит.
Дык проектировать всё надо в едином стиле, тогда и проблем не будет.

NIKr0m@nceR Wrote:Дайте я тоже поучаствую в споре: хотите не обращаться куды попало - юзайте вектор, например. при попытке лезть в отрицательные элементы получите исключение.
Угу, я об этом говорил на 4-й странице темы. Ещё бы хотел добавить, что стоит использовать модификатор const так часто, как это возможно (особенно для классовых функций).


RE: С++, общая тема - packa - 04.04.2012 18:18

Научился передавать двумерный массив в функцию и работать далее как с одномерным:
Вопрос: внутри функции можно ли работать как-нибудь в более привычном виде?

Под более привычным имеется ввиду представить его как двумерный.

Слышал про массив указателей, вроде как должно писаться вместо (int *a) вот это:(int **a) Но я не понял как передать ему двумерный массив &kakoy_to_massiv[0][0] - так указывается только на начало массива, без одного 0 передается int *[5]
Блин, чувствую что я очень близко, но вот не могу дотянуть)


RE: С++, общая тема - gamecreator - 04.04.2012 19:21

(04.04.2012 18:18)packa Wrote:  Научился передавать двумерный массив в функцию и работать далее как с одномерным
неправильно ты массив передаешь. нужно просто название переменной записать
(04.04.2012 18:18)packa Wrote:  Вопрос: внутри функции можно ли работать как-нибудь в более привычном виде?
я уже писал об этом:
(01.04.2012 19:23)gamecreator Wrote:  если одномерный массив можно передать как написав int *array, так и int array[], то n-мерный статический массив нельзя передать, не указав размеры n-1 его измерений
т.е. тебе придется записать параметр как int a[][5] или int a[5][5]
(04.04.2012 18:18)packa Wrote:  Слышал про массив указателей, вроде как должно писаться вместо (int *a) вот это:(int **a)
это для динамических массивов, тебе оно не поможет.


RE: С++, общая тема - Efrit - 04.04.2012 19:54

packa Wrote:Вопрос: внутри функции можно ли работать как-нибудь в более привычном виде?
Если не использовать шаблоны функций, а также хаки типа reinterpret_cast - то для статического массива никак нельзя, увы.

gamecreator Wrote:т.е. тебе придется записать параметр как int a[][5] или int a[5][5]
Ничего подобного! Игродел, не вводи человека в заблуждение.
Например, этот код прекрасно сработает как для двумерных статических, так и для динамических массивов: (Click to View)
   
А вообще, создавать подобным образом "динамические массивы" - это не есть гут. Потому что это массив указателей, а не "двумерный массив". У двумерного массива все его "строки" будут иметь одинаковую длину, а в случае с массивом указателей - это условие не обязательно будет верно...

Функция, изначально заточенная под статические массивы, всегда будет работать и с динамическим массивом тоже (если в ней не указывать размер массива явно). А вот обратное будет неверно, поэтому лучше всегда работать со стеком. Для "нормальных" динамических массивов в C++ уже давно придуман std::vector, и изобретать велосипед тут незачем. Именно вектор я тебе, Пакка, и рекомендую использовать.


RE: С++, общая тема - gamecreator - 04.04.2012 21:15

(04.04.2012 19:54)Efrit Wrote:      Add_10_to_all_values_of_array(*dynamic_array, 4, 7); // добавляем 10 ко всем элементам динамического массива
не вводи человека в заблуждение. этим вызовом ты прибавишь 10 к первой строке массива и неизвестно чему, находящемуся в памяти после этой строки.
(04.04.2012 19:54)Efrit Wrote:  А вообще, создавать подобным образом "динамические массивы" - это не есть гут. Потому что это массив указателей, а не "двумерный массив". У двумерного массива все его "строки" будут иметь одинаковую длину, а в случае с массивом указателей - это условие не обязательно будет верно...
как создашь - так и будет. зубчатые массивы никто не заставляет создавать.


RE: С++, общая тема - Efrit - 04.04.2012 21:48

gamecreator Wrote:не вводи человека в заблуждение. этим вызовом ты прибавишь 10 к первой строке массива и неизвестно чему, находящемуся в памяти после этой строки.
Ничего подобного. Ты бы хоть код скомпилировал для начала, прежде чем утверждать.
Если длина всех строк одинакова, то приведённый мною код всегда будет работать корректно.

gamecreator Wrote:как создашь - так и будет. зубчатые массивы никто не заставляет создавать.
Двумерный массив по определению обязан быть зубчатым. Если строки двумерного массива имеют разную длину - то это набор каких-то различных одномерных массивов, а не "матрица". Пакке нужна именно матрица, и для неё мой код вполне подходит.


RE: С++, общая тема - gamecreator - 05.04.2012 01:20

(04.04.2012 21:48)Efrit Wrote:  Ничего подобного. Ты бы хоть код скомпилировал для начала, прежде чем утверждать.
Если длина всех строк одинакова, то приведённый мною код всегда будет работать корректно.
я верю, что в большинстве случаев он будет работать корректно. на что ты рассчитывал писав свою функцию:
- тот, кто будет его вызывать, создаст строки матрицы строго в порядке от 0 до n-1
- менеджер памяти выделит каждый блок строго за предыдущим, без разрывов
(04.04.2012 21:48)Efrit Wrote:  Если строки двумерного массива имеют разную длину - то это набор каких-то различных одномерных массивов, а не "матрица".
а если у них одинаковая длина? согласен, что это матрица?


RE: С++, общая тема - NIKr0m@nceR - 05.04.2012 11:47

Ну вообще, имхо, спор бессмысленный ибо странно говорить что является труЪ двумерным массивом если одно является одномерным массивом наделенным необходимым функционалом а второе фактически массивом массивов т.е. более общим объектом.
бтв, Efrit, а мне больше нравятся квадратные скобочки ибо читабельнее.
gamecreator, что значит "в большинстве случаев"? многомерные массивы именно так и создаются, я и говорю, что по факту это одномерный массив с необходимым функционалом.


RE: С++, общая тема - gamecreator - 05.04.2012 12:56

NIKr0m@nceR, сначала посмотри о чем речь и как создается динамический массив в примере. одномерный массив не равно массив массивов


RE: С++, общая тема - NIKr0m@nceR - 05.04.2012 13:23

gamecreator, я посмотрел перед тем как писать, я и не говорю что равно. я говорю что называть какой-то из них двумерным массивом а другой нет ибо это нечто иное не вполне верно. Двумерный массив как контейнер для, к примеру, интов может быть реализован, как я понимаю, двумя способами: создать одномерный массив m*n и прикрутить интерфейс или создать массив указателей на массивы. когда пишется int example_array[2][4] то фактически компиллятор выделяет массив на 8 интов и позволяет к ним обращаться как example_array[i][j] что, вообще говоря, является переобозначением для удобства конструкции *(example_array + 4 * i + j). Насчет динамического - проглядел, там действительно что попало функция сделает. я вообще не понимаю, это две разные конструкции, зачем х в одну кучу валить неясно.

P.S. я не вдавался в подробности, но по стандарту 11 запилили контейнер array вроде. У него функционал какой? Его использовать разумнее чем вектор или нет?


RE: С++, общая тема - gamecreator - 05.04.2012 14:29

судя по всему, std::array - аналог статического массива.


RE: С++, общая тема - gamecreator - 05.04.2012 17:15

но std::array все равно не решает проблему передачи массива в функцию (впрочем, как и любой другой шаблонный метод), т.к. параметры шаблона должны быть известны на этапе компиляции.


RE: С++, общая тема - Efrit - 05.04.2012 17:37

gamecreator Wrote:но std::array все равно не решает проблему передачи массива в функцию (впрочем, как и любой другой шаблонный метод), т.к. параметры шаблона должны быть известны на этапе компиляции.

http://rsdn.ru/forum/cpp/4642026.1.aspx

Quote:Вы можете работать с ним точно также, как вы работаете с массивами в С, то есть используя указатель на первый элемент массива, который получается с помощью функции-члена класса data, и размер массива, который получается с помощью функции-члена класса size.



RE: С++, общая тема - gamecreator - 05.04.2012 17:56

и как же ты передашь 2-мерный массив (array<array,...>,...>)?


RE: С++, общая тема - Efrit - 06.04.2012 19:01

Понятия не имею, я с std::array не работал Ab Мне и вектора вполне хватает.


RE: С++, общая тема - packa - 06.04.2012 21:11

У вас тут защита от нубов стоит?
Ловил баги 3,5 часа, выбился из сил, решил тут отпоститься. Только начал писать пост, одну за другой нашел 2 ошибки(!)

И это при том что проверял построчно, и с выводом в метки.


RE: С++, общая тема - Efrit - 06.04.2012 22:07

packa Wrote:У вас тут защита от нубов стоит?
   
packa Wrote:Ловил баги 3,5 часа, выбился из сил, решил тут отпоститься. Только начал писать пост, одну за другой нашел 2 ошибки
Так что в итоге-то, все проблемы решил? 118


RE: С++, общая тема - Berserker - 06.04.2012 22:15

Efrit, жжёшь Sm


RE: С++, общая тема - packa - 06.04.2012 22:36

Quote:Так что в итоге-то, все проблемы решил?
На данном этапе. Rolleyes

Как и советуют, разбил программу на много задач поменьше, вот потихоньку реализую.


RE: С++, общая тема - packa - 07.04.2012 18:12

Как в играх делаются апгрейды?
Кроме как каждой башне впаять все сразу и включать\выключать флагами ничего не придумал.
Например как реализованы абилки существ в героях?
(я делаю мини-стратегию Sm )


RE: С++, общая тема - Efrit - 07.04.2012 18:35

packa Wrote:Как в играх делаются апгрейды?
Кроме как каждой башне впаять все сразу и включать\выключать флагами ничего не придумал.

Сначала не мог допереть, какое отношение этот вопрос имеет к C++ Ab А потом вспомнил, что с классами-то ты ещё не знаком... Поскольку если бы ты был с ними знаком, то такого вопроса у тебя бы не возникло Rolleyes

Так что, Пакка, придётся тебе про них начать читать. Вначале читай только основы - что вообще такое "класс" и "объект", чем public отличается от private, ну и что такое "конструктор" и "деструктор". Всё, знаний об этих шести понятиях на первых порах будет более чем достаточно...

Вот только "вставить классы" в программу, изначально проектируемую без ООП, вряд ли получится. Проще будет переписать всё с нуля - если, конечно, код ещё не очень большой...


RE: С++, общая тема - Sav - 07.04.2012 18:54

packa Wrote:Например как реализованы абилки существ в героях?
В основном так, как реализовывать не следует, - в определённых местах кода проверяется номер существа, и если он такой-то - проигрывается способность.


RE: С++, общая тема - gamecreator - 07.04.2012 19:34

Efrit, т.е. ты предлагаешь реализовать систему грейдов через наследование? а если система грейдов не является деревом?


RE: С++, общая тема - packa - 07.04.2012 20:01

Если что, поясню -

Грейды самые обычные, не тот у меня уровень знаний пока чтобы изголяться и придумывать что то дейcтвительно интересно-замудренное)

Атака I -> Атака II -> Атака III
Защита I -> Защита II -> Защита III
Лазерный прицел I
Зажигательный снаряд I


RE: С++, общая тема - gamecreator - 07.04.2012 20:13

так это просто раскачка. сконвертируй грейды в числовые параметры и храни и подставляй в игровые формулы уже эти параметры.


RE: С++, общая тема - packa - 07.04.2012 21:08

Не только, вот лазерный прицел например - целая функция по отрисовки (громко сказано правда, там ~2 строчки, но все же...)

А с атакой ты, в общем то прав. Просто на 1 лвл сделать 0 прибавку и все)


RE: С++, общая тема - Efrit - 07.04.2012 21:10

gamecreator Wrote:Efrit, т.е. ты предлагаешь реализовать систему грейдов через наследование? а если система грейдов не является деревом?

gamecreator, хотя это действительно один из возможных вариантов, но я предлагаю Пакке не его Sm Иначе бы я в своём предыдущем сообщении хотя бы упомянул слово "наследование"...

Не, я предлагаю намного проще:

- ввести в классе "башня" unsigned-переменную "уровень";
- тело конструктора этого класса сделать таким: { Init(...); }, где Init - это публичная функция инициализации объекта класса;
- в функцию Init среди параметров передавать этот "уровень"; (чтобы можно было создавать башню с заданным уровнем развития)
- когда нужно "улучшить" или "ухудшить" башню - просто вызываем Init с новыми параметрами, и всё.

P.S. Разумеется, Init должна содержать в себе "прорисовку башни" и прочие необходимые операции.


RE: С++, общая тема - gamecreator - 07.04.2012 22:44

(07.04.2012 21:08)packa Wrote:  Не только, вот лазерный прицел например - целая функция по отрисовке
для одноуровневых грейдов можно хранить наличие


RE: С++, общая тема - packa - 10.04.2012 22:24

Слишком много массивов(
Из за чего я не могу поймать ячейку с багом. Из-за чего просто не понимаю чем он вызван)
Например условие
if (a!=b){}
else{Label1->Caption=a;Label2->Caption=b}
после чего получаю а = 100 b = 500 (грубо говоря...) Ну невозможно же!
   
и Лейблы тоже почти не спасают в поиске багов - они перетираются другими значениями. (это не взаимоисключающий параграф)

Как дальше быть? Как искать баги в этой ситуации?
P.S. На одиночных переменных все работало (1 враг, 1 выстрел, 1 башня... )


RE: С++, общая тема - gamecreator - 10.04.2012 23:17

(10.04.2012 22:24)packa Wrote:  Например условие
if (a!=b){}
else{Label1->Caption=a;Label2->Caption=b}
после чего получаю а = 100 b = 500 (грубо говоря...) Ну невозможно же!
у тебя лейблы перетираются, можно получить вообще что угодно. а чтобы знать чем они перетираются - всегда пиши что именно за значение ты выводишь: лейбл="значение а="+а
(10.04.2012 22:24)packa Wrote:  и Лейблы тоже почти не спасают в поиске багов - они перетираются другими значениями.
так один лейбл - один вывод. или лейбл+=вывод
(10.04.2012 22:24)packa Wrote:  Как дальше быть? Как искать баги в этой ситуации?
изучай искусство дебага. и вообще, у тебя однопоточное приложение!
(10.04.2012 22:24)packa Wrote:  1 враг, 1 выстрел, 1 башня
TD пишешь?


RE: С++, общая тема - packa - 11.04.2012 00:36

Quote:так один лейбл - один вывод
Циклов много, самое интересное внутри Sm
Quote:лейбл+=вывод
Там таймер на полсекунды =(
Если увеличить, то слишком долго ждать нужной ситуации
Quote:TD пишешь?
Больше всего на ТД походит) А так не совсем ее собирался делать, но вылилось в это


RE: С++, общая тема - gamecreator - 11.04.2012 00:44

и вообще, какие еще лейблы? мессаджбокс же!

еще можно писать в файл


RE: С++, общая тема - packa - 11.04.2012 00:49

Quote:мессаджбокс же!
Это который как справка появляется окном? нее...
Я со многими параметрами одновременно работаю, да и в случае с += он ведь не проканает - стопит процесс

Quote:еще можно писать в файл
А вот это хорошая мысль.


RE: С++, общая тема - gamecreator - 11.04.2012 01:04

(11.04.2012 00:49)packa Wrote:  в случае с += он ведь не проканает
ээ... причем тут += ?


RE: С++, общая тема - packa - 11.04.2012 10:32

Ну я к тому, что месседж бокс то подходит только для одного значения. Если нужен именно полная строка изменений,то он не подойдет.
for(int i=0,; i<5, i++){
massiv[i]+=5;
MessageBox(massiv[i]);
}
В результате чего мы получим по 1 значению.после каждого нажатия на ок.(цикл ведь не будет дальше двигаться?..)
А как "накапливать" в него я не знаю, да и зачем, в лабел или файл удобнее с этой точки зрения (только вот в метку похоже не влезет.)"


RE: С++, общая тема - gamecreator - 11.04.2012 13:03

в чем проблема собирать текст в строку и после цикла вывести его?


RE: С++, общая тема - packa - 16.04.2012 13:53

Ура! Начал писать блок-схему и отловил один из багов Sm
А вы рисуете ее? Что думаете, нужная штука?


RE: С++, общая тема - Sav - 16.04.2012 15:10

Ни разу не рисовал. По мне, сам код выглядит куда нагляднее, если его, конечно, хорошо писать, т. е. не пренебрегать правилами оформления, подробно комментировать, максимально разбивать на функции и т. д. Да и если плохо - всё равно по мне проще всё в голове держать.


RE: С++, общая тема - gamecreator - 16.04.2012 15:25

блок-схема? для современных масштабов? быстрее уж написать программу без этой блок-схемы, чем просто ее нарисовать. для программирования есть более адекватные способы записи. те же диаграммы действий.

не говоря о uml


RE: С++, общая тема - packa - 16.04.2012 18:46

Quote:для программирования есть более адекватные способы записи.
Не слышал...
Quote:Ни разу не рисовал. По мне, сам код выглядит куда нагляднее, если его, конечно, хорошо писать, т. е. не пренебрегать правилами оформления, подробно комментировать, максимально разбивать на функции и т. д. Да и если плохо - всё равно по мне проще всё в голове держать.
Ну наверное я для такого еще слишком низкого уровня. Вот глянул на схемку, сразу видно в какой ветке может быть ошибка.
А в самой программе как то все нагромождено слишком
Хотя стараюсь писать по правилам, по крайней мере по тем, которые я знаю)
Image: 677539a9fa49t.jpg


RE: С++, общая тема - Efrit - 16.04.2012 20:25

Пакка, я видел твою ПМ-ку, но посмотреть как следует всё никак не могу - некогда Bad Через неделю отпуск, тогда уж точно гляну (а может, и раньше).
Пока лишь бросилась в глаза пара нюансов:

- форматирование кода. Тело какого-то блока всегда должно отделяться табуляцией от его заголовка, а у тебя даже на последнем скриншоте оно стоит на той же самой вертикали. Да и большинство программистов (в том числе и я) всё-таки отдают "открывающей скобке" целую строку, хотя это дело вкуса.

- объявление переменных. На кой чёрт они объявлены внутри h-файла, когда больше никаких cpp-шников у тебя нету? Ты ведь явно не библиотеку пишешь. А то я при чтении основного исходника никак не мог понять, что же значит та или иная переменная... Не говоря уже про то, что глобальные переменные сами по себе не есть гут.

- утечки памяти. Твоя программа вылетает через десяток-другой секунд после запуска, всё увеличивая размер выделяемой для себя памяти. Глянул код - и точно, в нём в четырёх местах используется new, но нету ни одного delete...


RE: С++, общая тема - packa - 16.04.2012 21:17

Quote:Тело какого-то блока всегда должно отделяться табуляцией от его заголовка, а у тебя даже на последнем скриншоте оно стоит на той же самой вертикали.
Он тогда слишком уходит вправо, из-за чего даже поскроллить не получается - двойной скролл по вертикали и горизонтали.
Quote:Да и большинство программистов (в том числе и я) всё-таки отдают "открывающей скобке" целую строку, хотя это дело вкуса.
Хм, специально поднимал этот вопрос(везде где только мог) ), большинство мне сказало что открывающую лучше всего ставить в той же строке, что и заголовок. Хотя тут наверное больше как понравится. Нужно пробовать)
Quote:На кой чёрт они объявлены внутри h-файла, когда больше никаких cpp-шников у тебя нету?
Удобно же - все переменные там, в любой момент можно посмотреть где какая. Специльное место для них) Отдельно и цивильно так сказать Sm
Quote:Не говоря уже про то, что глобальные переменные сами по себе не есть гут.
Почему? Тогда остро стоит проблема доставание или передача в цикл. А тут элементарно - где хочешь там и вызывай.
Quote:Глянул код - и точно, в нём в четырёх местах используется new, но нету ни одного delete...
А вот с этим не знаком Sm блок с картинками просто копировал, но как он подлинно работает не знаю.
   

Quote:Через неделю отпуск, тогда уж точно гляну (а может, и раньше).
Пока лишь бросилась в глаза пара нюансов:
Не над, этого пока вполне достаточно. Этого и хотел)


RE: С++, общая тема - Efrit - 16.04.2012 21:43

Quote:Он тогда слишком уходит вправо, из-за чего даже поскроллить не получается - двойной скролл по вертикали и горизонтали.
Зато читается в сто раз лучше. А размер шрифта можно и уменьшить, если что. И боюсь спросить, что же это за редактор такой - который не позволяет скроллить колёсиком мышки по вертикали, если есть полоса прокрутки по горизонтали?

Quote:Хм, специально поднимал этот вопрос(везде где только мог) ), большинство мне сказало что открывающую лучше всего ставить в той же строке, что и заголовок. Хотя тут наверное больше как понравится.
Почти во всех IDE по C++ обе скобки по умолчанию выделяются в отдельные строки. Думаю, что это о чём-то говорит. Хотя, например, на MSDN большинство кода написано иначе...

Quote:Удобно же - все переменные там, в любой момент можно посмотреть где какая. Специальное место для них) Отдельно и цивильно так сказать.
Когда код чужой, а переменных много - то это нифига не удобно. Не говоря уже про то, что это нарушает принцип инкапсуляции. Любой объект (в том числе и переменная) должен быть доступен лишь в той части кода, где он действительно необходим - и точка. В остальных участках кода он не должен быть виден.

Quote:Почему? Тогда остро стоит проблема доставание или передача в цикл. А тут элементарно - где хочешь там и вызывай.
Мне лень расписывать, "почему". Погугли, об этом до меня ещё тысячу раз говорили. А главная причина всё в том же - ухудшается инкапсуляция. А в C++, абсолютно любой код можно написать вообще без какого-то использования глобальных переменных.

Quote:А вот с этим не знаком Sm блок с картинками просто копировал, но как он подлинно работает не знаю.
new - выделяет блок памяти в ОЗУ, необходимый для создания объекта используемого класса, и вызывает конструктор этого класса.
delete - вызывает деструктор используемого класса, и затем очищает ранее использованную область памяти.


RE: С++, общая тема - Efrit - 16.04.2012 22:27

Пакка, вот тебе хорошая статья, в которой наглядно объясняется, почему глобальные переменные - зло.
Там, правда, примеры приводятся на Делфи - но суть от этого не меняется.


RE: С++, общая тема - gamecreator - 16.04.2012 23:47

(16.04.2012 20:25)Efrit Wrote:  - форматирование кода.
это особая, уличная магия стиль Пакки: у команды, которая применяется к блоку, такой же отступ, как и у блока. мутноъ!
(16.04.2012 20:25)Efrit Wrote:  Да и большинство программистов всё-таки отдают "открывающей скобке" целую строку
не льсти нам, еретиков больше, чем ты думаешь.
(16.04.2012 20:25)Efrit Wrote:  Не говоря уже про то, что глобальные переменные сами по себе не есть гут.
ну смотря когда. иногда можно и сделать одну. errno же
(16.04.2012 21:17)packa Wrote:  большинство мне сказало что открывающую лучше всего ставить в той же строке, что и заголовок
это еретики K&R. выбирай. рекомендую стиль Олмана
(16.04.2012 21:17)packa Wrote:  Тогда остро стоит проблема доставание или передача в цикл.
подробнее, в чем именно проблема?
(16.04.2012 21:17)packa Wrote:  блок с картинками просто копировал, но как он подлинно работает не знаю.
код в студию


RE: С++, общая тема - NIKr0m@nceR - 17.04.2012 01:04

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


RE: С++, общая тема - gamecreator - 17.04.2012 02:21

с каким еще заголовком?

googlecode Wrote:Spaces vs. Tabs
Use only spaces, and indent 2 spaces at a time.
FFFFUUUUUUUUUUUUUUUU!!!!!! ничего не разберешь же


RE: С++, общая тема - NIKr0m@nceR - 17.04.2012 03:45

ну в смысле
void do_something_awesome (double with_this, char* and_this) {
    //Some extraordinry stupid bytes of code with no effect
}
а при переносе скобки 1-я строка станет явно отделенной от второй. на мой взгляд итак ок.
а про табы - ну, очевидно, что надо пробелы тыкать (универсальность там прочая фигня, править удобно) а сам я с детства на 3-х был. когда вижу табуляции по 6 пробелов у меня глаза разъезжаются и я ниче не понимаю Bad с 3х на 2 перешел вообще не заметив разницы Sm


RE: С++, общая тема - Deo - 17.04.2012 07:49

Это "египетские скобки".
Image: h6IEf.jpg
По-моему такой код читать сложнее
Code:
try{
    //код
    if (условие) {
        //код
    }
    //код
    if (другоеусловие) {
        //немного кода
        if (еще одно условие){
            //код
        }
    }                
}
catch (Exception ex){
    //обработка исключения
}
чем такой:
Code:
try
{
    //код
    if (условие)
    {
        //код
    }
    //код
    if (другоеусловие)
    {
        //немного кода
        if (еще одно условие)
        {
            //код
        }
    }                
}
catch (Exception ex)
{
    //обработка исключения
}

В последнем варианте проще визуально сопоставить открывающиеся и закрывающиеся скобки.


RE: С++, общая тема - Sav - 17.04.2012 09:35

gamecreator Wrote:
googlecode Wrote:Spaces vs. Tabs
Use only spaces, and indent 2 spaces at a time.
FFFFUUUUUUUUUUUUUUUU!!!!!! ничего не разберешь же
А по-моему, 2 пробела - самое удобное. Просто нужно использовать моноширинный шрифт. 4 пробела долго писать и всё разъезжается, на мобильных устройствах становится абсолютно нечитаемым.


RE: С++, общая тема - NIKr0m@nceR - 17.04.2012 10:29

Deo, На самом деле, это вопрос привычки. я и в первом варианте неплохо это понимаю. С другой стороны, первый вариант намного компактнее что позволяет охватывать взглядом больший кусок кода. А вообще, на вкус и цветстиль товарищей нет.


RE: С++, общая тема - gamecreator - 17.04.2012 10:58

(17.04.2012 03:45)NIKr0m@nceR Wrote:  а при переносе скобки 1-я строка станет явно отделенной от второй.
так это же хорошо, улучшает читаемость
(17.04.2012 03:45)NIKr0m@nceR Wrote:  править удобно
ни разу не удобно. с табами - удобно править, да.
(17.04.2012 09:35)Sav Wrote:  Просто нужно использовать моноширинный шрифт.
а кто-то не использует?
(17.04.2012 09:35)Sav Wrote:  4 пробела долго писать
таб же


RE: С++, общая тема - Sav - 17.04.2012 11:22

Таб во всех, по крайней мере андроидских, виртуальных клавиатурах упрятан чёрти-где, если вообще есть.


RE: С++, общая тема - gamecreator - 17.04.2012 12:04

ну тогда это вынужденное ограничение, а не удобство


RE: С++, общая тема - Sav - 17.04.2012 12:10

Удобство в принципе создаётся из вынужденных ограничений.


RE: С++, общая тема - NIKr0m@nceR - 17.04.2012 13:43

gamecreator, я хз как табы могут быть удобнее пробелов. все равно в начало строки я перемещаюсь кнопкой хоум. ну не вижу я в чем их сила Bad К тому же если у функции параметры в несколько строк писать и отступ некратен величине таба то придется миксовать что не айс.
а насчет скобки - я написал, что итак достаточно отделены имхо


RE: С++, общая тема - Efrit - 22.04.2012 23:33

Столкнулся с забавным фактом. Не знаю, баг ли это или фича - но штука странная.

В общем, если в опциях компилятора gcc включена поддержка c++11, то перестаёт работать инклуд математических констант из <cmath> - например, хорошо всем знакомых M_PI и M_E.
Если отключить поддержку нового стандарта - то всё инклудится хорошо, как и раньше...

Пришлось использовать <qmath.h> (в Qt) - с ним такой проблемы не наблюдается. Вроде бы, это полный аналог <cmath>, или всё же нет?


RE: С++, общая тема - gamecreator - 23.04.2012 00:01

а почему не math.h?


RE: С++, общая тема - Efrit - 23.04.2012 00:05

Так это же то же самое, что и <cmath>.


RE: С++, общая тема - gamecreator - 23.04.2012 01:13

точно? ты проверял? из math.h тоже не подтягивает пи и е? потому что cstring и string.h насколько я знаю - далеко не то же самое.

попробуй открыть cmath и посмотреть, может там надо какой-нибудь идентификатор объявить типа USE_MATH_DEFINES? кажись, еще в 9-й студии нужно было объявлять (не говоря уже о всех последующих)


RE: С++, общая тема - Efrit - 23.04.2012 08:56

gamecreator Wrote:точно? ты проверял?
Да точно, это известный факт. Это же C++, в ней вся стандартная сишная библиотека не имеет расширений. Недаром же ты пишешь просто include <iostream>... Вот, Википедия подтверждает.

gamecreator Wrote:из math.h тоже не подтягивает пи и е?
Тоже, естественно.

gamecreator Wrote:попробуй открыть cmath и посмотреть, может там надо какой-нибудь идентификатор объявить типа USE_MATH_DEFINES?
Легко сказать - открой и посмотри Sm Там же повсюду условная компиляция с огромным числом констант... Да и прекрасно всё работает без каких-либо идентификаторов, если не под c++11 пытаться.

gamecreator Wrote:кажись, еще в 9-й студии нужно было объявлять (не говоря уже о всех последующих)
А причём здесь студия? Я же не под ней работаю...


RE: С++, общая тема - gamecreator - 23.04.2012 09:12

(23.04.2012 08:56)Efrit Wrote:  Недаром же ты пишешь просто include <iostream>
вот как раз iostream не равно iostream.h. поэтому и пишу
(23.04.2012 08:56)Efrit Wrote:  Легко сказать - открой и посмотри Sm Там же повсюду условная компиляция с огромным числом констант...
поиск люди придумали для таких ситуаций. я же находил в свое время. если совсем невмоготу - скинь файл, найти - дело пары минут.
(23.04.2012 08:56)Efrit Wrote:  А причём здесь студия? Я же не под ней работаю...
так файлы то могут быть и похожи. или по-твоему они их с нуля переписывают для каждого компилятора?


RE: С++, общая тема - Efrit - 23.04.2012 09:25

Википедия Wrote:Каждый заголовочный файл из стандартной библиотеки языка Си включен в стандартную библиотеку языка C++ под различными именами, созданных путем отсечения расширения .h и добавлением 'c' в начале, например, 'time.h' стал 'ctime'.
Это же, кстати, относится и к <cstring>. А вот <iostream> - да, всё-таки другой.

gamecreator Wrote:если совсем невмоготу - скинь файл, найти - дело пары минут.
Ну вот, погляди 118


RE: С++, общая тема - gamecreator - 23.04.2012 09:46

cmath Wrote:#include <math.h>
они в math.h


RE: С++, общая тема - Efrit - 23.04.2012 09:56

И что с этого? Даже если компиляция действительно идёт по указанной тобой ветке, то константы оттуда всё равно не инклудятся...

Ты лучше скажи мне, по какой ветке идёт компиляция при включении c++11 Ab


RE: С++, общая тема - gamecreator - 23.04.2012 10:01

math.h включается всегда в cmath. так что:
Code:
#if defined(_USE_MATH_DEFINES) && !defined(_MATH_DEFINES_DEFINED)
#define _MATH_DEFINES_DEFINED

/* Define _USE_MATH_DEFINES before including math.h to expose these macro
* definitions for common math constants.  These are placed under an #ifdef
* since these commonly-defined names are not part of the C/C++ standards.
*/

/* Definitions of useful mathematical constants
* M_E        - e
* M_LOG2E    - log2(e)
* M_LOG10E   - log10(e)
* M_LN2      - ln(2)
* M_LN10     - ln(10)
* M_PI       - pi
* M_PI_2     - pi/2
* M_PI_4     - pi/4
* M_1_PI     - 1/pi
* M_2_PI     - 2/pi
* M_2_SQRTPI - 2/sqrt(pi)
* M_SQRT2    - sqrt(2)
* M_SQRT1_2  - 1/sqrt(2)
*/

#define M_E        2.71828182845904523536
#define M_LOG2E    1.44269504088896340736
#define M_LOG10E   0.434294481903251827651
#define M_LN2      0.693147180559945309417
#define M_LN10     2.30258509299404568402
#define M_PI       3.14159265358979323846
#define M_PI_2     1.57079632679489661923
#define M_PI_4     0.785398163397448309616
#define M_1_PI     0.318309886183790671538
#define M_2_PI     0.636619772367581343076
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2    1.41421356237309504880
#define M_SQRT1_2  0.707106781186547524401

#endif  /* _USE_MATH_DEFINES */


более того,
math.h Wrote:These are placed under an #ifdef since these commonly-defined names are not part of the C/C++ standards.
что означает, что в gcc их быть не может, основная фишка gcc - стандарты же


RE: С++, общая тема - Efrit - 23.04.2012 10:08

Да причём здесь вообще всё это? Ну да, объявлены они в math.h, и что?
Про проблему с использованием c++11 здесь ни слова не сказано...

Есичо, я пробовал дефайнить _USE_MATH_DEFINES перед инклудом <cmath> - не помогало.


RE: С++, общая тема - gamecreator - 23.04.2012 10:16

значит для с++11 есть другой набор заголовков или его особенности влияют на компиляцию этих.


RE: С++, общая тема - Efrit - 23.04.2012 10:18

Вот и я про что. Либо что-то дополнительно надо дефайнить, либо действительно баг.
По крайней мере, в Qt помогает инклуд <qmath.h> - а вот как быть в "чистом" gcc, я даже не знаю...


RE: С++, общая тема - gamecreator - 23.04.2012 10:32

самому писать нужные функции Sm


RE: С++, общая тема - Efrit - 23.04.2012 10:49

gamecreator Wrote:самому писать нужные функции Sm

Ага, как же Rolleyes

Code:
#ifdef WAR_TIME
   #undef M_PI
   #define M_PI  4  // в военное время число PI может достигать четырёх
#endif  // WAR_TIME



RE: С++, общая тема - NIKr0m@nceR - 24.04.2012 10:30

у меня в мингв это выглядит так
Code:
/* Traditional/XOPEN math constants (double precison) */
#ifndef __STRICT_ANSI__
#define M_E        2.7182818284590452354
#define M_LOG2E        1.4426950408889634074
#define M_LOG10E    0.43429448190325182765
#define M_LN2        0.69314718055994530942
#define M_LN10        2.30258509299404568402
#define M_PI        3.14159265358979323846
#define M_PI_2        1.57079632679489661923
#define M_PI_4        0.78539816339744830962
#define M_1_PI        0.31830988618379067154
#define M_2_PI        0.63661977236758134308
#define M_2_SQRTPI    1.12837916709551257390
#define M_SQRT2        1.41421356237309504880
#define M_SQRT1_2    0.70710678118654752440
#endif
может 11 очень ревностно относится к стандарту и шаг влево/вправо влекут расстрел?


RE: С++, общая тема - gamecreator - 24.04.2012 12:25

на каждый ifndef найдется свой undef


RE: С++, общая тема - packa - 25.04.2012 01:21

Не дадите ссылку на статью по динамическим массивам? Да, слоупочу, но все что нашел - базовые, как объявить, и очень вкратце как использовать.


RE: С++, общая тема - gamecreator - 25.04.2012 01:43

это слишком "далеко"?


RE: С++, общая тема - Efrit - 25.04.2012 01:45

packa, в Вики всё отлично расписано: http://ru.wikipedia.org/wiki/Vector_(C++)

Хотя, для полноценного понимая вектора нужно всё-таки знать, что такое "шаблоны"...


RE: С++, общая тема - gamecreator - 25.04.2012 02:00

Efrit, так вектор это объект, а не динамический массив. тогда больше подойдет статья по указателям (или эта: англ(оригинал)/рус (игнорируем убогую венгерскую нотацию в начале статьи))


RE: С++, общая тема - GrayFace - 27.04.2012 14:36

Не знаю, как внутри реализован Vector, но думаю, что массивом, соответственно он имеет даже побольше прав называться "динамический массив", чем указатель. По крайней мере для меня, больше привыкшего к нормальным языкам со встроенными динамическими массивами.


RE: С++, общая тема - packa - 27.04.2012 14:48

Прямо таки у вас отлично Noob Protection работает! Sm Спасибо))

P.S. Научился динамическому расширению динамического массива (лол) )
Делаю это так: При нужде увеличить
1)создаю еще один массив с такой же размерностью,
2)копирую в него все значения данного массива
3) удаляю данный массив
4) создаю новый массив с размерностью х+1
5) копирую из массива - фантома все значения обратно
6) удаляю массив фантом
7) присваиваю свеже созданной ячейке переменную
8) Вот )

Насколько корректен такой алгоритм?
Насколько он быстр?
У меня пока около 7-8 массивов, и даже 1 трехмерный. Как оно будет с современным компом?


RE: С++, общая тема - Efrit - 27.04.2012 16:18

месье знает толк в извращениях! ©

Ужас какой. Такой алгоритм точно никуда не годится.
Например, если тебе придётся "динамически расширять массив" внутри рекурсивной функции, то при больших размерах исходного массива тебе тупо не хватит оперативной памяти, и возникнет переполнение стека.

Уж проще вектор освоить, реально Ab Нету в нём ничего сложного...


RE: С++, общая тема - packa - 27.04.2012 16:30

Я еще фишку прикручивал, что если идет удаление ячейки посередине массива, то все сдвигается. Так что это еще лайт-версия)

Quote:Уж проще вектор освоить, реально Ab Нету в нём ничего сложного...
Ну не знаю) Я даже в название впереть не могу, с каких щей это вектор?) Вектор это такая линия со стрелочкой)
Сразу ассоциации с канвой, ну никак не с массивами)

То бишь я не могу его представить . А массив штука изьюзаная мной вдоль и поперек, мое родное)) Хоть какие то представления имеются.

И еще, чтобы мой пост не был лишен смысла:
Я всю отрисовку делаю через Canvas->Drow, и каждые 10мс закрашиваю черным прямоугольником на весь экран - из за чего все довольно некрасиво мигает. Any ideas?


RE: С++, общая тема - gamecreator - 27.04.2012 22:53

(27.04.2012 14:36)GrayFace Wrote:  Не знаю, как внутри реализован Vector, но думаю, что массивом, соответственно он имеет даже побольше прав называться "динамический массив", чем указатель.
я имел ввиду, что указатель ближе к голому динамическому массиву, чем вектор.
(27.04.2012 14:48)packa Wrote:  Насколько корректен такой алгоритм?
Насколько он быстр?
он крайне корректный и крайне медленный. для ускорения можно сразу создавать новый массив нового размера, копировать, удалять старый и переприсваивать. но так теряется корректность и могут быть проблемы с освобождением памяти. вот в чем С лучше С++ - так это в выделении памяти. обрати внимание на функции calloc, realloc, free.

и на файл memory.h

(27.04.2012 16:30)packa Wrote:  с каких щей это вектор?) Вектор это такая линия со стрелочкой)
вспомни его координаты
(27.04.2012 16:30)packa Wrote:  Any ideas?
в C# элементу управления (по крайней мере, форме) можно установить двойную буферизацию. поищи это.


RE: С++, общая тема - Efrit - 27.04.2012 23:10

gamecreator Wrote:в C# элементу управления (по крайней мере, форме) можно установить двойную буферизацию. поищи это.

В плюсовой VCL тоже. this->DoubleBuffered = true, если в синтаксисе не опечатался...


RE: С++, общая тема - etoprostoya - 27.04.2012 23:32

Кто-нибудь знает программы для вычисления числа Пи или других констант с большой точностью? С открытыми исходниками очень желательно.


RE: С++, общая тема - Efrit - 27.04.2012 23:57

Image: bb1658a0185ff273d8a1a79611d7b470.png

Программу теперь, думаю, можно написать и самому Ab


RE: С++, общая тема - etoprostoya - 28.04.2012 00:17

Как смешно.


RE: С++, общая тема - Efrit - 28.04.2012 00:31

А что смешного? Вики утверждает, что именно эта формула и используется для точного расчёта числа Пи на обычных ПК.


RE: С++, общая тема - etoprostoya - 28.04.2012 01:11

Я программы спрашивал, а не формулу. Хочу сравнить.


RE: С++, общая тема - gamecreator - 28.04.2012 01:16

так зачем тебе программа? есть же число пи со скольки угодно знаками


RE: С++, общая тема - etoprostoya - 28.04.2012 01:19

Я хочу сравнить производительность разных алгоритмов вычисления числа Пи.

Само число Пи я не собираюсь вычислять, если вы это имеете в виду.


RE: С++, общая тема - packa - 28.04.2012 07:11

Quote:в C# элементу управления (по крайней мере, форме) можно установить двойную буферизацию. поищи это.
Quote:В плюсовой VCL тоже. this->DoubleBuffered = true, если в синтаксисе не опечатался...
Да я слышал, и уже использовал, но здесь почему то совершенно не работает!
Пробовал по разному и this->DoubleBuffered = true и DoubleBuffered = true и Form1->DoubleBuffered=true
И в разным местах: онпаинт, онкриэйт...

Сорс нужно?


RE: С++, общая тема - Efrit - 28.04.2012 13:46

etoprostoya Wrote:Я хочу сравнить производительность разных алгоритмов вычисления числа Пи.
Само число Пи я не собираюсь вычислять, если вы это имеете в виду.
Так нету этих "алгоритмов", насколько я понимаю. Это число по готовым формулам и вычисляют...

packa Wrote:Пробовал по разному и this->DoubleBuffered = true и DoubleBuffered = true и Form1->DoubleBuffered=true
И в разным местах: онпаинт, онкриэйт...
Ab
Это одна и та же запись. Потому что все "события формы" - это методы класса TForm, в котором Form1 и играет роль this. Но this - это более универсальная запись, она не изменится при переименовании Form1 в какую-нибудь my_favorite_Form. Поэтому, более каноничен первый вариант.

И прописывать это надо лишь один раз, в конструкторе формы. Почему не работает - хз. Приведи код того фрагмента, где ты раскрашиваешь всё своим "чёрным прямоугольником" (кстати, нафига?)


RE: С++, общая тема - totkotoriy - 28.04.2012 13:46

Может кто подскажет как оптимизировать код для alpha.dll?
Нагружает проц. вот эта функция, которая вычисляет каждый пиксель с альфа каналом
Code:
static int Draw( int Type, image *pImage, draw_info *pInfo )
{
    int screenW=GetSystemMetrics(SM_CXSCREEN);
    int screenH=GetSystemMetrics(SM_CYSCREEN);
    if( pInfo->screen_size.x != screenW || pInfo->screen_size.y != screenH )
        return OriginalDraw( Type, pImage, pInfo );

    static char LastNames[8][13] = { {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} };
    static int CurLastName = 0;

    if( g_bPrint )
    {
        for( int i = 0; i < 8; i++ )
            if( strcmp( pImage->name, LastNames[i] ) == 0 )
                goto draw;

        strncpy( LastNames[CurLastName], pImage->name, 12 );
        LastNames[CurLastName][12] = 0;
        aprintf( WHITE, "draw %s\n", LastNames[CurLastName] );
        CurLastName++;
        if( CurLastName >= 8 )
            CurLastName = 0;
    }
draw:

    map<image_name,new_image*>::iterator Rep = g_Replace.find( image_name(pImage->name) );
    if( Rep == g_Replace.end() )
        return OriginalDraw( Type, pImage, pInfo );

    new_image *pNewImage = Rep->second;

    // center image
    vector ImagePos = pInfo->pos - pInfo->pos0 + (pImage->total_size - pNewImage->size)/2;

    // crop image
    vector Pos = pInfo->pos;
    vector Size = pInfo->size;
    rect_cross( &Pos, &Size, ImagePos, pNewImage->size );
    rect_cross( &Pos, &Size, vector( 0, 0 ), vector( screenW, screenH ) );

    vector Pos0 = Pos - ImagePos;

    color16 *pOld = &pInfo->pscreen[Pos.y*screenW + Pos.x];
    colorRGBA *pNew;
    if( pInfo->horz_invert )
        pNew = &pNewImage->data[(Pos0.y+1)*pNewImage->size.x - Pos0.x];
    else
        pNew = &pNewImage->data[(Pos0.y  )*pNewImage->size.x + Pos0.x];
       for( int y = 0; y < Size.y; y++ )
    {
        for( int x = 0; x < Size.x; x++ )
        {
            if( ( *pNew & 0xFFFFFF ) == 0xFFFF ) // color for replacement
            {
                color16 New = pInfo->color;
                if( New )
                *pOld = MakeColor16( GetRed  (*pOld) + GetAlpha(*pNew)*(GetRed  (New) - GetRed  (*pOld))/256,
                                     GetGreen(*pOld) + GetAlpha(*pNew)*(GetGreen(New) - GetGreen(*pOld))/256,
                                     GetBlue (*pOld) + GetAlpha(*pNew)*(GetBlue (New) - GetBlue (*pOld))/256 );
            }
            else
                *pOld = MakeColor16( GetRed  (*pOld) + GetAlpha(*pNew)*(GetRed  (*pNew) - GetRed  (*pOld))/256,
                                     GetGreen(*pOld) + GetAlpha(*pNew)*(GetGreen(*pNew) - GetGreen(*pOld))/256,
                                     GetBlue (*pOld) + GetAlpha(*pNew)*(GetBlue (*pNew) - GetBlue (*pOld))/256 );
            pOld++;
            if( pInfo->horz_invert )
                pNew--;
            else
                pNew++;
        }

        pOld += screenW - Size.x;
        if( pInfo->horz_invert )
            pNew += pNewImage->size.x + Size.x;
        else
            pNew += pNewImage->size.x - Size.x;
    }
    return 0;
}
Не могу найти место где можно упростить вычисления или заменить логику. Пытался также сделать многопоточность с помощью openMP, но пока не ничего не получается да и это сильно не поможет, т.к. ядро 2,4 ггц не должно нагружаться на 100%...


RE: С++, общая тема - Sav - 28.04.2012 13:56

Можно вместо "/256" написать ">> 8", может компилятор сам не оптимизирует. И ещё я бы не стал использовать методы для обращения к пикселям в таком низкоуровневом процессе.

Да и класс для цвета зря используется.

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


RE: С++, общая тема - Efrit - 28.04.2012 14:04

Сложно сказать, но по виду - возможно, тормозит функция MakeColor16 и её вызов. Зачем там одни и те же касты выполняются дважды?
Да и само решение какое-то корявое - каждый пиксель менять. Хотя других я и не знаю.

Попробуй закомментить вызовы этой функции и посмотреть - меньше нагрузка стала?


RE: С++, общая тема - packa - 28.04.2012 15:06

Code:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
rhis->DoubleBuffered=true;
}
Code:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        ammo = new Graphics::TBitmap;
        ammo->LoadFromFile("ammo.bmp");
Form1->Canvas->Brush->Color=(TColor)RGB(0,0,0);
       Form1->Canvas->Rectangle(0,0,ClientWidth,ClientWidth);
/*Много кода и отрисовок*/
   delete ammo;
}

Quote:Это одна и та же запись.
Угу, но вдруг глючит) лучше уж проверить.

http://zalil.ru/33150201
Вот на всякий случай - прошу в код даже не вглядываться) данный сорс только чтобы показать как мерцает.


RE: С++, общая тема - totkotoriy - 28.04.2012 15:07

(28.04.2012 13:56)Sav Wrote:  Можно вместо "/256" написать ">> 8", может компилятор сам не оптимизирует. И ещё я бы не стал использовать методы для обращения к пикселям в таком низкоуровневом процессе.

Да и класс для цвета зря используется.

Короче, слишком высокоуровневый код, как по мне, неуместный для такого процесса.
Я просто не думаю, что перевод всего на низкий уровень существенно повысит скорость. Дело не в сложности расчетов, а в их количестве. Вот если бы перенести эти расчеты на графический процессор или придумать другую логику.
А что значит >>? Просто я не в одном языке нормально не шарю.
(28.04.2012 14:04)Efrit Wrote:  Попробуй закомментить вызовы этой функции и посмотреть - меньше нагрузка стала?
Я это и написал, просто привел всю функцию для наглядности.

Может ещё есть в какой-нибудь libpng уже готовая функция для наложения альфа канала?
Хотел ещё новые библиотеки zlib и libpng в GCC пропихнуть, но у них изменился синтаксис, а править у меня мозгов пока не хватит, просто думал тоже мож чего там оптимизировали.
Может вообще через openGL попробовать?


RE: С++, общая тема - packa - 28.04.2012 15:12

Quote:(кстати, нафига?)
Иначе следы будут. Ужасные)
Если не трудно, помести в комметарий эту строчку ( Form1->Canvas->Rectangle(0,0,ClientWidth,ClientWidth); ), и увидишь)


RE: С++, общая тема - totkotoriy - 28.04.2012 16:13

Упростил чуть чуть:
Code:
for( int y = 0; y < Size.y; y++ )
    {
        for( int x = 0; x < Size.x; x++ )
        {
            
            ro1 = GetRed  (*pOld);
            rn1 = GetRed  (*pNew);
            go1 = GetGreen  (*pOld);
            gn1 = GetGreen  (*pNew);
            bo1 = GetBlue  (*pOld);
            bn1 = GetBlue  (*pNew);
            an1 = GetAlpha(*pNew);
            if( ( *pNew & 0xFFFFFF ) == 0xFFFF ) // color for replacement
                        {
                color16 New = pInfo->color;
                if( New )
                *pOld = MakeColor16( GetRed  (*pOld) + GetAlpha(*pNew)*(GetRed  (New) - GetRed  (*pOld))/256,
                                     GetGreen(*pOld) + GetAlpha(*pNew)*(GetGreen(New) - GetGreen(*pOld))/256,
                                     GetBlue (*pOld) + GetAlpha(*pNew)*(GetBlue (New) - GetBlue (*pOld))/256 );
            }
            else
            {
            NewRed = ro1 + an1*(rn1 - ro1)/256;
            NewGreen = go1 + an1*(gn1 - go1)/256;
            NewBlue = bo1 + an1*(bn1 - bo1)/256;
                *pOld = MakeColor16( NewRed, NewGreen, NewBlue);
            }
            pOld++;
            if( pInfo->horz_invert )
                pNew--;
            else
                pNew++;
        }
Производительность выросла как минимум в 2 раза Dance3 по сему несказанно счастлив 109. Может что еще придумаю.


RE: С++, общая тема - Sav - 28.04.2012 16:17

totkotoriy Wrote:Я просто не думаю, что перевод всего на низкий уровень существенно повысит скорость. Дело не в сложности расчетов, а в их количестве.
В героях делаются аналогичные вещи и ничего. Ну, дело твоё, но если не попробуешь сделать хоть что-то - точно ничего не получится.

>> - это поразрядный двоичный сдвиг вправо.

Вот видишь, такая фигня - а какой эффект. Sm Так что упростить как раз и надо.


RE: С++, общая тема - Efrit - 28.04.2012 16:21

packa, ну это же жуть! Unsure Плз, переформатируй свой код - читать же абсолютно невозможно. Я в Notepad++ открывал, есичо.
Да и зачем нам весь проект? Нужен лишь исходник, а ещё лучше - его фрагмент...

totkotoriy, ещё и в строчках типа *pOld = MakeColor16( GetRed (*pOld) + GetAlpha(*pNew)*(GetRed (New) - GetRed (*pOld))/256, тоже не помешало бы произвести замену на ro1, rn1 и иже с ними.


RE: С++, общая тема - totkotoriy - 28.04.2012 16:28

(28.04.2012 16:17)Sav Wrote:  >> - это поразрядный двоичный сдвиг вправо.

Вот видишь, такая фигня - а какой эффект. Sm Так что упростить как раз и надо.
Так ить если бы я разбирался, конечно я бы сделал уже давно, потому и прошу помочь. Радует что даже сейчас уже можно использовать плавный скролинг без значительных тормозов.
Может еще какие нибудь идеи есть на счет кода? Просто для меня написать самому функцию работы с цветом на низком уровне - это что то не реальное.

(28.04.2012 16:21)Efrit Wrote:  totkotoriy, ещё и в строчках типа *pOld = MakeColor16( GetRed (*pOld) + GetAlpha(*pNew)*(GetRed (New) - GetRed (*pOld))/256, тоже не помешало бы произвести замену на ro1, rn1 и иже с ними.
Я уже заменил, но это какая то видать не слишком нужная ветка... наверное если попадется пнг без альфа канала или что-то такое


RE: С++, общая тема - etoprostoya - 28.04.2012 16:32

totkotoriy, попробую оптимизировать. Только у меня проект на MSVC, а не для GCC. Там ещё можно на MMX или SSE перевести, чтобы умножать сразу по два или четыре числа за раз.


RE: С++, общая тема - totkotoriy - 28.04.2012 16:39

(28.04.2012 16:32)etoprostoya Wrote:  totkotoriy, попробую оптимизировать. Только у меня проект на MSVC, а не для GCC. Там ещё можно на MMX или SSE перевести, чтобы умножать сразу по два или четыре числа за раз.
Спасибо, буду ждать.
И ещё есть одна идейка насчет того глюка с не прорисовкой альфа канала на поле боя. Попробую в альфа плагин к хуку на прорисовку дефов существ вставить какое нибудь обновление экрана - может поможет.


RE: С++, общая тема - etoprostoya - 28.04.2012 16:40

(28.04.2012 13:46)Efrit Wrote:  
etoprostoya Wrote:Я хочу сравнить производительность разных алгоритмов вычисления числа Пи.
Само число Пи я не собираюсь вычислять, если вы это имеете в виду.
Так нету этих "алгоритмов", насколько я понимаю. Это число по готовым формулам и вычисляют...

Формулы просто так не напишешь в код, для этого используют разные алгоритмы. К тому же большие числа или числа с высокой точностью не поддерживаются в C\C++, для работы с ними нужен дополнительный код - сторонние библиотеки или свой собственный. Очень много нюансов.


RE: С++, общая тема - etoprostoya - 28.04.2012 16:50

Блин, мне тестить не на чем - все старые пнгешки куда подевал, а куда не помню. totkotoriy, можешь скинуть карту для теста и пнгешки для неё?


RE: С++, общая тема - gamecreator - 28.04.2012 17:05

(28.04.2012 15:06)packa Wrote:  void __fastcall TForm1::Timer1Timer(TObject *Sender)
и этим все сказано. рисовать надо в процедуре отрисовки же!! а где угодно вызывать invalidate


RE: С++, общая тема - totkotoriy - 28.04.2012 17:17

(28.04.2012 16:50)etoprostoya Wrote:  Блин, мне тестить не на чем - все старые пнгешки куда подевал, а куда не помню. totkotoriy, можешь скинуть карту для теста и пнгешки для неё?
Вот анимированные некоторые магические земли, просто можно накидать соответствующие объекты на карту.


RE: С++, общая тема - packa - 28.04.2012 17:27

Извини, я не совсем понял.
1) В таймере пишем FormPaint(Sender); И все из таймера перемещаем в OnPaint?
2) invalidate(); (так ей пользоваться? Насколько нагуглил, так.) В конце таймера и пропишу.


RE: С++, общая тема - gamecreator - 28.04.2012 17:41

(28.04.2012 17:27)packa Wrote:  1) В таймере пишем FormPaint(Sender); И все из таймера перемещаем в OnPaint?
и рисуем по прежнему в таймере.
не рисуй ничего в таймере, забудь что ты вообще такое можешь. вот правильно сделали в windows forms в c#, что скрыли возможность рисования где попало.


RE: С++, общая тема - packa - 28.04.2012 17:47

Тогда я точно не знаю что делать Sm
Ну не через цикл же рисовать, это было бы глупо...

Ифрит Wrote:packa, ну это же жуть! Unsure Плз, переформатируй свой код - читать же абсолютно невозможно.
Да, я знаю) Именно поэтому я вынес нужные куски на форум, а сорс дал только для того чтобы вы поэкспериментировали с ними (если так не получается) Такой код ни в коем случае не нужно читать) Это было бы даже невежественно с моей стороны.

Quote:Да и зачем нам весь проект? Нужен лишь исходник, а ещё лучше - его фрагмент...
Ну так чтобы запустить... Скомпилить...


RE: С++, общая тема - gamecreator - 28.04.2012 17:52

packa, ты можешь назначит обработчик события отрисовки и рисовать там?


RE: С++, общая тема - packa - 28.04.2012 18:04

Могу, но только 1 раз.
Как это сделать каждые 10мс, не знаю.

Ну простите уж Sorry


RE: С++, общая тема - Efrit - 28.04.2012 18:06

Игроед, ты чего? Да назначил он его уже давно, ниже в его коде глянь. Там же он свой "чёрный прямоугольник" и рисует. Другое дело, что лишь его...

Кстати, Пакка, зачем тебе он вообще нужен? Ну если так хочется, чтобы цвет формы был чёрный - что мешает поставить в её свойство Color значение clBlack?


RE: С++, общая тема - packa - 28.04.2012 18:13

Quote:Там же он свой "чёрный прямоугольник" и рисует. Другое дело, что лишь его...
Я там отрисовываю стартовые позиции.
Когда жму старт, в ход идет таймер, со своей многократной перерисовкой.

Ифрит, не подскажешь как в onpaint рисовать несколько раз? Я не понимаю что мне игродел говорит )

Quote:Кстати, Пакка, зачем тебе он вообще нужен? Ну если так хочется, чтобы цвет формы был чёрный - что мешает поставить в её свойство Color значение clBlack?
Следы же (Click to View)
А если ты про тот одиночный - то когда в проге, как то проще контролировать, чем "где-то там в свойствах"


RE: С++, общая тема - Efrit - 28.04.2012 18:28

packa Wrote:Ифрит, не подскажешь как в onpaint рисовать несколько раз? Я не понимаю что мне игродел говорит )
Эфрит Rolleyes
Ну так и вызывай ручками OnPaint столько раз, сколько тебе и нужно 105

packa Wrote:Следы же
Мда. А работать с прозрачными спрайтами не судьба? Поставил transparent у TImage в true и радуйся жизни...

packa Wrote:А если ты про тот одиночный - то когда в проге, как то проще контролировать, чем "где-то там в свойствах"
Угу, а потом же сам жалуешься, что "что-то там мерцает". Потому как в моём случае - вбил один раз, и больше не паришь себе голову. А если так уж не нравится прописывать свойства в инспекторе объектов - что мешает прописать это в коде, внутри конструктора формы?


RE: С++, общая тема - packa - 28.04.2012 18:45

Quote:Эфрит Rolleyes
Учтем)
Quote:Ну так и вызывай ручками OnPaint столько раз, сколько тебе и нужно 105
Ну так через таймер столько, раз сколько нужно.
А нужно бесконечно много раз.
Quote:А работать с прозрачными спрайтами не судьба? Поставил transparent у TImage в true и радуйся жизни...
Это решительно ничего не изменит - "тело" все равно будет оставаться сзади от движения
У меня ведь это не объекты которые можно сместить. У меня это картинки, которые рисуются заново с новыми координатами.

Почему так? а) Потому что я не умею динамически создавать объекты. б) Я не умею работать с группами объектов.

А перерисовывать меня в школе научили Sm
Quote:Потому как в моём случае - вбил один раз, и больше не паришь себе голову. А если так уж не нравится прописывать свойства в инспекторе объектов - что мешает прописать это в коде, внутри конструктора формы?
Ну так и у меня, данную запись вбил месяц назад, так она и стоит.
То бишь писать в Owner? А какая разница, в онпаинт ли писать или в овнере, все равно результат 1


RE: С++, общая тема - Sav - 28.04.2012 19:03

totkotoriy Wrote:И ещё есть одна идейка насчет того глюка с не прорисовкой альфа канала на поле боя. Попробую в альфа плагин к хуку на прорисовку дефов существ вставить какое нибудь обновление экрана - может поможет.
Да не в этом там проблема. Проблема вообще элементарна - в определённых случаях элементы боя просто рисуются на своём месте несколько раз без стёрки предыдущего изображения. Без альфа-канала это незаметно, а в тех местах, где он или вообще какая-либо прозрачность присутствует после определённого числа наложений изображение, естественно, становится непрозрачным. Это не решается при помощи чёрной магии и не связано с отрисовкой def'ов.


RE: С++, общая тема - totkotoriy - 28.04.2012 19:17

(28.04.2012 19:03)Sav Wrote:  Это не решается при помощи чёрной магии и не связано с отрисовкой def'ов.
Вон че оно. Спасибо за информацию... будем думать...


RE: С++, общая тема - gamecreator - 28.04.2012 19:40

(28.04.2012 17:27)packa Wrote:  invalidate(); ... В конце таймера и пропишу.
(28.04.2012 18:04)packa Wrote:  Как это сделать каждые 10мс, не знаю.
ты же сам себе противоречишь!
для ленивого пакки, который любит чтобы за него все думали и делали: invalidate - метод элемента управления, который заставляет его перерисовываться.
(28.04.2012 18:28)Efrit Wrote:  Ну так и вызывай ручками OnPaint столько раз, сколько тебе и нужно 105
ну от тебя я такого нубства не ожидал.
(28.04.2012 19:03)Sav Wrote:  Проблема вообще элементарна - в определённых случаях элементы боя просто рисуются на своём месте несколько раз без стёрки предыдущего изображения. Это не решается при помощи чёрной магии и не связано с отрисовкой def'ов.
по-моему это решается режимом смешивания


RE: С++, общая тема - Efrit - 28.04.2012 19:48

Quote:ну от тебя я такого нубства не ожидал.

Да я просто толком и не понял, что именно Пакке надо... "Перерисовывать всё и всегда"? Тогда вызывать Repaint для каждого нужного контрола внутри OnPaint, как вариант...


RE: С++, общая тема - gamecreator - 28.04.2012 19:56

не знаю что такое repaint, но у контрола должен быть метод, который забракует его отрисовку и заставит вызвать paint. обычно он называется invalidate. а если код отрисовки выполняется не при системном вызове paint, то ничего хорошего (или вообще ничего) пользователь не увидит.


RE: С++, общая тема - packa - 28.04.2012 20:23

Не такой уж я и ленивый, честно )
Здесь что то реально затупил, кажется разобрался.
Взаимодействия с таймером всегда для меня объект слоупочества почему-то 105


RE: С++, общая тема - Sav - 28.04.2012 20:39

gamecreator Wrote:по-моему это решается режимом смешивания
Вряд ли, т. к. геройский экран, на котором всё отрисовывается, 16-битный и не хранит никакой информации о том, где была использована полупрозрачность при отрисовке.


RE: С++, общая тема - totkotoriy - 28.04.2012 21:58

(28.04.2012 19:40)gamecreator Wrote:  по-моему это решается режимом смешивания
А можно поподробнее?Ab


RE: С++, общая тема - gamecreator - 28.04.2012 22:26

нельзя, сам я в этом не разбираюсь


RE: С++, общая тема - totkotoriy - 29.04.2012 09:53

Подскажите ещё пожалуйста - может всё таки получиться с обновлением поля боя - как впихнуть выполнение триггера ERM в код alpha.dll?
Code:
"   image__sub_47C300:         \n"
//Вызов триггера ERM
"   pushad                     \n"
"   push   29502               \n"
"   mov    eax, 0x74CE30       \n"
"   call   eax                 \n"
"   add    esp, 4              \n"
"   popad                      \n"
//Как вот в этом месте корректно перейти к коду ниже?
//Нужно чтоб код выше корректно отработал и корректно перешёл к коду ниже :)
"   pop    eax                 \n"
"   pop    ecx                 \n"
"   push   eax                 \n"
"   push   ebp                 \n"
"   mov    ebp, esp            \n"
"   push   ecx                 \n"
"   mov    al, [ebp+0x3C]      \n"
"   mov    eax, 0x47C307       \n"
"   jmp    eax                 \n"



RE: С++, общая тема - etoprostoya - 29.04.2012 13:14

Интересно. Компилирую с параметром /MT (Multi-threaded, подключается минимум дллок) - альфа-плагин исправно вызывает вылеты, а компилирую с параметром /MD (Multi-threaded DLL, подключается максимум дллок) - всё нормально работает.


RE: С++, общая тема - totkotoriy - 29.04.2012 13:30

(29.04.2012 13:14)etoprostoya Wrote:  Интересно. Компилирую с параметром /MT (Multi-threaded, подключается минимум дллок) - альфа-плагин исправно вызывает вылеты, а компилирую с параметром /MD (Multi-threaded DLL, подключается максимум дллок) - всё нормально работает.
А что значит подключается минимум или максимум длллок?


RE: С++, общая тема - gamecreator - 29.04.2012 13:33

ну можно библиотеки статически подключить, а можно - динамически. в первом случае предпочтение отдается статическому подключению, во втором - динамическому.


RE: С++, общая тема - packa - 03.05.2012 12:09

Можно вместо вектора использовать Deque и чем это чревато?
(не знаю тонкостей, я только начал копать под вектор)

И как добавить в начало вектора элемент?


RE: С++, общая тема - gamecreator - 03.05.2012 14:35

(03.05.2012 12:09)packa Wrote:  Можно вместо вектора использовать Deque и чем это чревато?
ты сначала определись какая структура данных тебе надо.
(03.05.2012 12:09)packa Wrote:  И как добавить в начало вектора элемент?
insert же


RE: С++, общая тема - NIKr0m@nceR - 03.05.2012 16:48

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


RE: С++, общая тема - packa - 03.05.2012 17:40

Если не ошибаюсь в расчетах мне нужно:
1) Трехмерный массив, и штук 5-6 двумерных, все динамические
2) Удаление с начала массива
3) Добавление в конец массива
4) Небольшое копирование массива (<20)

Вот вроде и все.
Quote:insert же
Спс, не подумал что он такой "умный" и не сотрет мне первый элемент.
Хотя странно что я так подумал)


RE: С++, общая тема - Efrit - 03.05.2012 17:43

Ужас какой. Ладно ещё двумерные массивы, но трёхмерные-то тебе зачем? Ты же вроде двумерную игрушку пишешь, а не 3D-шутер?


RE: С++, общая тема - packa - 03.05.2012 17:49

[принадлежность к башне][номер патрона в потоке (очереди)][корды патрона, а также его тип]


RE: С++, общая тема - Efrit - 03.05.2012 18:09

Мда. Пакка, тебе явно нужно начинать читать про классы и структуры Ab
Потому как использовать для этих целей массивы - это не только громоздкое извращение, но и лишняя трата системных ресурсов.


RE: С++, общая тема - packa - 03.05.2012 18:17

Да ладно, современная оперативка в 8 гигов и 4 ядра как-нибудь обработают мою игру Sm
Так стоит deque вместо vector использовать или нет?


RE: С++, общая тема - gamecreator - 03.05.2012 18:53

у тебя же "очередь патронов", вот и используй очередь (тобишь дек)
(03.05.2012 18:17)packa Wrote:  ...4 ядра...
у тебя параллелизм реализован? сомневаюсь.


RE: С++, общая тема - NIKr0m@nceR - 03.05.2012 19:27

очередь это кью (queue), она и занимает поменьше и вообще не стоит задавать функционала больше, чем на самом деле необходимом. А вообще, эфрит абсолютно прав насчет классов и тому куча причин. Во-первых. довольно быстро почувствуешь что это удобнее ибо внутренняя логика и компактность записи, во-вторых, - править станет проще, а в-третьих, отладка становится эффективнее.
gamecreator, всё равно параллелизм реализован в винде и эксплорер с музякой будут обсчитываться отдельно от игры, хотя реального прироста, разумеется, в этом случае будет не очень много.


RE: С++, общая тема - gamecreator - 03.05.2012 20:08

(03.05.2012 19:27)NIKr0m@nceR Wrote:  очередь это кью (queue)
так ее же нет в stl (?)
(03.05.2012 19:27)NIKr0m@nceR Wrote:  всё равно параллелизм реализован в винде и эксплорер с музякой будут обсчитываться отдельно от игры, хотя реального прироста, разумеется, в этом случае будет не очень много.
но его игру будет обрабатывать таки одно ядро. а это обычно немного.


RE: С++, общая тема - packa - 03.05.2012 20:32

Code:
Стандартные последовательные контейнеры STL: vector, string, deque и list.
Стандартные ассоциативные контейнеры STL: set, multiset, map и multimap.
Пруф

Ну вот, разработка игры откладывается еще на неделю, придется классы учить -_-


RE: С++, общая тема - Efrit - 03.05.2012 21:40

Да есть же в STL контейнер queue, вы чего? И был всегда.
Но в любом случае, тут всё равно лучше свои классы писать. Да и рано всё-таки Пакке шаблоны юзать, коли он ещё классов не знает...

packa Wrote:разработка игры откладывается еще на неделю, придется классы учить
Какой оптимист Rolleyes


RE: С++, общая тема - gamecreator - 03.05.2012 21:50

а потом еще на месяц. для изучения структур данных и алгоритмов.


RE: С++, общая тема - packa - 03.05.2012 21:58

Quote:Да есть же в STL контейнер queue, вы чего? И был всегда.
Вот именно поэтому я предпочитаю терроризировать живых людей, а не находить не пойми-что в гугле)
Quote:Какой оптимист
Quote:а потом еще на месяц. для изучения структур данных и алгоритмов.
Не-не-не вы что) Во-первых я так точно другу проспорю о сроках выхода)
А во вторых, интерес падает пропорционально не-кодинью-игры =(


RE: С++, общая тема - gamecreator - 03.05.2012 22:10

(03.05.2012 21:40)Efrit Wrote:  Да есть же в STL контейнер queue, вы чего?
так он там только в виде обертки над другим контейнером


RE: С++, общая тема - Efrit - 03.05.2012 22:32

packa Wrote:Вот именно поэтому я предпочитаю терроризировать живых людей, а не находить не пойми-что в гугле)

А я предпочитаю просто написать в компиляторе строчку #include <queue>. Если не ругается - значит, контейнер есть.
И терроризировать никого не надо. Компилятор - твой главный помощник, используй его как можно чаще.

gamecreator, ну и пусть.


RE: С++, общая тема - NIKr0m@nceR - 03.05.2012 23:20

Вообще, есть замечательный сайт на котором про стандарт написано неплохо - http://www.cplusplus.com.
Насчёт терроризирования людей - могу посоветовать решать проблемы в он-лайн режиме. В том числе, возникающие в процессе изучения вопросы лучше задавать так чтобы быстро получать ответ. Это конечно замечательный форум, но я, к примеру, куда быстрее отвечу на вопрос по аське или контакту нежели тут и мне кажется, что это будет эффективнее. вот.
p.s. в принципе, на некоторые вопросы я готов отвечать, контакты могу по личке кинуть (если их тут в профиле нет Sm)


RE: С++, общая тема - packa - 04.05.2012 17:03

Quote:Компилятор - твой главный помощник, используй его как можно чаще.
Имхо, так можно поступать, имея за плечами немалый опыт.
Ну вот, допустим, не заругался, а как им пользоваться? и т.д. Также перебирать методы?
А если там, к примеру, вместо push_back - qpush_back. Я ввел первый вариант и сделал вывод - queue не умеет добавлять в конец, т.к. компилятор выдал ошибку на push_back.
Quote:Вообще, есть замечательный сайт на котором про стандарт написано неплохо - http://www.cplusplus.com.
Жаль только не русский =( На нем в разы удобнее)
Quote:p.s. в принципе, на некоторые вопросы я готов отвечать, контакты могу по личке кинуть (если их тут в профиле нет Sm)
Ну отказываться не стану Sm

Quote:Насчёт терроризирования людей - могу посоветовать решать проблемы в он-лайн режиме.
Здесь самая главная проблема в том, что через некоторое время это начинает напрягать человека. Возможно даже инвиз-статус) Надоедает же... А на форуме, во-первых не 1 человек, во-вторых между вопросами проходит достаточное кол-во времени, чтобы не напрягать. Хотя чувствуется что я тот еще доставатель ^_^


RE: С++, общая тема - etoprostoya - 04.05.2012 17:31

Ты не столько доставатель, сколько не умеешь (или не хочешь тратить на это время) правильно формулировать вопросы и задачи.


RE: С++, общая тема - Efrit - 07.05.2012 16:14

Впервые сам задам сюда вопрос.

Как вообще можно изменить значение std::shared_ptr внутри метода класса, если этот смарт-пойнтер является одним из его полей?
То бишь такой вариант: (Click to View)
- не работает.

Единственный способ изменить sh_ptr - это поместить его в список инициализации конструктора: в его заголовке вместо Test() нужно написать Test() : sh_ptr(new int(42)). В этом случае всё нормально, а *(tst.sh_ptr) действительно возвращает 42. Но как быть, если я захочу поменять его внутри конструктора/метода, а не только инициализировать? Это же не константа, в конце концов...

P.S. До этого не приходилось пользоваться смарт-пойнтерами внутри классов, применял их лишь на уровне функций. Внутри классов всегда юзал обычные сишные указатели - да и, всё-таки, редко приходится выделять память в куче внутри какого-то класса...


RE: С++, общая тема - NIKr0m@nceR - 07.05.2012 22:21

у меня нет std::shared_ptr и в стандарте я его не нашёл. с другой стороны, есть boost::shared_ptr но он вроде работает немного иначе. если интересует. могу бустовый глянуть.


RE: С++, общая тема - Efrit - 07.05.2012 22:35

Это в C++11 shared_ptr находится прямо в std:: - и, соответственно, нужно просто инклудить #include <memory>.
А в C++03, shared_ptr находится уже в std::tr1:: - и поэтому инклудить нужно #include <tr1/memory>.

Бустовские смарт-пойнтеры действительно работают немного иначе, поэтому хочется узнать именно про STL-ные... Но в принципе, они тоже подойдут.


RE: С++, общая тема - NIKr0m@nceR - 07.05.2012 23:34

Во-первых, tr1 у меня тоже нету Bad
Во-вторых, http://ru.wikipedia.org/wiki/C%2B%2B11#.D0.A3.D0.BD.D0.B8.D0.B2.D0.B5.D1.80.D1.81.D0.B0.D0.BB.D1.8C.D0.BD.D0.B0.D1.8F_.D0.B8.D0.BD.D0.B8.D1.86.D0.B8.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.86.D0.B8.D1.8F может поможет.
В-третьих, я так понимаю что неважно, что буст. Неэффективный но рабочий способ с явным вызовом конструктора:
sh_ptr = boost::shared_ptr<int>(new int(42));


RE: С++, общая тема - Efrit - 08.05.2012 00:28

NIKr0m@nceR Wrote:Во-первых, tr1 у меня тоже нету
Странно. Что ж это за компилятор такой? 118

NIKr0m@nceR Wrote:Неэффективный но рабочий способ с явным вызовом конструктора
Копировать временный указатель на новый объект в куче? Хм, а ведь действительно вариант... Спасибо, что-то я затупил. Ещё можно пользоваться функцией std::make_shared, но она заодно осуществляет копирование объекта Bad О ней я, наверное, позже напишу.

Пока что интересует такой вопрос. Есть такой код: (Click to View)
   
Вывод приложения таков:

Test default ctor
Test dtor
Test dtor
---------------
Test default ctor
Test dtor


Почему деструктор в первом случае вызывается дважды, а не один раз? Ведь никакого копирования, как видно из вывода, не было... Неужели компилятор вначале пытается освободить всё, что содержится "внутри указателя" - а лишь потом удаляет "обычные" объекты со стека?


RE: С++, общая тема - etoprostoya - 08.05.2012 00:50

(08.05.2012 00:28)Efrit Wrote:  
NIKr0m@nceR Wrote:Во-первых, tr1 у меня тоже нету
Странно. Что ж это за компилятор такой? 118

У меня в MSVC 2008 (9.0) тоже нет tr1.

Efrit, скомипилируй с листингом кода на асме и посмотри где происходит второй вызов деструктора.


RE: С++, общая тема - NIKr0m@nceR - 08.05.2012 01:08

tr1 (я так понял "C++ Standards Committee's Library Technical Report (TR1)") это дополнение, которое позже перетекло в С++11, а у меня старенький гцц который у меня руки не доходят обновить - там и буст, и гтк, и кутэ (за компанию), и ещё что-то а у меня сессия.
твой пример я посмотрел, при попытке проследовать по шагам, нашёл что первый деструктор заканчивается чем-то вроде
Code:
inline int atomic_exchange_and_add( int * pw, int dv )
{
    // int r = *pw;
    // *pw += dv;
    // return r;

    int r;

    __asm__ __volatile__
    (
        "lock\n\t"
        "xadd %1, %0":
        "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
        "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
        "memory", "cc" // clobbers
    );

    return r;
}
а в асмовставках я вообще не силён.
после этого пишется строчка, потом снова вызывается деструктор и дебаггер вылетает при поимке очередного исключения. вот.

Upd. Ну да, ты прав на выходе из блока вызываются деструкторы t и указателя. вроде так и должно быть.


RE: С++, общая тема - gamecreator - 08.05.2012 17:10

(08.05.2012 00:28)Efrit Wrote:  Почему деструктор в первом случае вызывается дважды, а не один раз? Ведь никакого копирования, как видно из вывода, не было...
конструктор указателя может работать напрямую с памятью в обход конструктора копирования


RE: С++, общая тема - NIKr0m@nceR - 08.05.2012 17:36

Нет. Там дело именно в том, что вызывается деструктор указателя, который вызывает деструктор указываемого объекта, а потом вызывает деструктор самого t на выходе из блока.


RE: С++, общая тема - Efrit - 08.05.2012 17:48

NIKr0m@nceR, угу. Только вот если написать внутри main:

PHP Code:
...

{
    
Test= new Test();  // создали объект в куче
    
delete t;  // и удалили его
    
std::shared_ptr<Testsh(t);  // создали указатель на этот объект


- то один фиг, деструктор для Test всё равно дважды вызовется... Хотя t на тот момент уже ни на что не ссылается.

Мораль - не использовать смарт-пойнтеры для объектов на стеке (по ссылкам их передавать, и всего делов), ну и не забывать обнулять "обычные" указатели после вызова delete.


RE: С++, общая тема - gamecreator - 08.05.2012 17:57

(08.05.2012 17:48)Efrit Wrote:  Мораль - не использовать смарт-пойнтеры для объектов на стеке
а никто и не собирался Sm


RE: С++, общая тема - NIKr0m@nceR - 08.05.2012 20:12

Ну вообще, это довольно сложный вопрос где как и что передавать и это сильно зависит от ситуации. Нас вот учили более-менее все нестандартные вещи передавать либо по константной ссылке либо по указателю - типо во избежание путаницы.


RE: С++, общая тема - GrayFace - 11.05.2012 14:44

(27.04.2012 22:53)gamecreator Wrote:  он крайне корректный и крайне медленный. для ускорения можно сразу создавать новый массив нового размера, копировать, удалять старый и переприсваивать. но так теряется корректность и могут быть проблемы с освобождением памяти. вот в чем С лучше С++ - так это в выделении памяти. обрати внимание на функции calloc, realloc, free.

и на файл memory.h
36 Потеря корректности? Проблемы с освобождением?

Если массив часто надо увеличивать, то надо выделять больше памяти. Например, при нехватке памяти увеличивать размер выделенной памяти в 2 раза и, пока не заполнится, расширять без перевыделений.

(28.04.2012 15:06)packa Wrote:  
Code:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        ammo = new Graphics::TBitmap;
        ammo->LoadFromFile("ammo.bmp");
Form1->Canvas->Brush->Color=(TColor)RGB(0,0,0);
       Form1->Canvas->Rectangle(0,0,ClientWidth,ClientWidth);
/*Много кода и отрисовок*/
   delete ammo;
}
Надо 1 раз загружать из файла, а не в таймере.

(28.04.2012 17:41)gamecreator Wrote:  не рисуй ничего в таймере, забудь что ты вообще такое можешь. вот правильно сделали в windows forms в c#, что скрыли возможность рисования где попало.
Почему же? Спокойно можно рисовать в таймере и в OnPaint. Еще можно вызывать Repaint - он отрисовывает сразу, а не когда дойдет до сообщения.

(28.04.2012 18:28)Efrit Wrote:  Мда. А работать с прозрачными спрайтами не судьба? Поставил transparent у TImage в true и радуйся жизни...
Для анимации TImage неприменим из-за мерцания. Хотя DoubleBuffered может и поможет...

(03.05.2012 17:49)packa Wrote:  [принадлежность к башне][номер патрона в потоке (очереди)][корды патрона, а также его тип]
Где 3-е измерение? Даже в таком варианте "корды патрона, а также его тип" - это не 3-е измерение. А по сути тут одномерный массив патронов, точнее связный список. Если классы по-началу пугают, сделай патроны структурами, там всё просто, ни на какую мудрёную теорию не наткнёшься.


RE: С++, общая тема - NIKr0m@nceR - 11.05.2012 18:14

чем сишные функции выделения памяти лучше и почему их нельзя юзать в плюсах я так и не узнаю.

Quote:Если классы по-началу пугают, сделай патроны структурами, там всё просто, ни на какую мудрёную теорию не наткнёшься.
а в чём собственно разница? в с++ они отличаются лишь формой записи и тем, что в классах по умолчанию прайвет а в структурах - паблик. и насчёт списка мне кажется не вполне прав - список это реализация, а требуемому функционалу отвечает контейнер очередь (как мне видится). здесь снова виден плюс ооп - если что-то надо поменять, то меняется "внутренность" класса, а все внешние функции, методы и т.д. "ничего не почувствуют"


RE: С++, общая тема - etoprostoya - 11.05.2012 20:25

(11.05.2012 18:14)NIKr0m@nceR Wrote:  чем сишные функции выделения памяти лучше и почему их нельзя юзать в плюсах я так и не узнаю.

1. В плюсах нет аналогов realloc и calloc, _aligned_malloc(), который просто необходим для работы с SSEx, AVX.
2. Не используют в плюсах, потому что считается дурным стилем использование malloc вместо new или их вместе, пусть и для разных типов. То есть, вопрос стиля, по большей части.


RE: С++, общая тема - packa - 12.05.2012 20:42

Поделитесь ссылкой на нормальный компилятор под Си.
Чтобы ничего лишнего, никаких там #pragma hdrstop как в билдере например
И вообще чтобы был просто чистый лист, ф-ия сохранения, и компиляции\запуска. Ну и естественно отлов ошибок Sm

Перебрал много всяких они либо не работают на Win7, либо среды разработки, типа билдера (мне оч сложно в них разобраться, да и не нужно по большей части сейчас), либо виснут :-\

И да: Image: f0b899f25944t.jpg

Ab

Вопрос в догонку:
Можно ли обычному массиву в СИ в качестве размерности передавать переменную?
В С++ точно знаю что нет. Онли константы. Сам проверял))
А вот про СИ... по большей части сбили с толку здесь http://www.sql.ru/forum/actualthread.aspx?bid=21&tid=425437&pg=1
Ваш ответ? Sm


RE: С++, общая тема - packa - 12.05.2012 20:47

Сам бы проверил, да вот компилятора не нашел, в добавок еще и забанили (


RE: С++, общая тема - etoprostoya - 12.05.2012 22:36

Quote:Поделитесь ссылкой на нормальный компилятор под Си.
   Чтобы ничего лишнего, никаких там #pragma hdrstop как в билдере например
Turbo C. Не знаю, правда, работает ли под Win 7.

Quote:Можно ли обычному массиву в СИ в качестве размерности передавать переменную?
Нет.

Quote:А вот про СИ... по большей части сбили с толку здесь
Это не обычный массив C.


RE: С++, общая тема - Efrit - 12.05.2012 22:38

Для packa - кроме "Turbo C", в голову ничего больше не лезет. Но зачем? В том же Билдере можно создать консольное приложение, и в нём уже работать. Ты напрасно начал изучать C++ в GUI-режиме, а надо было - в консоли. Чем больше ты будешь со старта заморачиваться со всякими "кнопками" и "компонентами" - тем лучше ты будешь знать VCL, но сам C++ ты от этого будешь знать только хуже...

Так что, создавай консольку в Билдере, отключай VCL и радуйся жизни. Дебаггер и сохранение в нём есть, да и прочие вещи тоже необходимы. Панельки для "визуального проектирования" среда сама скроет, так что они мешать не будут.

А вместо заморочек с GUI - ты бы лучше прочёл, к примеру, как раз про #pragma hdrstop. Зря ты её ругаешь - это очень полезная директива. Которая, кстати, даже и в некоторых C-шных компиляторах есть. Но если так уж хочешь - можешь строчку с ней убрать. На работу программы это не повлияет, лишь компиляция может происходить дольше обычного.

packa Wrote:Можно ли обычному массиву в СИ в качестве размерности передавать переменную?
В С++ точно знаю что нет. Онли константы. Сам проверял))
Во многих плюсовых компиляторах прекрасно можно объявлять массивы с переменным размером. Насчёт "чистого С" не помню - но, вроде бы, в C99 это также можно делать.


RE: С++, общая тема - packa - 12.05.2012 22:53

Quote:В нормальных плюсовых компиляторах прекрасно можно объявлять массивы с переменным размером.
Всмысле? Опытным путем... Как ты и говорил, "Компилятор твой лучший помощник"
Хотя я, наверное, как всегда, криво выразился:
Обычные статические массивы не принимают в размерность переменную.
Ну точно же! Писал что то вроде
int n=5;
int arr[n]; - ошибка!

Quote:Так что, создавай консольку в Билдере, отключай VLC и радуйся жизни.
Первым делом так и сделал, потому что в среде кодинга билдер самая родная вещь Sm))
Там ерунда какая то, так и не разобрался.
Помоги тогда с ним:
1 Создаю "консольный проект" по инструкции http://foreva.susu.ru/for_stud/prog_lang/bcb_project.html
2 На всякий случай ничего не стирая дописываю #include <iostream> - для вывода вроде
3 Ну и начинаю: для проверки printf("HI!");
Ошибки...
Проба #2 cout<< "hi"; тоже самое!

Ошибка: Image: ed3a48984dbet.jpg

Код
Quote:#include <iostream>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
printf("HI!");
    return 0;
}
Зеленым мое, красным то что бы хотел убрать Sm
Кстати, про pragma я знаю что делают, а для чего в скобках у мейн стоит не понял - для чего?


RE: С++, общая тема - NIKr0m@nceR - 12.05.2012 23:45

Я использую MinGW studio, в которой компиллятор gcc со всеми вытекающими. В частности, можешь писать код в блокноте/vim'е/любом другом месте и компилить его из командной строки. а можешь и в мингв писать, там мне ничего не мешало. с прагмами, к примеру, гсс не дружит Bad Ещё, насколько я помню, объявление массива переменной длины зависит от компиллятора и там где смотрел я делать так КРАЙНЕ не рекомендуют. В конце концов, напиши ты new или malloc, всё равно компиллятору придётся это делать за тебя а так ты это контролируешь.
у мейн в скобках - параметры запуска (те которые из командной строки вбиваются или в ярлычке прописываются например) инт это их количество, а следующее, насколько я помню, массив из argc+1 строк, в нулевой из которых содержится полный адрес а дальше - те самые параметры. В некоторых компилерах (вроде борланда) есть ещё третий параметр но я его не помню, лучше гуглить. Я, обычно, шапку пишу int main(void) потому что мне такк привычнее но это всё равно вопрос вкуса. вот.
з.ы. мингв скачать можно с помощью гугла, также могу свою старенькую закинуть куданить на обменник если хочешь.


RE: С++, общая тема - Efrit - 13.05.2012 11:08

packa Wrote:Ну точно же! Писал что то вроде
int n=5;
int arr[n]; - ошибка!
В борландовском и MS компиляторах действительно будет ошибка - а, к примеру, компилятор GCC прекрасно сработает.

packa Wrote:Помоги тогда с ним:
1 Создаю "консольный проект" по инструкции http://foreva.susu.ru/for_stud/prog_lang/bcb_project.html
2 На всякий случай ничего не стирая дописываю #include <iostream> - для вывода вроде.
Здесь всё правильно. Писать эту строчку желательно выше, чем hdrstop.

packa Wrote:Кстати, про pragma я знаю что делают, а для чего в скобках у мейн стоит не понял - для чего?
Мда Bad
Пакка, срочно купи уже себе хоть какую-нибудь книгу по C++. Потому как функция main - это ну самые основы языка...
Пока можешь на эти параметры просто забить. И удалять их не надо - они что, есть просят?

packa Wrote:Ошибки...
Проба #2 cout<< "hi"; тоже самое!
Ну дык. Функция cout действительно определена в <iostream>, но ведь там она находится в пространстве имён std! Так что, у тебя есть три пути:

1) Писать не cout << "hi!", а std::cout << "hi!". И для всех остальных функций из стандартной библиотеки тоже. И заодно про неймспейсы прочти, это очень простая штука.
2) Написать в начале своего исходника (ниже, чем hdrstop) строчку using namespace std; Всё, после этого твоя запись будет верна. Но не вздумай вставлять эту строчку в h-файлы! Только в cpp-шники, да и то с осторожностью.
3) Инклудить не <iostream>, а <iostream.h> - старую версию файла. Там нет неймспейсов, поэтому твоя предыдущая запись снова будет верна. Но учти, старые файлы есть не во всех компиляторах. Да и не стоит всё же так делать...


RE: С++, общая тема - packa - 13.05.2012 11:57

Все равно та же ошибка...
Блин, мне срочно нужно тренироваться, ЕГЭ уже очень скоро! Паскаль выучить не успеваю, так что остается перейти с++ на чистый си

1) Не работает, ошибка на том скрине
2) Не работает, ошибка на том скрине
3)
Выходит ошибка не в записи - не синтаксическая, а в чем то другом, чего я не знаю...
Quote:Пакка, срочно купи уже себе хоть какую-нибудь книгу по C++.
Некогда( Кое-как заставил себя забить на с++ и готовиться к экзамену -_-


RE: С++, общая тема - Efrit - 13.05.2012 12:58

Нафига писать std::cout, коли ты уже подал команду "юзать std"? Ну да ладно, на работу программы это не влияет.

Это у тебя Билдер какой-то корявый, поскольку указанные примеры обязаны компилироваться. Либо переставляй его, либо пиши под другим компилятором...


RE: С++, общая тема - NIKr0m@nceR - 13.05.2012 18:49

Эфрит не указал ещё один вариант которому учили меня - подключать не весь стд а только необходимое:
using std::cout;
насчет аргументов мейна - а оставлять их зачем?
а еще, мне не нравятся эти сини с сяутами Bad наверное потому. что я кучу времени писал на с и привык к принтфосканфам.
а насчёт ошибки - мне бы побольше глянуть а то так не понятно нифига Bad


RE: С++, общая тема - packa - 13.05.2012 19:02

Quote:а насчёт ошибки - мне бы побольше глянуть а то так не понятно нифига
А что там еще можно разглядеть?
Там просто еще ~100 строчек с "синтаксической ошибкой"

А передать мне нечего =( Т.к. похоже проблема только на моей машине\на моей версии билдера...

Бтв, скачал какую то MinGW studio, запустил, создал проект, вывел hi bro)
Вроде бы все работает (запускать ведь через ф5?)
NIKr0m@nceR, дай связь какую нибудь Sm Или ЛС тебе будет удобнее читать?


RE: С++, общая тема - NIKr0m@nceR - 13.05.2012 21:48

запускать через F8, если F5, то это дебаг Sm


RE: С++, общая тема - gamecreator - 15.05.2012 02:53

(11.05.2012 14:44)GrayFace Wrote:  36 Потеря корректности? Проблемы с освобождением?
там ты переприсваиваешь указатели, можно запутаться. а еще при таких изменениях переменных иногда лезут ошибки при освобождении памяти, я уже когда-то писал.
(11.05.2012 14:44)GrayFace Wrote:  Почему же? Спокойно можно рисовать в таймере и в OnPaint.
можно. но зачем? потеря двойной буферизации (а значит и жутко медленная отрисовка), стирание при следующем вызове отрисовки, еще что-нибудь вылезет. уже лучше вызвать перерисовку формы через invalidate.
(11.05.2012 14:44)GrayFace Wrote:  Еще можно вызывать Repaint - он отрисовывает сразу, а не когда дойдет до сообщения.
не знаю что это, описание какое-то мутное.
(11.05.2012 18:14)NIKr0m@nceR Wrote:  чем сишные функции выделения памяти лучше и почему их нельзя юзать в плюсах я так и не узнаю.
емнип, ты и не спрашивал.
конечно же, их можно (и нужно) использовать в плюсах. а лучше они наличием realloc
(12.05.2012 20:42)packa Wrote:  Поделитесь ссылкой на нормальный компилятор под Си.
msvc. емнип, он поддерживает С. но размер большой, конечно.
(12.05.2012 22:53)packa Wrote:  красным то что бы хотел убрать
не пойму чем оно тебе мешает
(13.05.2012 18:49)NIKr0m@nceR Wrote:  а еще, мне не нравятся эти сини с сяутами Bad наверное потому. что я кучу времени писал на с и привык к принтфосканфам.
а насчёт ошибки - мне бы побольше глянуть а то так не понятно нифига Bad
так стандартный ввод-вывод намного гибче Sm мне он тоже нравится больше потокового.


RE: С++, общая тема - NIKr0m@nceR - 15.05.2012 23:22

бтв, а как работает реаллок? в том смысле что действительно ли это сильно эффективнее чем тупо создать новый кусок и удалить старый?
про так и не узнаю это я просто неудачно выразился и не заметил, извиняюсь

у меня тут вопрос возник: какой механизм работы исключений типа деления на 0? просто интересно а гуглить влом, если кто знает - просветите.


RE: С++, общая тема - etoprostoya - 16.05.2012 00:09

>>бтв, а как работает реаллок? в том смысле что действительно ли это сильно эффективнее чем тупо создать новый кусок и удалить старый?
Да, вроде эффективнее, хотя я не тестировал на скорость. В первом случае всё происходит средствами ОСи, а во втором ты своими ручками, то есть кодом. Зря что ли создавались АПИшные функции типа HeapRealloc()?


RE: С++, общая тема - gamecreator - 16.05.2012 02:29

(15.05.2012 23:22)NIKr0m@nceR Wrote:  бтв, а как работает реаллок? в том смысле что действительно ли это сильно эффективнее чем тупо создать новый кусок и удалить старый?
вроде бы должно быть эффективнее:
msdn Wrote:realloc returns a void pointer to the reallocated (and possibly moved) memory block.
но в то же время:
msdn Wrote:realloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode.
(15.05.2012 23:22)NIKr0m@nceR Wrote:  какой механизм работы исключений типа деления на 0?
всмысле? как и другие исключения. вылазит ошибка деления на ноль - выбрасывается исключение


RE: С++, общая тема - NIKr0m@nceR - 16.05.2012 06:29

а где оно выбрасывается? на каком уровне? просто в моей мингв нет виндовской обработки исключений и её обработка реализована страшненьким макросом с асмовставками, вот я и заинтересовался.


RE: С++, общая тема - gamecreator - 16.05.2012 15:05

так деление на ноль это прерывание. в обработчике прерывания и выбрасывается.


RE: С++, общая тема - NIKr0m@nceR - 16.05.2012 23:42

а, протупил. точно. спс


RE: С++, общая тема - Efrit - 17.05.2012 14:32

Эх, ну какой дурак придумал, что в сях неинициализированные указатели равны мусору, а не NULL?
Полдня сегодня из-за этого потратил - в одной из if-веток конструктора забыл проинициализировать поле-указатель...


RE: С++, общая тема - NIKr0m@nceR - 17.05.2012 15:14

ага, бывает. на всякий случай стараюсь сразу проинициализировать всё.


RE: С++, общая тема - AVS - 17.05.2012 15:26

(17.05.2012 14:32)Efrit Wrote:  Эх, ну какой дурак придумал, что в сях неинициализированные указатели равны мусору, а не NULL?
Полдня сегодня из-за этого потратил - в одной из if-веток конструктора забыл проинициализировать поле-указатель...

Ну с таким же успехом можно отгрести багов и от любой другой переменной. Тут уж либо обнулять все (как в паскале при создании объекта в куче) либо ничего не трогать. В сях скрость работы на одном из первых мест - ничего "лишнего" компилятор пытается не вставлять.


RE: С++, общая тема - Efrit - 17.05.2012 16:02

AVS Wrote:Ну с таким же успехом можно отгрести багов и от любой другой переменной.
Не совсем так. Ведь "другие переменные" нельзя разыменовывать - только указатели...

AVS Wrote:В сях скрость работы на одном из первых мест - ничего "лишнего" компилятор пытается не вставлять.
Сделали бы опцию в компиляторе, и всего делов... Может, это есть уже где?


RE: С++, общая тема - Berserker - 17.05.2012 16:30

cyclone?


RE: С++, общая тема - AVS - 17.05.2012 16:36

(17.05.2012 16:02)Efrit Wrote:  
AVS Wrote:Ну с таким же успехом можно отгрести багов и от любой другой переменной.
Не совсем так. Ведь "другие переменные" нельзя разыменовывать - только указатели...

И чо? Да с другими переменными не будет сразу AV (или что еще хуже порча чего нить полезного) , но например какой нить case пойдет не по той ветке - тоже мало приятного; да мало ли, что еще может быть.


RE: С++, общая тема - gamecreator - 20.05.2012 01:46

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


RE: С++, общая тема - Efrit - 20.05.2012 12:19

Да я и не спорю. Просто случай того, что "какая-то переменная стала равна мусору", легко находится мониторингом всех переменных в отладчике - ведь программист, как правило, знает, значения из какого диапазона может принимать каждая его переменная. И всякие неадекватные значения (как правило, "мусорные" значения переменных очень большие) видны сразу.

С указателями же обнаружить подобную ошибку куда сложнее, поскольку их "мусорные" значения ничем на вид не отличаются от остальных - и там, и там какие-то адреса участков памяти в ОЗУ. Плюс, указатели, в отличие от переменных, можно попытаться разыменовать, что также может привести к ошибке...


RE: С++, общая тема - gamecreator - 21.05.2012 23:28

но компиляторы в таких языках обычно выдают предупреждение (а то и ошибку), если переменная не инициализирована.


RE: С++, общая тема - Efrit - 22.05.2012 12:55

Не, далеко не всегда. В конструкторах классов, особенно если в них есть if или switch-ветки - так вообще никогда...


RE: С++, общая тема - GrayFace - 24.05.2012 06:54

Ну это всё-же проблема компилятора. Не инициализированная переменная должна вызывать warning. С переменными классов в Билдере тоже не должно быть проблем, т.к. TObject инициализирует всё нулями. Вот то, что в классическом с++ при создании объекта он заполнен мусором, мне тоже не нравится. // вообще, интересно, как Борланд "пришили" с++ к Дельфи - как поступили со строками, с виртуальными конструкторами, виртуальными функциями класса, class of...

(15.05.2012 02:53)gamecreator Wrote:  можно. но зачем? потеря двойной буферизации (а значит и жутко медленная отрисовка), стирание при следующем вызове отрисовки, еще что-нибудь вылезет. уже лучше вызвать перерисовку формы через invalidate.
Я на самом деле не знаю, какие там тонкости, просто сам пробовал так рисовать. Было бы интересно почитать детально.

(28.04.2012 19:03)Sav Wrote:  
totkotoriy Wrote:И ещё есть одна идейка насчет того глюка с не прорисовкой альфа канала на поле боя. Попробую в альфа плагин к хуку на прорисовку дефов существ вставить какое нибудь обновление экрана - может поможет.
Да не в этом там проблема. Проблема вообще элементарна - в определённых случаях элементы боя просто рисуются на своём месте несколько раз без стёрки предыдущего изображения. Без альфа-канала это незаметно, а в тех местах, где он или вообще какая-либо прозрачность присутствует после определённого числа наложений изображение, естественно, становится непрозрачным. Это не решается при помощи чёрной магии и не связано с отрисовкой def'ов.
Для двигающихся монстров я такую проблему решал - тень иногда по нескольку раз рисовалась без стирания.
Код для отрисовки с прозрачностью я могу оптимизировать как-нибудь на досуге.


RE: С++, общая тема - packa - 26.05.2012 18:31

пишу от руки прогу на с++

Code:
int main(void)
{
}
return 0; нужно писать в конце? как вообще по стандарту? на егэ нужно...


RE: С++, общая тема - gamecreator - 26.05.2012 20:54

конечно нужно. но многие компиляторы прощают это для main


RE: С++, общая тема - NIKr0m@nceR - 26.05.2012 21:59

нужно, я вообще мейн начинаю со слов
int main(void) {
    return 0;
}


RE: С++, общая тема - etoprostoya - 27.05.2012 00:26

А я обычно так пишу:
void main()
{
}

И никаких вам ретурнов! Sm


RE: С++, общая тема - gamecreator - 27.05.2012 00:32

зато int универсальнее


RE: С++, общая тема - NIKr0m@nceR - 27.05.2012 08:36

gcc обижается на попытки сделать main неинтовым


RE: С++, общая тема - Efrit - 27.05.2012 10:45

packa, по стандарту можно return в конце main не ставить. Его отсутствие эквивалентно return 0. Причём это верно только для main, с другими функциями так не прокатит.


RE: С++, общая тема - GreyGhost - 29.05.2012 16:07

если main объявлена как int то return быть обязан.

просто во многих компиляторах есть заглушка
int main(...)
{
(void)main(...)
return 0;
}

все процессы ОБЯЗАНЫ возвращать ОС статус завершения.


RE: С++, общая тема - packa - 01.06.2012 21:09

Может мой вопрос прозвучит глупо, но существуют компиляторы под Симбион S60 ?
Вот новый телефон нокия 6120) хотелось бы везде иметь возможность кодить)


RE: С++, общая тема - Efrit - 01.06.2012 22:02

В стандартный состав библиотеки Qt входит порт под Simbian, так что ответ - да.


RE: С++, общая тема - Efrit - 19.06.2012 13:37

Вопрос от меня. Можно ли хоть как-нибудь передать среди параметров шаблона тип класса, в котором и идёт эта "передача"?
Понимаю, что сформулировал коряво, поэтому покажу код:

PHP Code:
template <typename T>
class 
Sub
{
};
//-------------------

class Temp
{
    
Sub<ints1;
    
Sub<Temps2;
}; 

Этот код отлично скомпилируется и будет работать. Но, допустим, я решил переименовать класс Temp в MyFavoriteClass - а это означает, что и тип переменной s2 придётся переименовать...

В C++11 есть удобная штука decltype(X), которая определяет тип X ещё на этапе компиляции. Естественно, что я попробовал сначала написать decltype(*this) - но, увы, "invalid use of 'this' at top level". А вот если написать такую строку внутри какого-то метода Temp, то всё будет работать, поскольку this уже будет существовать...

Вот и как быть? Как мне сказать компилятору, что я хочу передать именно текущий класс Temp как параметр шаблона?


RE: С++, общая тема - etoprostoya - 19.06.2012 13:50

Наобум.
template <typename T>
class T
{
    Sub<int> s1;
    Sub<T> s2;
};

Просто редко приходится работать с шаблонами.


RE: С++, общая тема - Efrit - 19.06.2012 13:59

etoprostoya, спасибо, но такой способ не подойдёт. Нужно просто переименовать тип, не параметризовывая его.

Считай, что помимо Temp есть ещё Temp2, Temp3 и так далее - и в каждом из них есть член, имеющий тип Sub<>. И вот как мне не указывать постоянно конкретное имя внутри угловых скобок - а дать понять компилятору, что нужно использовать "текущий" класс?


RE: С++, общая тема - Efrit - 20.06.2012 18:28

Оказывается - то, что я хочу сделать, всё же есть в стандарте C++11, но ещё не реализовано в GCC:

Quote:If a function-definition or member-declarator declares a member function of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” between the optional cv-qualifier-seq and the end of the function-definition or member-declarator. It shall not appear before the optional cv-qualifier-seq and it shall not appear within the declaration of a static member function (although its type and value category is defined within a static member function as it is within a non-static member function). [Note: the type and value category is defined even for the case of a static member function because declaration matching does not occur until the complete declarator is known, and this may be used in the trailing-return-type of the declarator. —end note]

Otherwise, if a member-declarator declares a non-static data member (9.2 [class.mem]) of a class X, the expression this is a prvalue of type “pointer to X” within the optional brace-or-equal-initializer. It shall not appear elsewhere in the member-declarator.

Буду ждать...


RE: С++, общая тема - packa - 26.06.2012 21:21

Снова нубс-проблемка)

Случайно обнаружил что у моей главной формы почему-то стоит Visible=false в свойствах, и при этом она отлично отображается...

Создал вторую форму, и как мне все же сделать чтобы при запуске показывалась сразу вторая форма, а первая только после нажатия, допустим "старт" ?


RE: С++, общая тема - FallenAngel - 27.06.2012 11:24

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


RE: С++, общая тема - Efrit - 04.07.2012 19:44

Что ж, Пакка, как и просил - держи рецензию на свой код Ab
Прокомментирую его так, будто это настоящий продакшн-код:

PHP Code:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "Unit1.h"
#include <vector>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
using namespace std;
TForm1 *Form1;
int mainXmainYraznica_ammo_enemy_YammoNn;
bool build;
const 
int enemyN=5;

class 
Tower
{
public:
    
int xx;
    
int yy;
    
int health;
    
int damage;
    
int target;
    
int reload;

    
Tower int xint yint hint dint tint r);

    
void Draw_Tower();
    
void Zahvat_Target();
    
void Draw_Lazer();
    
void Reload_Tower();
};

class 
Enemy
{
public:
    
int xx;
    
int yy;
    
int health;

    
Enemyint xint yint h );

    
void Draw_Enemy();
    
void Move_Enemy();
};


class 
Ammo
{
public:
    
int xx;
    
int yy;
    
int number;
    
int target;

    
Ammo (int xint yint nint t);

    
void Move_Ammoint j);
    
void Spawn_Ammoint j);
    
void Draw_Ammo();
};


vector <Enemyenemy_group;
vector <Towertower_group;
vector <Ammoammo_group;
vector <intinterval;

Graphics::TBitmap *enemy2 ;
Graphics::TBitmap *ammo ;
Graphics::TBitmap *tower ;
Graphics::TBitmap *boom ;
Graphics::TBitmap *main ;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
        : 
TForm(Owner)
{
}
//---------------------------------------------------------------------------
Enemy::Enemyint xint yint h )
{
 
xx=x;
 
yy=y;
 
health=h;
}

//----------------------------

void Enemy::Draw_Enemy()
{
for (
int i=0i<enemyNi++)
{
    if (
enemy_group[i].xx!=mainX)
    {
        if (
enemy_group[i].health>0)
        {
            
Form1->Canvas->Draw(enemy_group[i].xxenemy_group[i].yyenemy2);
        }
        else
        {
            
Form1->Canvas->Draw(enemy_group[i].xxenemy_group[i].yyboom);
        }
    }
}
}
//---------------------

void Enemy::Move_Enemy()
{
        if ( 
xx != mainX )
        {
            if (
xx>0)
            {
                
xx+=1;
            }
        }
}
//===========================

Tower::Towerint xint yint hint dint tint r)
{
    
xx=x;
    
yy=y;
    
health=h;
    
damage=d;
    
target=t;
    
reload=r;
}
//---------------

void Tower::Zahvat_Target()
{
int rasstoyanie[5]; //Массив расстояний от башни до врага
        
for (int j=0enemyNj++)
        {
        if (
enemy_group[j].health>0)
        {
        
int raznicaXtarget xx enemy_group[j].xx//Разница по Х
        
int raznicaYtarget yy enemy_group[j].yy//Разница по Y
                
if (raznicaYtarget<0){         //Если башня выше цели
                
raznicaYtarget=enemy_group[j].yy yy;
                }
        
rasstoyanie[j]=sqrt(pow(raznicaXtarget,2)+pow(raznicaYtarget,2)); //Расстояние от врага до башни, по Пифагору
        
}
        
int min rasstoyanie[0];
        
int b=0;
        for (
int j=0j<enemyNj++){
                if (
rasstoyanie[j]<min){
                        
min=rasstoyanie[j]; //Находим ближайшего врага
                        
b=j;
                }

                if (
rasstoyanie[j]<350)
                { 
//Если враг в области поражения башни (пока числом)
                
target=b//Запоминаем номер врага
                
}
        }
        }


}
//-------------

void Tower::Draw_Tower()
{
Form1->Canvas->Draw(xxyytower);
}

//-------------

void Tower::Draw_Lazer()
{
    
Form1->Canvas->Pen->Color=(TColor)RGB(200,0,0);
    
Form1->Canvas->MoveTo(xx,yy);
    
Form1->Canvas->LineTo(enemy_group[target].xx,enemy_group[target].yy);
}
//--------------

void Tower::Reload_Tower()
{
    
reload+=1;
}

//=====================================================================

Ammo::Ammo (int xint yint nint t)
{
    
xx=x;
    
yy=y;
    
number=n;
    
target=t;
}

//-----------------------

void Ammo::Move_Ammoint j )
{
for(
int j=0j<ammoNj++)                       // Для каждого патрона из массива... Делать столько раз, сколько патронов в потоке.
    
{
        if ( 
enemy_group [target].xx == xx && enemy_group[target].yy == yy )
        {
            
enemy_group[target].health-=50;
        }
        else
        {
            
xx-=1;   // Движение по оси Х

            //Разница между высотой врага и патрона=высота патрона - высота"выделенного" врага
            
raznica_ammo_enemy_Y=0;
            if (
enemy_group[target].yy yy//Если высота врага < высота патрона
            
{
                
raznica_ammo_enemy_Y enemy_group[target].yy yy;
                if (
raznica_ammo_enemy_Y 5)
                {
                    
yy += raznica_ammo_enemy_Y;
                }
                else
                {
                    
yy += 5//Опускаемся на 5
                
}
            }
            else
            {
                
raznica_ammo_enemy_Y yy enemy_group[target].yy;
                if (
raznica_ammo_enemy_Y<5)
                {
                    
yy -= raznica_ammo_enemy_Y;
                }
                else
                {
                    
yy -= 5//Поднимаемся на 5
                
}
            }
        }
    }
}

//--------------------------
void Ammo::Spawn_Ammo int j )
{
    if ( 
tower_group[j].target >= && tower_group[j].target )           //Если у башни есть цель
    
{
        if (
enemy_group[tower_group[j].target].health>0)
        {
                
Ammo newAmmo (tower_group[j].xxtower_group[j].yyammoNtower_group[j].target);
                
ammo_group.push_backnewAmmo );
                
ammoN++;
                
tower_group[j].reload=0;   //Обнуляем для нового отсчета
        
}
    }
}
//-----------------

void Ammo::Draw_Ammo()
{
    
Form1->Canvas->Drawxxyyammo);
}
//===========================

void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (
int i=0enemyNi++)
{
    
Enemy newEnemyrandom(100),random(300), 100 );
    
enemy_group.push_backnewEnemy );
}
Timer1->Enabled true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
for (
int i=0i<enemyNi++)
{
enemy_group[i].Move_Enemy();
}
//
if (tower_group.empty()!=true)
{
    for (
int i=0i<tower_group.size(); i++)
    {
    
tower_group[i].Zahvat_Target(); //Башни ищут ближайшую цель
    
}
    for(
int j=0j<nj++)
    {
        if (
tower_group[j].reload==10)
        {
            
ammo_group[j].Spawn_Ammo);
        }
        else
        {
            
tower_group[j].Reload_Tower();
        }
    }
    for (
int k=0k<ammoNk++)
    {
    
ammo_group[k].Move_Ammo);  //Двигаем все патроны
    
}
}
Invalidate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormPaint(TObject *Sender)
{
for (
int i=0i<enemyNi++)
{
enemy_group[i].Draw_Enemy();
}

if (
tower_group.empty()!=true)
{
    for (
int i=0i<tower_group.size(); i++)
    {
        
tower_group[i].Draw_Tower();
        if ( 
tower_group[i].target >= )           //Если у башни есть цель то рисуем "лазер"
        
{
            if (
enemy_group[tower_group[i].target].health>0)
            {
              
tower_group[i].Draw_Lazer();
            }
        }
    }
    for(
int j=0ammoNj++)
    {
        
ammo_group[j].Draw_Ammo();
    }
}
Form1->Canvas->Draw(610235main);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
DoubleBuffered=true;
for (
int i=0enemyNi++)
{
    
Enemy newEnemyrandom(100),random(300), 100 );
    
enemy_group.push_backnewEnemy );
}
n=0;
mainX=610;
mainY=235;
ammoN=0;
tower = new Graphics::TBitmap;
tower->LoadFromFile("tower.bmp");
main = new Graphics::TBitmap;
main->LoadFromFile("main.bmp");
enemy2 = new Graphics::TBitmap;
enemy2->LoadFromFile("enemy2.bmp");
ammo = new Graphics::TBitmap;
ammo->LoadFromFile("ammo.bmp");
boom = new Graphics::TBitmap;
boom->LoadFromFile("boom.bmp");
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormMouseDown(TObject *SenderTMouseButton Button,
      
TShiftState Shiftint Xint Y)
{
if (
build==true)
{
    
Tower newTower X,Y10050, -110);
    
tower_group.push_backnewTower );
    
n++;
}
Invalidate();
Form1->Edit1->Text=tower_group.size();
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button2Click(TObject *Sender)
{
 if (
build==true){
build=false;
}
else {
build=true;}
}
//--------------------------------------------------------------------------- 

Оформление:
 
1) Бросается в глаза разный стиль именования переменных: mainX, mainY, raznica_ammo_enemy_Y. Нотация везде должна быть единой, даже если эта нотация - венгерская.
2) Конструктор класса Tower вынесен за его пределы - это ладно (хотя и не ясно, зачем), но почему он записан где-то в середине файла, а не сразу вслед за классом? А ещё лучше - выносить классы в отдельные файлы.
3) Да и что значат его переменные, почему они все однобуквенны? В строке Tower ( int x, int y, int h, int d, int t, int r) разобраться сможет только автор этого кода, и никто другой. А писать код надо так, будто сопровождать его будет склонный к насилию психопат - который знает, где ты живёшь. (с)
4) За названия вроде "raznica_ammo_enemy_Y" или "Zahvat_Target()" нужно вырвать и застрелить руки. Если уж не знаешь полностью английского (что вполне простительно) - то пиши всё транслитом, но смешивать языки - это моветон.
5) Все символы, относящие к названию типа, нужно писать слитно. В строке vector <Enemy> у тебя Enemy является частью типа, поэтому пробел ставить не надо. Это же касается и звёздочек в объявлениях указателей.
6) А вот в строках типа enemy_group[i].xx!=mainX, наоборот, нужно обязательно отделять пробелом знаки операций. Иначе визуально ничего не понятно. Арифметические операции - это полноценные функции, и они заслуживают "отделения".
7) Скобки {} кое-где поплыли, а кое-где и отступы вместе с ними. Местами вообще получилась нечитабельная каша, как в функции Zahvat_Target().


Кодинг:
 
1) Строка #include <vector> должна стоять выше, чем #pragma hdrstop. Потому как в твоём случае <vector> будет инклудиться всегда, хотя достаточно всего одного раза.
2) Используется множество глобальных переменных - которые, как известно, не есть гут. В большинстве случаев их можно заменить локальными, если только это не синглтоны. Да и хотя бы прокомментировать их не мешало бы.
3) Из-за конструкций вроде Form1->Canvas->Draw(610, 235, main) есть риск быть похороненным в закрытом гробу бирюзового цвета. Почему именно бирюзового? Потому что 610. А если уж эта строка нужна чисто "для дебага", то нужен комментарий об этом (а ещё лучше - условная компиляция).
4) В конструкторах лучше использовать списки инициализации, а не поочерёдное присваивание. Во-первых, так безопаснее. Во-вторых, только так можно проинициализировать не-статические константы класса.
5) Кстати, а где константы-то? В коде хватает переменных, которые не изменяются после инициализации. А ведь "константность" защищает от ошибок на этапе исполнения.
6) Раздражают конструкции вида if (tower_group.empty()!=true) или reload+=1. В первом случае сравнение с true можно не писать, а во втором нужен обычный инкремент.
7) Приведение типов в стиле C, как в строке (TColor)RGB(200,0,0), не всегда безопасно - лучше использовать "плюсовые" static_cast и dynamic_cast.
8) Зачем в функцию Move_Ammo( int j ) передаётся параметр j, когда он же вводится в первой строчке самой функции? Либо неиспользуемая переменная, либо просто ошибка.
9) Ввело в ступор содержимое функции Button2Click(). Надеюсь, что это просто "заглушка" такая?


Рекомендации:
 
1) Использовать везде единый стиль записи. Это касается именования переменных, расстановки скобок и комментариев. Имена должны быть осмысленными.
2) Упаковывать данные внутрь классов, используя идиому RAII. Если картинка относится к элементу конкретного класса, не надо таскать её как глобальную переменную - нужно выделить память под неё в конструкторе, и освободить в деструкторе.
3) Почему не стоит обходить вектор через int-переменную, скромно умолчу. Но на всякий случай посоветую почитать про итераторы. Через них всё идёт намного быстрее.
4) Вместо "голых" указателей лучше использовать shared_ptr<> и создавать всё в стеке, избегая кучи вообще. Хотя тебе ещё далековато до такой техники.
5) Вместо множества функций типа Draw_Tower() и Draw_Lazer() лучше иметь одну перегруженную функцию Draw(), которая могла бы принимать объекты разных типов. Это удобно для вызова функций (IDE сама показывает перегрузки), да и наследоваться от таких классов куда проще.
6) В любом классе желательно наличие конструктора по умолчанию (без параметров), дабы его объекты можно было использовать внутри массивов и STL-контейнеров. У тебя же далеко не везде так.

P.S. Только не стоит расстраиваться от прочитанного - я в твоём возрасте кодил намного хуже Rolleyes


RE: С++, общая тема - etoprostoya - 04.07.2012 19:56

(04.07.2012 19:44)Efrit Wrote:  9) Ввело в ступор содержимое функции Button2Click(). Надеюсь, что это просто "заглушка" такая?

Функция меняет параметр build с true на false и наоборот. Что непонятного?
А в остальном почти во всём присоединяюсь.


RE: С++, общая тема - packa - 04.07.2012 21:47

Image: 6db876e06533.jpg

Оформление (Click to View)
Кодинг (Click to View)
рекомендации (Click to View)



RE: С++, общая тема - Deo - 05.07.2012 06:29

Я эти ваши C++ не знаю, но ведь метод Draw_Enemy проходит по всем врагам и рисует их, но помимо этого он вызывается для каждого врага, не?




RE: С++, общая тема - packa - 05.07.2012 08:12

Quote:Я эти ваши C++ не знаю, но ведь метод Draw_Enemy проходит по всем врагам и рисует их, но помимо этого он вызывается для каждого врага, не?
Угу, это фейл.

Но к счастью это ни на что не влияет, кроме как зря рисует, зато четче будет)))


RE: С++, общая тема - Efrit - 05.07.2012 08:33

packa Wrote:Единой и старался делать) в 3 переменной просто необходимо такое название, иначе не ясно разница между чем и чем.
Не, я про другое. Я про символы подчёркивания в именах. Их надо либо использовать везде, либо вообще не использовать.

packa Wrote:У меня все конструкторы вынесены ниже, рядом с методами. Почему в середине? Просто у меня еще 2 класса, группировал контруктор+метод+метод+...
Нет, функции-члены класса должны распаолагаться либо внутри него, либо сразу вслед за ним. Я не хочу рыскать по всему cpp-шнику в поисках нужной мне функции - особенно, если самих классов много.

packa Wrote:Исключительно для конструктора. Если заглянуть в сам конструктор там все предельно ясно
Ничего не ясно. В строке Tower ( int x, int y, int h, int d, int t, int r) - что такое x? Что такое h? Что такое d, t, r? Если я захочу создать экземпляр твоего класса - то я не смогу этого сделать, поскольку я понятия не имею, что же значат его параметры. Правильно писать Tower (int x_pos, int y_pos, int health, int damage, int target, int reload). Поскольку иначе мне придётся копаться во внунренностях твоего класса, а мне некогда.

packa Wrote:Не понял что не так) КоординатаХ, КоординатаУ, картинка - вроде так все пишется.
Почему именно 610 и 235, а не 510 и 234? С какого перепугу функция меняет конкретные пиксели экрана? А что, если я захочу уменьшить размеры окна? Или у меня экран 480*320? А если это число 610 используется в нескольких функциях, а я захотел его поменять, что тогда? Мне придётся править каждую функцию, что ли?
Запомни: вообще нельзя использовать какие-то конкретные числа внутри кода. В худшем случае - такие константы надо дефайнить, и внутри функций использовать именно константы, а не явно указанные числа. Единственные числа, которые можно указывать явно - это 0, 1 и -1 (ну и двойка также иногда разрешается). Разве что, ещё можно использовать 8 как число бит в байте, 10 и 16 для функций перевода в системы счисления, ну и 100 для подсчёта процентов. Не более!

packa Wrote:Ammo::Ammo (int x, int y, int n, int t) : xx(x), yy(y), number(n), target(t); // ?
Да, именно так.

packa Wrote:Одна есть и хватит)) А если серьезно - специально оставлял переменные - чтобы при надобности просто их менять, не правя при этом код.
Константы сильно экономят время, отлавливая ошибки ещё на этапе компиляции. Когда-нибудь ты это оценишь.

packa Wrote:Со вторым полностью согласен, а вот с первым нет. Потому что код явно теряет свою очевидность, что тупо мешает читаемости. Я бы сказал что здесь овчинка выделки не стоит)
Какое из двух высказываний для тебя звучит более понятно?
   1) Если группа башен пуста, то...
   2) Если верно, что группа башен пуста, то...
На мой взгляд - однозначно первое... Вот и с кодом то же самое. Особенно если условий много, и они вложены друг в друга.

packa Wrote:Нажали на кнопку - Вошли в режим строительства - каждый клик строит башню.
Нажали повторно, вышли из режима, можем кликать до посинения, ничего не произойдет
Део верно заметил, что можно просто написать build = !build и не мучаться.

packa Wrote:Мозгу нуба намного сподручнее пользоваться интами, чем абстрактными итераторами)
Кстати уже заюзал в одном месте, но все равно тяжко обрабатывать мозгу, как это работает, хоть и понятно достаточно.
Итератор - это просто "обёртка" над указателем. Если ты не до конца понимаешь адресную арифметику указателей - то, конечно, итераторами пользоваться ещё не стоит.

packa Wrote:Почему? 3 класса = 3 конструктора.
Дык это не конструкторы по умолчанию - у них параметры есть! Я же говорил именно про конструкторы по умолчанию...

P.S. Да, ещё забыл сказать: public-переменные в классе - это почти всегда плохо. Нужно везде использовать get- и set-функции для каждой переменной, к которой планируется "сторонний" доступ. Даже если они будут простейшими.


RE: С++, общая тема - NIKr0m@nceR - 08.07.2012 13:54

Давайте я тут что ли спрошу. Дело в том что я заядлый дндшник и жутко устал тратить кучу сил и времени на генерацию персонажа, заполнение чарников, которые постоянно забываются и т.д. и т.п. Посему мне хочется это дело автоматизировать, но основная проблема заключается в том, что я слабо представляю какое этому всему придать внутреннее устройство. ну то есть я конечно могу зафигачить один такой большой map и обращаться к параметрам по строке-названию. после чего написать 9к строк кода с кучами свичей, а после того как захочу подкорректировать что-нибудь, благополучно стать погребённым в этом коде. У кого-нибудь есть идеи как мне помочь/что полистать/о чём размыслить
/кто виноват/что делать
?


RE: С++, общая тема - Efrit - 08.07.2012 14:28

Чубайс / трясти надо

Сложно ответить, поскольку я не знаю, что именно из себя представляют ДнД-шные чарники.
Можешь кинуть ссылки на описание, а ещё лучше - скрины/фотки заполненных листов?

И что там может поменяться, разве правила не фиксированы?


RE: С++, общая тема - Efrit - 08.07.2012 16:49

Посмотрел чарлисты и чуток глянул правила. Да уж, объёмистая штука!

Вообще сложно сказать, как именно здесь действовать. Основная сложность тут в том, что все элементы системы сильно связаны между собой, и изменения какого-то одного пункта часто влекут за собой изменения в других. Например, увеличил персонаж свой навык магии - и эффекты заклинаний у него также стали лучше, ну и какие-то новые возможности тоже вполне могут добавиться...

Плюс, хватает "божественных объектов" типа класса или расы: если у персонажа изменить расу/класс, то у него вообще всё поменяется нафиг. Более того - насколько я понимаю, класс зависит от расы. И персонажи могут приобретать какие-то новые фичи в зависимости от комбинации раса+класс... Короче гря, полный набор антипаттернов Ab

Но уж твой вариант с "огромным map-ом" точно не прокатит - запутаешься с всевозможными хитросплетениями "божественных" параметров персонажа типа расы/класса/пола. Я бы советовал прежде всего выделить те классы, которые вообще никак не меняются: например, "слоты персонажа" вроде бы фиксированы (или же, у каких-то рас есть третья рука?). И в первую очередь - реализовать их.

Из-за того, что всё сильно связано - очень советую юзать property, иначе замучаешься. То есть либо юзай С#, либо (если хочется именно на плюсах) VC++ или Qt (второе лучше, так как кроссплатформ). Кроме этого, не советую юзать где-либо внутри классов поле "родитель" - это только ещё больше запутает код, поскольку вдобавок ко всему придётся помнить, чем является такое-то заклинание: врождённой фичей персонажа, или же свойством оружия...

Какие-то конкретные методы проектирования мне в голову не лезут. Хотя, той же "абстрактной фабрикой" здесь можно попробовать воспользоваться - поскольку изменение расы/класса/пола не ведут к добавлению каких-то абсолютно новых классов, а лишь к модификации свойств старых. Но сами фабрики получатся огромные - хз, стоит ли здесь овчинка выделки. Но это в любом случае куда лучше, чем сотни map-овских ключей, ещё и без пропертей 118

P.S. Кстати, я для своей ФРПГ (Аредита) чарлисты полностью автоматизировал, а заодно с ними и проведение битв тоже, но мне было куда легче - у меня есть "модульность" на уровне системы. Например, у моих персонажей нет классов вообще, а пол почти ни на что не влияет - то есть хоть какую-то иерархию классов (программных) построить можно... А вот как быть с ДнД, я толком не знаю - слишком её система уж громоздка.


RE: С++, общая тема - NIKr0m@nceR - 08.07.2012 17:11

Бывает и 3 руки. у меня с паттернами вообще говоря практически шапочное знакомство, я никогда реально их не использовал пока что. Мне тоже в голову пришла фабрика но я только боюсь как бы с ней не запутаться. про третью руку - и такое бывает, а вот 6 базовых параметров практически на 100% незыблемы. ладно, спасибо за помощь, пойду строить фабрику


RE: С++, общая тема - Efrit - 08.07.2012 17:27

Quote:у меня с паттернами вообще говоря практически шапочное знакомство
Да у меня тоже. Трогал только как раз абстрактную фабрику и визитора - ну и синглтон, естественно. Ещё "мост" пытался щупать, но уже позабыл всё. Ещё начинал читать книжку по ним - но там такая вода написана, что аж уши вянут Ab

Quote:а вот 6 базовых параметров практически на 100% незыблемы
Дык на класс же это не тянет. Это всего лишь enum. Класс - это "раса", "класс" (в Днд-шном смысле) или "оружие", но уж никак не конкретные параметры.


RE: С++, общая тема - NIKr0m@nceR - 08.07.2012 17:39

Или может быть билдером создавать расу с классом и т.п.?

а про параметры - довльно тонкий вопрос. с одной стороны, это просто число, а с другой - у него подхарактеристики есть, куча производных чисел считается, чеки всякие. и мне не до конца понятно относится ли это к внутренней кухне стата или нет.


RE: С++, общая тема - Efrit - 08.07.2012 18:14

Паттерн "билдер" я в своё время толком так и не понял. Точнее гря - я не нашёл особых различий между ним и MVC... Так что тут подсказать не могу.

Если у параметров есть какие-то "подхарактеристики" - тогда да, придётся делать их классом. Странновато выглядит, но придётся...


RE: С++, общая тема - NIKr0m@nceR - 08.07.2012 18:20

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


RE: С++, общая тема - Efrit - 08.07.2012 18:48

Quote:это базовое число, или текущее значение, или базовое число и список того что на него влияет, или вообще чёрти пойми что.
Вот именно поэтому я и рекомендую использовать проперти. По крайней мере, можно будет просто написать goblin.force = 10 - и не париться, что при этой операции будет изменяться ещё туева хуча "подхарактеристик" персонажа. Только не стоит забывать про ехplicit-конструкторы 118

Quote:в частности, от этого зависит какие методы должны извне просто получать значения а какие должны быть внутренними.
Я думаю, что все методы, которые принимают хар-ки в качестве параметров, должны быть внешними.

А вообще, можно не париться и юзать распространённый подход: делать всё private - а когда по ходу дальнейшей разработки понадобится "доступ извне", сделать такой метод публичным. Обычно, человеком с опытом уже видит, что какой-то из методов нарушает инкапсуляцию - и он тогда поймёт, что сейчас менять private на public нельзя (и стоит, например, разделить метод на два - "приватную" и "публичную" части).


RE: С++, общая тема - packa - 14.08.2012 18:53

Есть такая штука:

Вектор объектов "танк". (class Enemy)
Вектор объектов "патрон" летящих в танки. (Class Ammo)

Среди параметров патрона есть Enemy *target (ссылка непосредственно на объект Enemy (танк) )

Проблема:
Танк "взрывается" До того как долетят все патроны. И после взрыва танка патроны теряют цель, и тупо улетают за экран ( и там вечно летят )

Пробовал решить проблему так:
Но во-первых вроде сравнение неверное
А во-вторых вылетает "выход за границы вектора" (в момент исчезновения последнего патрона(выделен желтым кругом) на данного врага)

Есть еще мысли, чтобы патроны взрывались именно в том месте, где был танк (а потом взорвался)


RE: С++, общая тема - Efrit - 14.08.2012 21:36

У тебя сама модель построена неправильно. Зачем вообще "патрон" хранит в себе "врага-цель"? И логично, что если уж танк-цель взрывается каким-то "сторонним" образом - то "патрон" не знает, как себя вести. Ведь он перестаёт быть нужным!

Намного правильнее было бы, если бы "патроны" не были привязаны к конкретным "танкам", а летели сами по себе. А проверка "попал или нет" проводилась бы по координатам, а не по "целям". То бишь - проходимся по всем "танкам" и смотрим, не совпали ли их координаты с какими-либо "патронами". Если да - то взрываем все такие "патроны", ведь их может быть несколько (ну и сам танк заодно).

Как бы это решил я:

- для всех игровых объектов создал бы абстрактный класс GameObject, от которого уже затем наследовал бы конкретные (танки, патроны, башни);
- разбил бы игровое поле на квадратные клетки (класс Cell), представляющие из себя спрайты N*N пикселей;
- каждая Cell-клетка хранила бы в себе указатель на GameObject, который показывал бы, чем именно "занята" эта клетка;
- тогда попадание патрона в танк проверялось бы легко: если "новая" клетка патрона уже кем-то занята - то этот "кто-то" взрывается (ну, если умеет).
то бишь обыкновенный полиморфизм, ничего сложного



RE: С++, общая тема - packa - 14.08.2012 22:06

Забавно) но все так, или практически так) За исключением клеток.

Quote:Намного правильнее было бы, если бы "патроны" не были привязаны к конкретным "танкам", а летели сами по себе. А проверка "попал или нет" проводилась бы по координатам, а не по "целям". То бишь - проходимся по всем "танкам" и смотрим, не совпали ли их координаты с какими-либо "патронами". Если да - то взрываем все такие "патроны", ведь их может быть несколько (ну и сам танк заодно).
Они и летят сами по себе, столкновение определяется так: есть структура Rect с 4 переменными (прямоугольник)
и в каждую 0,1 сек для всех объектов создается по этому Ректу, потом все эти ректы проверяются на столкновение.

Но есть одно Но! А куда им собственно лететь? Им нужно куда то лететь! Наиболее подходящим способом я избрал создать ссылку на объект (target) и черпать из него координаты (target->yy)

Quote:- для всех игровых объектов создал бы абстрактный класс GameObject, от которого уже затем наследовал бы конкретные (танки, патроны, башни);
Присутствует

Quote:- разбил бы игровое поле на квадратные клетки (класс Cell), представляющие из себя спрайты N*N пикселей;
Ну это будет оочень условно. У меня шаг 1 пиксель, и проверка на столкновение обрабатывается чуть ли не до касания бампера танка)

В общем вот можно пощупать (или хотя бы *ехе запустить, лучше 1 раз увидеть чем 100 раз услышать)
Просто не думаю, что у кого то есть желание копаться в моем коде) Но я старался очень и очень структурировано кодить и вроде как прибирался обычно.

P.S. У меня часто вылазит ошибка вектора - но ошибку кажет в _vector.h
Quote: __stl_throw_out_of_range("vector");
Нельзя ли как нибудь настроить, чтобы узнать ГДЕ именно происходит эта неправильность???
Вот опытным путем удалось установить что ошибка в строке 196, ну или +\- 20 строк )


RE: С++, общая тема - Efrit - 15.08.2012 18:09

Ошибка очевидна. Внутри вложенного цикла
   for (unsigned int j=0; j<ammo_tower_group.size(); j++)
вызывается метод
   Boom_Enemy(i)
который удаляет i-ый элемент из глобального массива enemy_group.
Однако i после этого не меняется (ведь это вложенный цикл, который работает по j, а не внешний), и поэтому в строке
   ammo_tower_group.at(j).target==&enemy_group.at(i)
вовсе не факт, что enemy_group.at(i) будет существовать.

А вообще, Пакка, твой код по-прежнему представляет из себя мешанину из: названий различного стиля, размазанных по всему файлу классов (что мешает их в отдельные файлы выделить?), отсутствия комментариев и кучи глобальных переменных. Особенно последнее огорчает... Если уж хочешь, чтобы твой код был понятен другому человеку - пиши его так, чтобы он был понятен. Чтобы человеку не приходилось рыскать по всему файлу, дабы узнать - что значит такая-то глобальная переменная...


RE: С++, общая тема - packa - 15.08.2012 19:11

Quote:Ошибка очевидна. Внутри вложенного цикла
Кстати да, тоже заметил один раз, только потом забыл подумать и больше не возвращался. Эффект замыленности на лицо Sm

Quote:А вообще, Пакка, твой код по-прежнему представляет из себя мешанину
Sorry А я думал прибрался... Просто я как дома, для меня все там на полочках))) Не подумал как то что непонятно может быть (

Quote:(что мешает их в отдельные файлы выделить?)
Знания, спасибо что натолкнул, попробую.

Quote: и кучи глобальных переменных
Ну инкапсуляция, имхо, высший класс и вообще оптимизация! Я пока на дне )


RE: С++, общая тема - packa - 20.08.2012 22:07

Не получается собрать воедино!
Решил вытащить классы в отдельный файл, а они так срослись!

есть Unit1.cpp в нём используется вектор ammo_tower_group;(ниже) пробовал писать extern vector <Ammo_First> ammo_tower_group; - не помогает. (#include "Unit1.h",#include "Unit2.h")
есть Unit1.h
есть Unit2.cpp в нём описание class Ammo_First; вектор vector <Ammo_First> ammo_tower_group; (#include "Unit2.h",#include "Unit1.h")
есть Unit2.h в нём объявление class Ammo_First; (#include "Unit1.h")

вылазит куча ошибок типа
[C++ Error] Unit2.cpp(7): E2238 Multiple declaration for 'vector'
[C++ Error] Unit2.cpp(6): E2141 Declaration syntax error

Вообще порядком запутался что и где екстернить нужно. =(


RE: С++, общая тема - packa - 20.08.2012 22:12

Смотрел в интернете, есть ситуация 1 в 1, только вместо моего типа Ammo_First там int и все благополучно работает!


RE: С++, общая тема - Efrit - 20.08.2012 22:32

Пакка, выложи получившийся код, а то без него сложно что-то понять.
Только, плз, не на Залил.ру Ab


RE: С++, общая тема - packa - 20.08.2012 23:45

Вот, только боюсь там немного путанно, ибо я запутался(

Изначальная идея - для каждого класса (всего их штук 5) выделить отдельный файл.
Конкретнее Враги\Патроны\Бункер\Интерфейс\Препятствия.

Попытался сначала на патронах. Встал вопрос - куда же девать глобальные вектора - решил положить в файл с классом, а в юнит1 екстерном прикрепить (пытался и наоборот, тоже не вышло)

P.S.А почему не залил?) мой любимый)


RE: С++, общая тема - Efrit - 21.08.2012 10:54

Так и не понял, где в твоём коде "разбиение классов по файлам". File1 - это всё, что ли? Ну да ладно.

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

"Заголовок" функции - это её тип, сигнатура и дополнительные атрибуты (explicit, inline, virtual, const, throw(), = 0). То есть всё, что стоит перед её фигурными скобками. При этом, внутри хедеров нужно указывать полный заголовок функции, а вот внутри цпп-шников лишь частичный: из атрибутов функции указываются лишь те, что стоят справа от сигнатуры.

Начинать "выделение классов в файлы" стоит с самых мелких классов, которые не зависят от других. И лишь затем переходит к более крупным. Кстати, у тебя строка с инклудом File1.h почему-то стоит выше строки с прагмой - это неверно, поскольку у тебя в этом хедере содержится не стандартный класс, а твой собственный (который может меняться).


RE: С++, общая тема - packa - 21.08.2012 13:30

Quote:Так и не понял, где в твоём коде "разбиение классов по файлам". File1 - это всё, что ли? Ну да ладно.
Не, File1 - это самая первая проба, для теста сделал простейщий класс и выводил его в Unit1.cpp. все получилось! (извини что не написал, но выше я же юнит2 указывал Sm )
И я пошел дальше, стал выделять в другой файл очень мощный класс - класс патронов. (unit2.cpp\ unit2.h)
почти получилось - но встал вопрос с вектором объектов этого самого класса.
При желании, наверное, можно избежать использования вектора объектов Ammo_First в каком нибудь из файлов, но не всю же жизнь избегать) Избегать не нужно, нужно знать! 166

Объявляю вектор в Unit1.срр в строках 128 129, в Unit2.cpp в самом начале, (вектор используется только в методе Boom_ammo)


P.S. Если отдельно создавать *h и *cpp в С++ builder, то как их связать потом? Именно в среде билдера - по стандарту когда жмешь на срр, внизу есть вкладка срр\h где можно быстро переходить туда сюда (вот с File1 так не получилось, а с Unit2 норм)
Но это не очень важно, так, ерунда.


RE: С++, общая тема - GrayFace - 27.08.2012 18:52

(04.07.2012 19:44)Efrit Wrote:  5) Все символы, относящие к названию типа, нужно писать слитно. В строке vector <Enemy> у тебя Enemy является частью типа, поэтому пробел ставить не надо. Это же касается и звёздочек в объявлениях указателей.
Как-раз звёздочки - часть имени переменной. Например, int *i, *j.

(04.07.2012 19:44)Efrit Wrote:  3) Почему не стоит обходить вектор через int-переменную, скромно умолчу. Но на всякий случай посоветую почитать про итераторы. Через них всё идёт намного быстрее.
А мне это интересно, весьма удивительная ситуация.

(04.07.2012 19:44)Efrit Wrote:  4) Вместо "голых" указателей лучше использовать shared_ptr<> и создавать всё в стеке, избегая кучи вообще. Хотя тебе ещё далековато до такой техники.
Если всё будет созаваться в стеке, то зачем вдруг shared_ptr? Объясни, что за техника. Хотя всё в стеке создавать в любом случае невозможно.


RE: С++, общая тема - Efrit - 27.08.2012 20:30

Quote:Как-раз звёздочки - часть имени переменной. Например, int *i, *j.
Не, я говорил про то, что Пакка вообще звёздочку как отдельный символ оформляет. Её нужно либо к названию типа цеплять, либо к названию переменной - но уж никак не отдельно.

Quote:А мне это интересно, весьма удивительная ситуация.
Дык быстрее же, чем обращение по номеру. Итераторы и были специально созданы для того, чтобы быстро перебирать элементы. Плюс, если Пакка захочет поменять вектор на лист - то ему код переписывать не придётся.

Quote:Если всё будет создаваться в стеке, то зачем вдруг shared_ptr? Объясни, что за техника. Хотя всё в стеке создавать в любом случае невозможно.
Я имел в виду, что в стеке будут создаваться сами shared_ptr Ab А так они создадутся в стеке, то при выходе из текущего блока будут вызваны их деструкторы - а заодно с ними, и деструкторы "хранимых" ими объектов. Сами-то объекты, разумеется, будут создаваться в куче - но время их жизни будет совпадать со "стековой".

А объекты из кучи, которые должны существовать и после выхода из текущего блока, нужны редко. Мне, кроме графических виджетов, больше ничего на ум не приходит... Но у тех в конструкторе хотя бы всегда есть указатель на виджет-родитель, что гарантирует их уничтожение при уничтожении родителя. А если такой связи нет - то получается утечка памяти.


RE: С++, общая тема - GrayFace - 28.08.2012 19:12

(27.08.2012 20:30)Efrit Wrote:  
Quote:А мне это интересно, весьма удивительная ситуация.
Дык быстрее же, чем обращение по номеру. Итераторы и были специально созданы для того, чтобы быстро перебирать элементы. Плюс, если Пакка захочет поменять вектор на лист - то ему код переписывать не придётся.
Почему же? По идее, если там начинка - массив, то по номеру - прямое обращение к памяти, а итератор - вызов функции. Надо будет посмотреть.


RE: С++, общая тема - NIKr0m@nceR - 05.04.2013 06:23

А можно я тут скромно возражу по поводу *? Это извечная тема холиваров и лично мне удобнее использовать синтаксис int * p поскольку в нём есть мнемоническая подсказка: p имеет тип int*, а *p имеет тип int.
Кстати, насчёт того, что итераторы быстрее: если в плане работы программы, то оптимизатор всё равно всё причешет что станет одинаково, а вот с синтаксической точки зрения, писать это реально быстрее.


RE: С++, общая тема - packa - 01.05.2013 00:15

Здрасте)

Такой вопрос: как заставить программу на с++ выполнять сторонний код?
В частности хочу написать движок игры на scheme, а сама игра(оформление, менюшки и т.д.) будет на с++.

Для примера пускай это будет морской бой: scheme вычисляет куда попал выстрел, хранит какой из кораблей затоплен какой наоборот, знает все координаты и так далее. А с++ все это красиво выводит.

Как вариант придумал такую схему: scheme все вычисления выводит в файл (постоянное его перезаписывая) а с++ берет данные оттуда, после этого снова отправляет запрос на новые вычисления.

Но это решает только половину проблемы, и то через костыль, т.к. когда я прошу открыться прогу на scheme (из с++) всплывает консолька на пару секунд после чего закрывается и все готово!

Какие есть предложения?


RE: С++, общая тема - etoprostoya - 01.05.2013 01:38

Через DLL - самый очевидный вариант. Пишешь на scheme все нужные функции, компилируешь их в DLL, а потом эти функции вызываешь в своей C-шной программе.


RE: С++, общая тема - packa - 01.05.2013 21:07

Провел я несколько часов в гугле и пришел к выводу, что шансы сделать DLL на лиспообразном языке стремится к 0 =(


RE: С++, общая тема - gamecreator - 02.05.2013 13:18

я думал о использовании потоков ввода-вывода. но как бы это сделать - хз


RE: С++, общая тема - packa - 02.05.2013 13:37

Меня кое где направили копать здесь
Но я так и не понял смысла этого)
Никаких примеров, скачать нечего, только беглый голый концепт "как это работает"
Может более шарящие люди могут найти в этом ценность) но мне это ничего не дало ((


RE: С++, общая тема - gamecreator - 02.05.2013 15:34

вот что нарыл. человек рассматривает твою проблему http://pubby8.wordpress.com/2012/03/22/scheme-with-c/
побочные ссылки в тему:
http://stackoverflow.com/questions/2610716/small-readable-scheme-interpreter-in-c
http://wiki.call-cc.org/man/4/Embedding


RE: С++, общая тема - packa - 02.05.2013 17:59

Побочные сам находил)

Спасибо, постараюсь перевести статью) но общий смысл ясен.
Это правда не совсем то, что хотелось бы, мне это видится как гугл переводчик с русского на английский.
Простые фразы переводит на ура, а в сложных предложениях косячит.

Вот и здесь думаю что прогу на 70+ строк не скомпилит в Сишный код...
А калькуляторы и прочие умножай-списки получатся.


RE: С++, общая тема - gamecreator - 02.05.2013 23:35

(02.05.2013 17:59)packa Wrote:  Это правда не совсем то, что хотелось бы, мне это видится как гугл переводчик с русского на английский.
...
Вот и здесь думаю что прогу на 70+ строк не скомпилит в Сишный код...
не понял о чём ты.


RE: С++, общая тема - packa - 03.05.2013 00:07

Сразу говорю, если скажу сейчас фигню, простите)

Но статью я понял так, что благодаря тем 3 программам, можно "переводить" код из скима, в Си примерно по следующей схеме:
Code:
(define n 5)
(cond
   [(= n 5) (error "error")]
Code:
int n=5;
switch (5) {
case 5: cout << "error";
}
На базовых конструкциях работает на ура!

Но стоит сделать какую нить хитрозакрученную прогу, как "переводчик" выдаст полную фигню.

Может я и ошибаюсь, слишком уж у меня поверхностные знания в этом вопросе...


RE: С++, общая тема - gamecreator - 03.05.2013 00:11

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


RE: С++, общая тема - packa - 03.05.2013 00:34

Оу, ну тогда я вернусь через пару дней, пойду читать на эту тему, чтоли)


RE: С++, общая тема - SyDr - 10.05.2013 12:59

http://sourceforge.net/projects/swig/?source=directory


RE: С++, общая тема - Bes - 27.11.2013 15:04

Image: cpplands1.png


RE: С++, общая тема - packa - 04.02.2014 17:54

Не расшифруете и\или не дадите ссылку, чтобы понять следующее:

Code:
HGLRC  hRC=NULL;              // Постоянный контекст рендеринга

     HDC  hDC=NULL;              // Приватный контекст устройства GDI

     HWND  hWnd=NULL;              // Здесь будет хранится дескриптор окна

     HINSTANCE  hInstance;              // Здесь будет хранится дескриптор приложения

Первые строки устанавливают Контекст Рендеринга (Rendering Context). Каждая OpenGL программа связывается с Контекстом Рендеринга, который в свою очередь вызывает Контекст Устройства (Device Context). Контекст Рендеринга OpenGL определен как hRC. Для того чтобы рисовать в окне, Вам необходимо создать Контекст Устройства Windows, который определен как hDC. DC соединяет окно с GDI (Graphics Device Interface). RC соединяет OpenGL с DC.

Что то не смог нагуглить.

VC++ + OpenGL


RE: С++, общая тема - gamecreator - 04.02.2014 19:03

Не пойму что тут может быть непонятно. Задавай вопросы.


RE: С++, общая тема - packa - 05.02.2014 11:39

Ну собственно главный вопрос в том, что это такое и что из себя представляет: Контекст Рендеринга (Rendering Context), Контекст Устройства (Device Context)


RE: С++, общая тема - gamecreator - 05.02.2014 12:32

Ну контекст устройства - вещь известная. Это винапи интерфейс для работы с устройствами вывода. Если ты хорошо знаком хотя бы с одной винапи-обёрткой, то это не должно быть для тебя чем-то новым.

Что такое контекст рендеринга - хз. За все те немногие разы, что я использовал опенгл - никогда с ним не сталкивался. Судя по мсдн - какая-то надстройка над опенгл от мелкософта. Можешь посмотреть в мсдн что она делает и надо ли она тебе вообще. Можно обойтись и обычным опенгл.