Sunday, July 29, 2012

Багаж

Энэ блогийг удаан хөтөлсөнгүй гэхдээ хүмүүс мэр сэр ордог бололтой одооноос бага багаар мэдээ нэмж байнаа.

Энэ удаад C++ програм бичихийн тулд эхлээд ямар ямар програм суулгах шаардлагатай талаар дурдая.

C++ дээр програм бичих гэж байгаа бол эхлээд өөрийнхөө зэвсэгээ бэлтгэх хэрэгтэй.

GNU compiler гэж гүүглэдээд өөрийнхөө ашиглаж буй үйлдлийн системд суулгах талаар санаа тавиарай. Хэрэв windows ашиглаж байгаа бол mingw суулгаад bin хавтасын замыг нь system PATH хувьсагчдаа нэмэхэд болно.


Харин одоо eclipse хэмээх IDE програмыг суулгах хэрэгтэй. Энэ програмыг ажиллуулахын тулд танд java хэрэг болж магадгүй, багахан хэмжээтэй тул татаж аваад суулгаарай.

Эцэст нь CDT буюу C Development Tools хэмээх eclipse ийн плагинийг eclipse дээрээ нэмж суулгана. install CDT eclipse гэж google-ээс хайгаад суулгах зааврыг үзээрэй.

Товчхондоо ийм, ингээд та C++ програм бичиж чадна. Асуух зүйл гарвал комментээр хэлэлцээрэй. Good Luck!

Friday, February 5, 2010

QuickSort буюу хурдан эрэмбэлэлтийн алгоритм

Энэ алгоритмыг хоёр янзаар бичиж болно.  Нэг нь рекурсив функцтайгаар нөгөөх нь стек өгөгдлийн бүтцийг ашиглаж рекурсгүй хийх боломжтой.
Рекурсив функцийг ашигласан код
template <class Type>
int partition(Type a[],int l,int r)
{
     Type v = a[r];
     int i = l-1, j = r;
     for(;;)
     {
          while(a[++i]
          while(j>1&&a[--j]>v);
          if (i>=j) break;
          swap(a,i,j);
     }
     swap(a,i,r);
     return i;
}
void quickSort(Type a[],int l,int r)
{
     if (l
     {
          int i = partition(a,l,r);
          quickSort(a,l,i-1);
          quickSort(a,i+1,r);
     }
}

Рекурсгүй хувилбар нь
template <class Type>
void quickSort(Type a[],int l,int r)
{
     int i;
     Stack<int> st;
     for(;;)
     {
          while(r>l)
          {
               int i = partition(a,l,r);
               if (i-1>r-i)
               {
                    st.push(l); st.push(i-1);
                    l = i+1;
               }
               else
               {
                    st.push(i+1); st.push(r);
                    r = i-1;
               }
          }
          if (st.empty()) break;
          st.pop(r); st.pop(l);
     }
}

hg
[бичигдэж байна...]

Saturday, January 23, 2010

C/C++ Binary Search function in Standard Library

C/C++ хэлний стандарт сангуудын нэлээд хүчирхэг нэгэн Функц болох bsearch функц stdlib.h/cstdlib толгой файлд тодорхойлогдсон байдаг. Хэрэв өгөгдсөн элемэнт өгөгдсөн эрэмбэлэгдсан массивт байхгүй бол NULL заагчийг буцаадаг.
void * bsearch ( const void * key, const void * base, size_t num, 
size_t size, int ( * comparator ) ( const void *, const void * ) );
key - хайж буй элемэнтийн санах ойд эзлэх хаяг
base - хайлт хийж буй массив
num - массивт хайлт хийх хэмжээ
size - массивийн өгөгдлийн төрлийн санах ойд эзлэх хэмжээ
compareFunction - харьцуулалт хийх функийн нэр. Харьцуулалт хийх функцийг миний өмнө бичсэн qsort() функцийг ашиглахад хэрэглэх зарчимтай ижил.
int compareMyType (const void * a, const void * b)
{
  if ( *(MyType*)a >  *(MyType*)b ) return 1;
  if ( *(MyType*)a == *(MyType*)b ) return 0;
  if ( *(MyType*)a <  *(MyType*)b ) return -1;
}

Жишээ код:

Wednesday, January 6, 2010

C/C++ дээр байдаг inline түлхүүр үгийн үүрэг

Сэдэвтэй холбоотой нийтлэл тул блогоосоо копи паст хийв.

Функцийн амин чухал үүргүүдийн нэг нь санах ойг хэмнэх байдаг. Өөрөөр хэлбэл функцийг дуудах бүрийд програмын удирдлага нэг л газар очдог бөгөөд функц дуудагдах тоогоор програмд давтагдан бичигдэхгүй гэсэн үг юм. Функц дуудах командад хүрмэгц удирдлага функцийн эхлэлийн команд дээр харайж очих бөгөөд, харин функц ажиллаад дуусахад удирдлага буцаж дуудсан газраа ирдэг.
Функц хэдийгээр санах ойг хэмнэх сайн талтай ч маш олон дуудагдах тохиолдолд програмын хурдад муу нөлөө үзүүлэх боломжтой. Өөрөөр хэлбэл тэр бүрийд шаардлагатай регистрүүдийг стект хийх, аргументүүдийг мөн хадгалах, удирдлагыг шилжүүлэх, буцах бүрийдээ регистрүүдийг сэргээх, удирдлага буцаах зэрэг үйлдлүүд хийгдэнэ.
Биелэлтийн хурдыг нэмэгдүүлэхийн тулд функцийг дотоод функц болгох боломжтой байдаг. Энэ юу гэсэн үг вэ гэхээр ийм функц нь програмыг хөрвүүлэх буюу компайлдах үед функцыг дуудсан газар бүрт нь функцрүү чиглүүлсэн удирдлага шилжүүлэх командыг биш харин уг функцын командуудыг шууд орлуулан бичдэг. Том хэмжээтэй функцүүдийн хувьд энгийн аргаар зохион байгуулах нь илүү байж болох юм. Харин цөөн тооны коммандуудаас тогтсон функцүүдийг дотоод биш болгон зохион байгуулах нь санах ойн хувьд ч бараг хэмнэлтгүй (алдагдалтай ч байж болно), хурдны хувьд ч алдагдалтай байж магадгүй. Нэг програмд тун олон удаа давтагдан орж байгаа бага хэмжээний бүлэг үйлдлийг функц болголгүй дахин давтан бичих нь програмын хурдыг нэмэх боловч програм дэндүү нүсэр бүтэцтэй ойлгомж муутай болох аюултай. Ийм л тохиолдолд дотоод функцийг ашиглах нь зүйтэй. Дараах жишээнд дотоод функцийг ашиглаж үзүүлсэн байна.
#include <iostream>
using namespace std;
inline float lbsToKg(float pounds)
{
return 0.453592*pounds;
}
int
main(void)
{
float lbs;
cout << "Jingee oruul (funteer) :";
cin >> lbs;
cout << "Tanii jin (kilogramaar) :"
<< lbsToKg(lbs);
}

Дотоод функцийг тодорхойлохын тулд inline гэсэн түлхүүр үгийг функцийн тодорхойлолтод хэрэглэх хэрэгтэй. Харин функцийн урьдчилсан тодорхойлолт биш, жинхэнэ биеийг нь үндсэн програмаас өмнө тодорхойлж өгсөн байх ёстой. Уг функцийн биеийг програм дотор шууд орлуулан ашиглах ёстой учраас ийм шаардлага бий болж байна. Энэ тохиолдолд функцийн урьдчилсан тодорхойлолт шаардагдахгүй.

Monday, January 4, 2010

Quick sort

C/C++ хэлэнд хурдаараа хамгийн дээгүүрт орох quicksort буюу хурдан эрэмбэлэлтийг stdlib.h санд оруулж өгсөн байдаг. Бодлого бодох гээд яарж байхад эрэмбэлэлтийн код бичихгүй, залхуу (бас эрэмбэлэлтийн функц бичиж дадаагүй) хүнд хичнээн амар гээч :)
Гэхдээ шууд идэхэд бэлэн доширак арай биш, эрэмбэлэх гэж байгаа массив маань ямар төрлийн элемэтүүдээс бүрдэхээс шалтгаалж харилцан адилгүй харьцуулах функц бичнэ.
int төрлийн массив эрэмбэлэх бол:

int compare_int(const void *a,const void *b) {
        int *x = (int *) a;
        int *y = (int *) b;
        return *x - *y;
}

Бутархай тоон массив бол:

int compare_double(const void *a,const void *b) {
        double *x = (double *) a;
        double *y = (double *) b;
        if (*x < *y) return -1;
        else if (*x > *y) return 1; 
        return 0;
}

Тэмдэгт мөр буюу char* эрэмбэлэх бол:
#include <string.h>
int compare_str(const void *a,const void *b) {
        return (strcmp((char *)a,(char *)b));
}
гэх маягаар програмыхаа хамгийн дээр нь зарлаад өгчихнө. Харин програм дундаа хурдан эрэмбэлэлтийг ашиглахдаа:

qsort(массивийн нэр,эрэмбэлэх хэмжээ,
        sizeof(массивийн өгөгдлийн төрлийн нэр),харьцуулах функцийн нэр);

Жишээ кодууд:
/*
int массив эрэмбэлэх
*/
#include <stdio.h>
#include <stdlib.h>
int compare_int(const void *a,const void *b) {
        int *x = (int *) a;
        int *y = (int *) b;
        return *x - *y;
}
int main(){
        int i;
        int a[] = {9, 45, 234, 32, 3424, 345, 78, 85}; 
        qsort(a, 8, sizeof(int), compare_int);
        for(i = 0; i < 8; i++){
                printf("%d\n", a[i]);
        }      
return 0;
}

/*
Тэмдэгт мөр эрэмбэлэх
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_str(const void *a,const void *b) {
        return (strcmp((char *)a,(char *)b));
}
int main(){
        int i;
        char a[4][20] = {"Sharavsambuu", "Xacaa", "Munkhbaatar", "Gansukh"}; 
        qsort(a, 4, sizeof(a[0]), compare_str);
        for(i = 0; i < 4; i++){
                printf("%s\n", a[i]);
        }      
return 0;
}

Saturday, November 7, 2009

Си болон Си++ ийн тухай жаахан

Cи хэл бол Cи++ ийн дэд олонлог гэж ойлгож болно. Эхлээд Си гэж процедур хандалтадат хэл гэж байж байгаад дараагаар нь түүнд объект хандалтад програмчлалын технологийг нэвтрүүлж өгсөнөөрөө Си++ болсон байнаа. Гэхдээ одоо ч аль альнийг нь ашигладаг бөгөөд тус тусын давуу талуудтай. Тэгэхээр энэ хоёр бол ялгаатай бие даасан хэл юмаа. Гэхдээ Си++ дотор Си хэлээр бичих боломжтой. Үүгээрээ жаахан ялгаа бий. Си++ хэлийг сурна гэдэг объект хандалтад технологитой Си хэлийг сурна гэж хараар ойлгож болноо. Эхлээд Си хэлийг сураад дараагаар нь объект хандалтад технологийг Си++ хэлээр сурах юмаа. Си/Си++ хэлний тухай нэлээн хэдэн монгол номнууд худалдаанд гарсан байдаг авч уншихыг зөвлөе. Програмчлана гэдэг тухайн програмчлалын хэлний ойлгогдох хэлээр хүн компьютерт заавар өгөн үйлдлүүдийг хөтөлбөржүүлж өөрийн хүссэн ажилаа хийлгүүлэх боломжтой болгохыг хэлж байгаа юмаа. Тэгэхээр Си хэлний ойлгодог хэлээр нь хүн эхлээд заавруудаа текст файлд хадгалах хэрэгтэй байдаг. Тэр хадгалсан файл нь *.c, *.c++, *.h, *.cc ... гэх мэт өргөтгөлтэй байнаа. Үүнийг ямар ч текст засварлагчаар нээсэн доторхи бичсэн Си хэл дэх үгүүд нь хүнд уншигдахаар ойлгомжтой байх болноо. Яагаад гэвэл эдгээр Си хэлний файлын өргөтгөлүүд нь текст файл хэлбэртэй болохоор тэр. Энэ файлуудыг компьтер ажиллуулъя гэвэл юу ч ажиллахгүй хулганаараа товшвол таны текст засварлагч л тэр файлыг онгойлгон нээх байх :) юу гэх гээд байна вэ гэвэл одоо бичсэн энэ текст файлаа компьютерийн ойлгодог хоёртын хэлрүү өөрөөр бинари лүү хөрвүүлэх хэрэгтэй. Виндөүсийн хувьд *.exe файлуудыг хулганаараа товшихоор ажилладаг биздээ. Энэ *.exe файлыг текст засварлагчаар нээвэл баахан л 0 1 1 0 0 1 1 01 0101 1 01 01101 1 101 0101 1 101 гэсэн юм л харагдах байхдаа кккккк. Учир нь эдгээр кодуудыг зөвхөн компьютер л өөрөө ойлгон биелүүлдэг. Хүн ойлгоход маш төвөгтэй байгаа биз. Хуучин хамгийн анх компьютер үүсч байхад инженэрүүд энэ кодуудыг нэг бүрчлэн өөрсдөө туузан төхөөрөмж дээр бичиж програмчилдаг байсан гэж бодохоор л хар дармаар. Тодорхой 1 0 1 1 0 бла бла бла гэсэн командан тус бүрт нэг англи үг харгалзуулснаар ассемблэр гэдэг нэртэй програмчлалын хэл үүссэн. Энэ бол тухайн үедээ маш том давуу тал нээлт болсон нь гарцаагүй. Учир нь програмчлагчид кодоо хүний ойлгогдох хэлээр бичдэг болсон шүү дээ. Гэтэл ассемблэр хэл бас л ойлгоход бэрх доод түвшнийх мөн алдаа их гаргах боломжтой том төслүүд дээр хэтэрхий их зардалтай гэх мэт сул тал гарсан тул Си гэх мэт арай л дээд түвшний хэлнүүд бий болжээ. Си хэл ассамблер шиг хангалттай доод түвшинд хандах боломжтой болохоор л өнөөдөр оршин тогтносоор буй. Дээд түвшний объект хандалтад Си++, Жава, Файтон ... гэх мэт хэлүүдэд цаанаа доод түвшинд яг юу болоод байгаа нь ойлгомжгүй. Харин Си хэл бол доод түвшин болоод дээд түвшний хоорондох блансыг хамгийн сайн барьж чадсан хэл юмаа. Ийм доод түвшинд хандах боломжтой болохоор л Си хэлийг гар утас жижиг төхөөрөмжүүдийн програмыг бичих үйлдлийн систем бичих гэх мэт нарийн ширийн зүйлд ашиглаж байнаа. За жаахан хадуурваа :)
Бичсэн текстэн файлаа тэгвэл хөрвүүлэгч(компилятор, compiler) програмын тусламжтайгаар машины хэлрүү хөрвүүлдэг байхнаа. Энэ хөрвүүлэгч програмууд нь дотроо маш олон янз. Жишээ нь микрософтын визуал студийн Си/Си++ хөрвүүлэгч програм, GNU gcc g++, Mars, mingw гэх мэт маш олон хөрвүүлэгчид байдаг байхнээ. Алийг нь ч ашиглаж Си болон Си++ програм бүтээх боломжтой. Гэхдээ нээлттэй эхийнхэн GNU gcc, g++ хөрвүүлэгчидийг ашигладаг энэ бол таны сонголт байх болно. Энэ хэлний түүхийн талаар википедиа эсвэл энд тэндэхийн номноос харах боломжтой би энд орчуулж тавьхаас залхуурав :) аа тийм мөн Си хэл нь олон зүйлд хэрэглэгддэгийн хувьд ISO, ANCII гэх мэт том том стандарчлалын байгууллагуудаар стандарчлагдсан байдаг.

За одоо олимпиад тэмцээнд орох эсвэл дээд сургуульд Си хэл ороход хэрэглээд байдаг цэнхэр дэлгэц бүхий BorlandC turboC энэ тэрийн талаар өөрийн бодлоо жаахан бичье. Эдгээрийг та зүгээр л жаахан боломж нэмсэн notepad эсвэл текст засварлагч мэтээр төсөөлөх хэрэгтэй. DOS цонх гаргаад програм бичихээр яахав бусад хүмүүст арай нэг мэргэжлийн юм хийгээд ч байгаа юм шиг гүү ч юм шиг харагддаг байхаа :) гэхдээ л энэ бол текст засварлагч. Си Си++ програм бичихэд заавал ийм цэнхэр дэлгэцэн дээр бичих шаардлагагүй ээ. Гэхдээ энэ бол таны л мэдэх хэрэг. Дээр би олон янзын хөрвүүлэгч байдаг талаар дурдсаан. Тэгвэл Borland-ийн Си хөрвүүлэгч програм бас байдаг байхнээ. Бид тэр цэнхэр дэлгэцэн дээр програмаа биччихээд CTRL+F9 дарахад цаанаа бол borland өөрийнхөө хөрвүүлэгчээр таны хадгалсан cpp эсвэл с файлыг exe рүү буюу машины ажилладаг файлруу хөрвүүлчихэж байгаа юм. Тэгээд л ажиллуулаад үр дүнгүүд хар дэлгэцэн дээр хэвлэгдэн харагддаг. Энэ хар дэлгэцийг консоль гэх бөгөөд printf cout функцүүдийн тусламжтайгаар үүн дээр үр дүнгүүдээ хэвлэн харж авах боломжтой. Үр дүнг ер нь бол файлруу хэвлэсэн ч болно шүү дээ :) гэхдээ ийм байдлаар хэвлэн харах нь илүү хурдан байх болно.

Ерөнхийдөө Си хэл дээр ажилладаг програм үүсгэхэд дараах дараалалтай байна:
- Си хэлний өгүүлбэрзүйгээр кодоо бичиж cpp, c, h гэх мэт өргөтгөлтэй текстэн файлуудаа үүсгэнэ.
- Compiler буюу хөрвүүлэгч програмаа дуудна.
- соорс файл тус бүрийг объект код гэдэг завсарын объектэн файлууд болгож үүсгэнэ
- linker буюу холбогч програмыг ажиллуулж эдгээр олон объект файлуудыг нэгтгэн тухайн үйлдлийн систем бүтэц дээр ажиллах боломжтой binary програм буюу хоёртын програмыг үүсгэнэ. Windows дээр бол exe файл үүсдэг линукс дээр бол өргөтгөл гол биш бусад үйлдлийн систем дээр яадгийг мэдэхгүй гэхдээ л өөрийн гэсэн формат үүсгэдэг л байх.
- Програмаа ажиллуулж шалгаж үзэх.

IDE гэдэг үгний товчлолийг та хаа нэгтээгээс харж л байсан байх. Integrated Development Environment гэсэн үгний товчлол бөгөөд монголоор нэгтгэсэн хөгжүүлэлтийн орчин гэсэн үг юм. Тэгэхээр Си хэлний өгүүлбэрзүйг гоё өнгөөр ялган харуулж хөрьвүүлж ажиллуулж шалгаж тайлагнах боломжтой мөн бусад олон боломж бүхий боломжтой текст засварлагчийг IDE гэдэг. Жава дээр бол Netbeans, Eclipse, Borland JBuilder гэх мэт IDE байдаг. Тэгэхээр энэ BorlandC гэдэг програм чинь маш олон янзын IDE-үүдийн л нэг байхнээ. Миний мэдэх Си IDE гэвэл Visual studio C++, Eclipse, netbeans, mingw, CodeBlock, CodeWarrior, BorlandC, TurboC гэх мэт олон янз байнаа.

Friday, July 3, 2009

Заагчууд санах ойд хэр хэмжээ эзэлдэг вэ?

[sharavsambuu@localhost tsedevsuren]$ more sample.cpp
#include <iostream>
using namespace std;
int main()
{
unsigned char *uc;
char *c;
short int *si;
unsigned int *ui;
int *i;
unsigned long *ul;
long *l;
float *f;
double *d;
long double *ld;
struct TWorker
{
int i;
char name[20];
char carrer[20];
int workdays;
int moneyOfDay;
float salary;
};
TWorker *w;
cout<<"санах ойд эзлэх хэмжээ unsigned char: "<<sizeof(uc)<<endl;
cout<<"санах ойд эзлэх хэмжээ char: "<<sizeof(c)<<endl;
cout<<"санах ойд эзлэх хэмжээ short int: "<<sizeof(si)<<endl;
cout<<"санах ойд эзлэх хэмжээ unsigned int: "<<sizeof(ui)<<endl;
cout<<"санах ойд эзлэх хэмжээ int: "<<sizeof(i)<<endl;
cout<<"санах ойд эзлэх хэмжээ unsigned long: "<<sizeof(ul)<<endl;
cout<<"санах ойд эзлэх хэмжээ long: "<<sizeof(l)<<endl;
cout<<"санах ойд эзлэх хэмжээ float: "<<sizeof(f)<<endl;
cout<<"санах ойд эзлэх хэмжээ double: "<<sizeof(d)<<endl;
cout<<"санах ойд эзлэх хэмжээ long double: "<<sizeof(ld)<<endl;
cout<<"санах ойд эзлэх хэмжээ TWorker: "<<sizeof(w)<<endl;
return 0;
}


[sharavsambuu@localhost tsedevsuren]$ g++ -o sample sample.cpp
[sharavsambuu@localhost tsedevsuren]$ ./sample
санах ойд эзлэх хэмжээ unsigned char: 4
санах ойд эзлэх хэмжээ char: 4
санах ойд эзлэх хэмжээ short int: 4
санах ойд эзлэх хэмжээ unsigned int: 4
санах ойд эзлэх хэмжээ int: 4
санах ойд эзлэх хэмжээ unsigned long: 4
санах ойд эзлэх хэмжээ long: 4
санах ойд эзлэх хэмжээ float: 4
санах ойд эзлэх хэмжээ double: 4
санах ойд эзлэх хэмжээ long double: 4
санах ойд эзлэх хэмжээ TWorker: 4
[sharavsambuu@localhost tsedevsuren]$

Эндээс харахад заагчууд төрлөөс үл хамааран санах ойд 4-н байт хэмжээтэй байдаг байхнээ.