Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

C++ подводни камъни (за начинаещи)
http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=881
Страница 1 от 2

Автор:  HCL [ Чет Юли 21, 2005 2:00 pm ]
Заглавие:  C++ подводни камъни (за начинаещи)

Темата е замислена, като място, където тези които започват да изучават С++, могат да намерят някои особености на синтаксиса и въобще на езика, които биха им създали проблеми.
Първият пример е елементарен, но е хубаво да му се обърне внимание. Впрочем, някой можели да обясни, защо след като ++ има по-голям приоритет от =, х не е 1?

Код:
int x=0, i=0;
x=i++;      //тук имаме х=0 и i=1


Код:
int x=0, i=0;
i++;
x=i;      //тук имаме x=1 и i=1

Автор:  Filo [ Чет Юли 21, 2005 2:20 pm ]
Заглавие: 

Трябва да се обясни разликата между:
Код:
x = ++i ;
x = i++ ;


Тука е разковничето. Само дете мене ме няма по обясненията.

Автор:  HCL [ Чет Юли 21, 2005 3:04 pm ]
Заглавие: 

Ясно разбрах го. Явно в този случай, приоритетите се определят от правилото:
Код:
x=i++;   //присвои i на x и увеличи i с едно
x=++i;   //увеличи стойността i с едно и я предай на x


А някой можели да подскаже как де създам двудимензионален масив с показатели?
Това не става:
Код:
int* liste;
int m=3;
liste = new int[m][m];

Автор:  Predator_MF [ Чет Юли 21, 2005 3:09 pm ]
Заглавие: 

Не ми е много ясно това понятие двуменсен масив, предполагам че ще е по-лесно с масив от масиви.

Автор:  HCL [ Чет Юли 21, 2005 3:13 pm ]
Заглавие: 

С два масива става без проблеми, въпросът е дали може с един.
Задачата е да се транспонира матрица и то с един масив.
Нещо подобно
Код:
int arr[3][3];

само дето не мога да използвам константи, понеже всяка задача е с различно големи матрици :(

Автор:  [ Чет Юли 21, 2005 3:31 pm ]
Заглавие: 

Код:
/* ALLOCATE A TWO-DIMENSIONAL SPACE, INITIALIZE, AND DELETE IT. */
#include <except.h>
#include <iostream.h>

template < class T > T max(T x, T y)
{
   return (x>y)>(x):(y);
};

void display(long double **);
void de_allocate(long double **);

int m = 3; // THE NUMBER OF ROWS.
int n = 5; // THE NUMBER OF COLUMNS.

int main(void)
{
long double **data; //See the Library Reference, Chapter
// TEST FOR EXCEPTIONS. 10, for a description
data = new long double*[m];   // STEP 1: SET UP THE ROWS. of xalloc.
try {
for (int j = 0; j < m; j++)
data[j] = new long double[n]; // STEP 2: SET UP THE COLUMNS
}
catch (xalloc) { // ENTER THIS BLOCK ONLY IF xalloc IS THROWN.
// YOU COULD REQUEST OTHER ACTIONS BEFORE TERMINATING
cout << "Could not allocate. Bye ...";
exit(-1);
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
data[i][j] = i + j; // ARBITRARY INITIALIZATION
display(data);
de_allocate(data);
return 0;
}
void display(long double **data) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << data[i][j] << " ";
cout << "\n" << endl;
}
}
void de_allocate(long double **data) {
for (int i = 0; i < m; i++)
delete[] data[i]; // STEP 1: DELETE THE COLUMNS
delete[] data; // STEP 2: DELETE THE ROWS

}
/*
produces this output:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
Chapter 3, C++ specifics 131
*/

Автор:  HCL [ Чет Юли 21, 2005 3:45 pm ]
Заглавие: 

pirev страшен си :D тръгна от раз.

Автор:  Predator_MF [ Чет Юли 21, 2005 5:01 pm ]
Заглавие: 

A ше обясните ли каква е идеята на такъв масив и с какво се различава от масив от масиви например :)

Автор:  HCL [ Чет Юли 21, 2005 7:01 pm ]
Заглавие: 

Хищник то това също се явява един вид масив от масиви.
По-точно имаш един масив, като всеки елемент от масива е друг масив. Хубавото в случая е, че поинтерите ти позволяват да използваш паметта динамично. Т.е. не е нужно да задаваш големината на масивите при компилация, а можеш да я определиш от потребителски вход или по други начини по време на изпълнение (което си е огромен плюс ако не знаеш колко големи масиви ти трябват точно).
В моя случай програмата създава квадратна матрица с m реда и m колони и това m го определя юзера, после разменя редовете и колоните и ако матриците са равни (т.е. с еднакви елементи) заключва, че матриците са симетрични. И това става много гъвкаво с този метод.

Автор:  Predator_MF [ Чет Юли 21, 2005 9:09 pm ]
Заглавие: 

Hqma takyv forum drug po CBETA :D MEPCU :D

Автор:  breeze [ Пет Юли 22, 2005 11:14 am ]
Заглавие: 

Цитат:
Ясно разбрах го. Явно в този случай, приоритетите се определят от правилото:
Код:

x=i++; //присвои i на x и увеличи i с едно
x=++i; //увеличи стойността i с едно и я предай на x


Грешка ;) която се среща дори и в някои учебници по C. ВИНАГИ първо става увеличаването и после присвояването. Разликата е, че операцията ++i връща резултат НОВАТА стойност на i, а i++ връща СТАРАТА стойност на i. Някой ще каже, каква е разликата между това обяснение и предишното? Ами доста голяма. Например, i++ се изпълнява по-бавно от ++i защото първо се съхранява старата стойност на i, после се увеличава i и се връща резултат съхранената стара стойност на i (да оставим настрани въпроса за оптимизирането ако резултата не се присвоява на нещо друго).
Има и други разлики (в момента ме мързи да мисля за пример ;) ) така че ако се водите по горното обяснение понякога стават кофти грешки. Да не говорим, че би се обезмислило понятието приоритет (ако във втория случай i++ се присвояваше с по висок приоритет от инкрементирането на i)

Автор:  HCL [ Пет Юли 22, 2005 12:38 pm ]
Заглавие: 

breeze разбирам какво имаш в предвид, но за какви други разлики става въпрос? Я дай някои примери.

Автор:  breeze [ Пет Юли 22, 2005 2:16 pm ]
Заглавие: 

ОК :)
Извинявам се за тъпия пример но не е изключено някой да напише следното:
Цитат:
unsigned char a[5], x = 0;

while(x < 5)
a[x] = x++;

В момента набързо измислих примера, аз самият се бях сблъскал с много по добър (съвсем реален) код но беше отдавна и не го помня.
И така, тук приятелчето иска (по доста кофти начин де) да запълни масива a[] с последователните числа 0, 1, 2, 3, 4. Той разсъждава по следния начин "Горе първо се извършва присвояването (тоест, а[0] = 0) и после x се увеличава - значи няма проблеми". И го написва. И ако има късмет, компилатора му изчислява първо дясната част (например с включени някои опцийки за оптимизация) - и генерира код който запълва масива така: XX, 0, 1, 2, 3, 4 - като последната четворка излиза извън масива вече (и маже навън чужда памет) а първия елемент остава неинициализиран. Какво се е случило? Ами просто това е типичен случай на некоректен C код. Класика, както и изрази от типа а++ + а--. Но за човек който си мисли че увеличаването на x става едва след присвояването, израза си е напълно коректен и се чуди защо се получава така
Разбира се, всеки свестен компилатор ще генерира предупреждение, нещо от сорта <Warning[Pa081]: undefined behavior: the order of read and modification of variable "x"> но човек трябва да разбере кога всъщност става увеличаването на x иначе ще се чеше по главата и ще се чуди какво му е недефинираното поведение на този код.

Автор:  HCL [ Нед Юли 24, 2005 10:11 pm ]
Заглавие: 

Ето още една интересна "грешка", с която се сблъсках днес. Пишех програма, която да демонстрира 6 от по-известните алгоритми за сортиране и се сблъсках с проблема (не се смейте :oops: ) как от main() да извикам функция, която да създаде масив с големина определена от потребителя и този масив или показател към него по късно в main() да се подаде на друга функция. Все още нямам идея как да го направя това и затова използвам малко по-прост метод и създавам масива директно в главната функция, а големината на масива се връща от допълнителна функция, чиято задача е единствено да получи размера на масива като вход от потребителя.
Интересното в случая е, че използвах switch за целта и допуснах грешката да дефинирам за втори път дефинирания вече в началото на програмата масив. Това че на предния ред освобождавам паметта не помогна и като капак на всичко компилатора не пусна съобщение за грешка. Съобщението се появи по късно след като пренаписах частта от сорса където е суйча с if else.
Това е част ос сорса, прилагам и самата програмата като прикачен файл, на някой може да му е интересно. Но е възможно да има грешки в сорса, начинаещ съм, т.е. да се не взима на пълно доверие!!!

Код:
int main()
{   int choice = 9;
   int size=1;   
   int *psize = &size;
   int *parray = new int [size];

   system("clear");

   do
   {   menu();
      cin >> choice;

      if (choice != 0)
      {   switch (choice)
         {   case 1: { size_array(psize);
                      delete[] parray;
                      int *parray = new int [size];   //Тук е грешката трябва да е само parray = new int [size];

                        for(int i=0; i<size; i++)
                        {   parray[i] = rand(); }
                    }
                  break;
            case 2: Show_array(parray,size);
                  break;
            case 3: Direct_Search(parray,size);
                  break;

            default:
                  {   system("clear");
                     cout << "\nWrong Input!\n";
                  }
         }
      }
   }while (choice != 0);

   return 0;
}


Като извод бих заключил, че трябва да се внимава, когато се използват по-големи от един ред statement-и в switch. Компилатора явно не "вижда" грешки в тази част от кода. :(
Някой може ли да обясни защо?

Прикачени файлове:
sortalgorithmen.cpp [5.49 KiB]
293 пъти

Автор:  HCL [ Пон Юли 25, 2005 2:26 am ]
Заглавие: 

Е сега вече няма да ми повярвате :lol: , но
Код:
(*pcurrent)++

и
Код:
*pcurrent++;

не дават един и същ резултат. Ако ще увеличавате стойността, която сочи показателя използвайте първото.
А го бях чел преди два-три дни и пак го обърках :?

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/