Отговори на тема  [ 16 мнения ]  Отиди на страница 1, 2  Следваща
C++ подводни камъни (за начинаещи) 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение C++ подводни камъни (за начинаещи)
Темата е замислена, като място, където тези които започват да изучават С++, могат да намерят някои особености на синтаксиса и въобще на езика, които биха им създали проблеми.
Първият пример е елементарен, но е хубаво да му се обърне внимание. Впрочем, някой можели да обясни, защо след като ++ има по-голям приоритет от =, х не е 1?

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


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


Чет Юли 21, 2005 2:00 pm
Профил WWW
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Юни 16, 2005 11:04 am
Мнения: 37
Мнение 
Трябва да се обясни разликата между:
Код:
x = ++i ;
x = i++ ;


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


Чет Юли 21, 2005 2:20 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Ясно разбрах го. Явно в този случай, приоритетите се определят от правилото:
Код:
x=i++;   //присвои i на x и увеличи i с едно
x=++i;   //увеличи стойността i с едно и я предай на x


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


Чет Юли 21, 2005 3:04 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
Не ми е много ясно това понятие двуменсен масив, предполагам че ще е по-лесно с масив от масиви.


Чет Юли 21, 2005 3:09 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
С два масива става без проблеми, въпросът е дали може с един.
Задачата е да се транспонира матрица и то с един масив.
Нещо подобно
Код:
int arr[3][3];

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


Чет Юли 21, 2005 3:13 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Фев 25, 2005 1:58 pm
Мнения: 4585
Местоположение: US
Мнение 
Код:
/* 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
*/


Чет Юли 21, 2005 3:31 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
pirev страшен си :D тръгна от раз.


Чет Юли 21, 2005 3:45 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
A ше обясните ли каква е идеята на такъв масив и с какво се различава от масив от масиви например :)


Чет Юли 21, 2005 5:01 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Хищник то това също се явява един вид масив от масиви.
По-точно имаш един масив, като всеки елемент от масива е друг масив. Хубавото в случая е, че поинтерите ти позволяват да използваш паметта динамично. Т.е. не е нужно да задаваш големината на масивите при компилация, а можеш да я определиш от потребителски вход или по други начини по време на изпълнение (което си е огромен плюс ако не знаеш колко големи масиви ти трябват точно).
В моя случай програмата създава квадратна матрица с m реда и m колони и това m го определя юзера, после разменя редовете и колоните и ако матриците са равни (т.е. с еднакви елементи) заключва, че матриците са симетрични. И това става много гъвкаво с този метод.


Чет Юли 21, 2005 7:01 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
Hqma takyv forum drug po CBETA :D MEPCU :D


Чет Юли 21, 2005 9:09 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Пет Май 27, 2005 1:32 pm
Мнения: 40
Местоположение: Sofia
Мнение 
Цитат:
Ясно разбрах го. Явно в този случай, приоритетите се определят от правилото:
Код:

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


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


Пет Юли 22, 2005 11:14 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
breeze разбирам какво имаш в предвид, но за какви други разлики става въпрос? Я дай някои примери.


Пет Юли 22, 2005 12:38 pm
Профил WWW
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Пет Май 27, 2005 1:32 pm
Мнения: 40
Местоположение: Sofia
Мнение 
ОК :)
Извинявам се за тъпия пример но не е изключено някой да напише следното:
Цитат:
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 иначе ще се чеше по главата и ще се чуди какво му е недефинираното поведение на този код.


Пет Юли 22, 2005 2:16 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Ето още една интересна "грешка", с която се сблъсках днес. Пишех програма, която да демонстрира 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 пъти
Нед Юли 24, 2005 10:11 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Е сега вече няма да ми повярвате :lol: , но
Код:
(*pcurrent)++

и
Код:
*pcurrent++;

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


Пон Юли 25, 2005 2:26 am
Профил WWW
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 16 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 0 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни