Skip navigation.

Log in | Sign up

Joomla trong ubuntu

Cài LAMP trên Ubuntu. Trong đó LAMP là viết tắt của Linux+Apache+MySql+Php.

1. Đầu tiên khởi động Terminate (Applications > Accessories > Terminal)
2. Cài đặtApache2 bằng lệnh: sudo apt-get install apache2
3. Cài đặt php5 bằng lệnh: sudo apt-get install php5 libapache2-mod-php5 php5-gd
4. Cài đặt mysql bằng lệnh: sudo apt-get install mysql-server libapache2-mod-auth-mysql php5-mysql mysql-client
5. Cài đặt phpmyadmin bằng lệnh: sudo apt-get install phpmyadmin
6. Khởi động lại service của Apache2: sudo /etc/init.d/apache2 restart
Sử dụng LAMP
Webserver: http://localhost (hoặc http://tenmay hoặc http://địa chỉ ip LAN hoặc http://172.0.0.1)
MySQL Database: http://localhost/phpmyadmin
Dường dẫn cho webserver: /var/www/


Tôi giả định các bạn đã cài đặt LAMP thành công trong Ubuntu

Tải về Joomla tại trang chủ: www.joomla.org

Unzip Joomla vào thư mục /var/www hoặc thư mục con /var/www/joomla. Để thuận lợi, tôi giả định folder cài đặt joomla là /var/www/joomla.

Các việc cần làm là:

* Thiết lập quyền ghi/xoá đối với các Joomla instance
* Thiết lập bảo mật: chmode cho file là 644 và folder là 755.
*

# 1. Allow writting in whole joomla subtree

sudo chown -R www-data:www-data /var/www/joomla


# 2. Handle file and directory permissions

cd /var/www/joomla
sudo find . -type f -exec chmod 644 {} \;
sudo find . -type d -exec chmod 755 {} \;

Đến đây, bạn có thể tiến hành cài đặt Joomla như thông thường.

Bước 2.1: Từ trình duyệt gõ http://localhost/Joomla, xuất hiện giao diện sau. Chọn ngôn ngữ mặc định là English.


Bước 2.2: Nếu các giá trị kiểm tra có màu xanh thì OK. nếu có màu đỏ thì xem lại phần phân quyền xem có đúng không. Mình chìm 2 ngày ngay phần này. hic


Bước 2.3: Hiển thị thông tin về bản quyền của Joomla. Nếu rãnh thì đọc.


Bước 2.4: Thiết lập các thông số kết nối đến CSDL MySQL


- Hostname: điền vào "localhost"

- User name: Tên tài khoản có quyền đối với cơ sở dữ liệu chứa Joomla của bạn.

- Password: Mật khẩu của tài khoản trên

- Availbe Collations: Bạn nên chọn là "utf8_general_ci"

- Database Name: Tên cơ sở dữ liệu của bạn. Ở đây là myCMS


Bước 2.5: Thiết lập các thông số FTP


Bỏ qua. Do cài trên localhost nên không cần quan tâm.


Bước 2.6: Thiết lập cấu hình site Joomla của bạn


- Site name: tên site của bạn.

- Your Email: địa chỉ email của bạn

- Admin Password: Mật khẩu để quản trị Joomla

Các thông số trên sau này đều có thể thay đổi dễ dàng nên bạn không cần bận tâm lắm. Chỉ cần nhớ mật khẩu là đủ.

- Install Defaul Sample Data: Cài đặt dữ liệu mẫu. Bạn nên nhấn nút này để Joomla tạo mẫu cho bạn một trang web đơn giản.


Bước 2.7: Kết thúc

- Lưu ý: tài khoản truy nhập hệ thống là: admin; mật khẩu: mật khẩu mà bạn đã gõ ở bước 6.

- Để xem Website của bạn: Trước tiên bạn phải xoá (với quyền root) thư mục installation trong /var/www/joomla
hoặc dùng lệnh:

Code:

sudo rm -R /var/www/joomla/installation/


Sau đó, nhấn vào nút Site và lúc ta có đường dẫn:

* http://localhost/Joomla/index.php

mới xem được.

- Để quản trị Website: Nhấn vào nút Admin và có đường dẫn:

* http://localhost/Joomla/administrator


Suu tam

(Scope) và (Lifetime)


Tai sao sach noi khai bao bien theo kieu static trong mot khoi nao do thi sau khi thuc hien xong thi no se luu lai trong bo nho ?. The ma chuong trinh sau sau khi thuc hien xong a() lan 1 thi trong debug khong hieu ivalue2 la gi ?

#include <iostream.h>

int ivalue1=1;

void a();

main()
{
//static int ivalue2=1;
extern int rvalue=0;
int ivalue3=0;
cout <<ivalue1/*<<ivalue2*/<<ivalue3<<endl;
a();
a();
return(0);
}

void a()
{
static int *pivalue1=&ivalue1;

int ivalue1=32;
static int ivalue2;
ivalue2+=2;

cout <<ivalue1<<ivalue2<<*pivalue1<<endl;
}

Giai Dap:

Có hai khái niệm khác nhau, nhưng nhiều lúc chúng ta hay bị nhầm lẫn chúng với nhau, đó là phạm vi hoạt động (scope) và thời gian tồn tại (lifetime) của một biến.

Phạm vi hoạt động của một biến xác định ở những phần nào của chương trình, biến đó có thể được "nhìn thấy", tức là bạn có thể sử dụng biến đó trực tiếp thông qua tên biến. Các biến trong C có thể có một trong các phạm vi hoạt động như sau:

1. Block scope.
các biến được khai báo bên trong 1 block sẽ có Block Scope. Chúng chỉ có thể được sử dụng bên trong Block đó mà thôi, khi chương trình thoát ra khỏi block đó, các biến đó trở thành "không nhìn thấy".

2. Function Scope.
Tất cả các biến khai báo ở đầu một hàm, cũng như các tham số của hàm đều có Function Scope. Phạm vi hoạt động của chúng là bên trong hàm đó, bên ngoài hàm thì chúng là invisible.

3. File Scope
Đó là các biến được khai báo bên ngoài các hàm ở trong một file. Để giới hạn phạm vi hoạt động của chúng trong file đó thôi thì chúng ta phải dùng từ khoá static để khai báo. (chú ý, là có sự khác biệt khi khai báo một biến dùng từ khoá static bên trong hàm, và bên ngoài hàm. Bạn sẽ rõ hơn khi đọc nốt phần còn lại dưới đây). Bạn chỉ có thể sử dụng các biến có File Scope bên trong file đó mà thôi, bên ngoài file đó, chúng là invisible.

4. Global Scope
Đó là các biến được khai báo bên ngoài tất các các hàm (kể cả hàm main()), nhưng phía trước nó không có từ khoá static (nếu không thì nó đã trở thành File Scope). Một biến có Global Scope chỉ có thể được định nghĩa tại một file mà thôi. Nếu bạn định nghĩa 2 biến có cùng tên và cùng có Global Scope thì compiler sẽ báo lỗi ngay. Nếu bạn muốn dùng biến đó trong một file khác thì bạn phải thông báo cho Linker biết là biến đó đã được định nghĩa ở một file (unit) nào đó rồi. Bạn làm việc đó dùng từ khoá extern . Ví dụ:

extern int count;

Thời gian tồn tại (lifetime) của một biến xác định khoảng thời gian mà giá trị của biến đó được lưu trữ trong chương trình. Các biến trong C có thể quy về hai dạng là những biến chỉ tồn tại trong một khoảng thời gian ngắn so với thời gian hoạt động của cả chương trình, và những biến sẽ tồn tại trong toàn bộ thời gian hoạt động của chương trình.

Tất cả những biến được khai báo bên ngoài các hàm sẽ có thời gian tồn tại là cả chương trình (tức là những biến có File Scope và Global Scope). Mặc dù chúng tồn tại cùng với thời gian thực hiện của chương trình, nhưng chỉ có các biến có Global Scope mới được nhìn thấy trong toàn bộ chương trình, các biến có File Scope chỉ được nhìn thấy trong file đó thôi, bên ngoài file đó, chúng vẫn tồn tại (giá trị mà chúng lưu trữ không hề bị mất đi) nhưng bạn không thể sủ dụng chúng được. Đó chính là sự khác nhau giũa phạm vi hoạt động và thời gian tồn tại của biến.

Bình thường, những biến khai báo trong một hàm hay một block chỉ tồn tại trong hàm đó, hoặc block đó mà thôi. Khi chương trình thoát ra khỏi hàm / block đó thì giá trị mà chúng lưu trữ cũng biến mất theo. Tuy nhiên, bạn có thể muốn có một biến chỉ nhìn thấy trong một block hoặc một hàm, nhưng giá trị mà nó lưu trữ không bị mất đí sau khi chương trình thoát ra khỏi hàm / block. Khi đó bạn dùng từ khoá static để khai báo biến. Khi bạn dùng từ khoá static để khai báo một biến, ý nghĩa của nó sẽ khác nhau, phụ thuộc vào vị trí của biến. Nếu biến đó nằm bên trong một hàm / block thì biến đó sẽ có phạm vi hoạt động là bên trong hàm / block đó, nhưng sẽ tồn tại trong toàn bộ thời gian chương trình thực hiện. Nếu biến đó nằm bên ngoài hàm, thì hiển nhiên là nó sẽ tồn tại cho tới khi nào chương trình thực hiện song, nhưng từ khoá static ở đây có một ý nghĩa khác. Nó thông báo cho compiler biết là bạn muốn hạn chế phạm vi hoạt động của biến bên trong file đó mà thôi.

Về câu hỏi, tại sao trong debug không hiểu ivalue2 là gì, đó là do ivalue2 có phạm vi hoạt động là Function Scope, nó chỉ được nhìn thấy trong hàm a() mà thôi, bên ngoài hàm, nó là invisible, mặc dù giá trị nó lưu trữ vẫn được giữ nguyên vẹn, và lần thứ hai khi bạn gọi a() thì giá trị lần trước bạn gọi hàm sẽ được sử dụng. Bạn muốn thấy nó trong debug, thì phải vào trong hàm mới được.

Trich luoc tai vninformatics

Static


static có tác dụng khác nhau phụ thuộc vào :
- đối tượng của nó (đi kèm theo một biến hay là một hàm).
- vị trí trong mã nguồn ( nó nằm bên trong 1 hàm, mốt lớp hay là 1 file)

1. Đối tượng là một biến

a. Nếu biến đó là biến cục bộ (local variable), tức là biến đó nằm bên trong một hàm nào đó, thì từ khoá static có tác dụng kéo dài thời gian sống (timelife) của biến đó cho đến khi chương trình thực hiện xong. Chắc là bạn đã biết, trong C/C++ một biến cục bộ thường thường chỉ sống một thời gian ngắn. Một khi chương trình thoát ra khỏi block hoăc hàm, nơi mà biến đó được khai báo, thì biến đó cũng không còn tồn tại nữa, tức là giá trị mà biến đó đang lưu trữ cũng sẽ bị mất. Bằng cách dùng từ khoá static khi khai báo biến, ta có thể thay đổi được thời gian sống của biến cục bộ. Tôi xin đưa ra một ví dụ:
#include <iostream>
using namespace std;

int Count()
{
int count = 0;

count++;
return count;
}
int main()
{
int count1, count2;

count1 = Count();
count2 = Count();
cout << "count1 = " << count1 << ", count2 = " << count2 << endl;
return 0;
}
Trong ví dụ này hàm Count() được gọi 2 lần, và kết quả in ra là cả 2 lần hàm đều trả về giá trị 1. Đó là bởi vì biến cục bộ count chỉ lưu trữ giá trị cho đến khi chương trình thoát ra khỏi hàm. Nếu dùng tư khoá static khi khai báo count thì kết quả in ra sẽ khác, lần thứ nhất hàm trả về 1, lần thứ hai hàm trả về 2 :
int Count()
{
static int count = 0;

count++;
return count;
}
Bạn có biết vì sao lại thế không? lý do là sau lần gọi hàm thứ nhất, biến count có giá trị 1. Đến khi hàm được gọi lần thứ hai thì giá trị của count từ lần gọi trước vẫn được lưu giữ, nến nó sẽ trở thành 2. Bạn hãy lưu ý dòng:

static int count = 0;

dòng này có nghĩa là "khỏi tạo biến count với giá trị ban đầu là 0". Vì sau khi sinh ra, count tồn tại cho đến khi chương trình kết thúc nên nó cũng chỉ được khỏi tạo một lần. Lần thứ hai khi chúng ta gọi hàm thì giá trị cũ của count sẽ được sử dụng, chứ không phải nó sẽ được khởi tạo một lần nữa với giá trị 0.

b. Nếu là biến có phạm vi hoạt động là "FILE SCOPE" , tức là biến đó nằm bên ngoài tất cả các hàm và lớp, thì static lại có tác dụng khác. Một biến "FILE SCOPE" thì hiển nhiên nó sẽ sống cho đến khi chương trình thực hiện xong, vì thế từ khoá static không có tác dụng kéo dài thời gian sống của biến, mà nó có tác dụng hạn chế phạm vi hoạt động của biến (scope) trong file đó, nơi mà biến đó được khai báo. Nếu ta không dùng từ khoá static thì từ một điểm bất kỳ trong chương trình, ta có thể truy cập tới biến đó. Khi khai báo biến đó là static thỉ chi những hàm trong file đó mới có thể truy cập đến biến. Bên ngoài file thì biến đó là invisible. Ví dụ ta có 2 file là unit1.cpp và unit2.cpp:
/* unit1.cpp */
int count;
void f1()
{
....
}
/* unit2.cpp */
extern int count; // ba'o cho compiler biet la` ta muon du`ng
// bien count khai ba'o trong unit1.cpp
void f2()
{
....// dung count o day
}
biến count là biến toàn cục nên ta có thể truy cập nó từ unit2.cpp, mặc dù nó được định nghĩa ở unit1.cpp. Nếu ta muốn phạm vi hoạt động của count chỉ hạn chế trong unit1.cpp thôi, thì khai báo nó như sau:

/* unit1.cpp */
static int count;
void f1()
{
....
}

Khi đó chỉ có những hàm trong unit1.cpp mới truy cập được tới count, những hàm trong unit2.cpp không thể sư dụng count được.

c. Nếu biến đó nằm trong phần khai báo của một lớp (class) thì từ khoá static làm cho biến đó có những đặc điểm sau:

- biến được sinh ra từ khi chương trình bắt đầu thực hiện và tồn tại cho đến khi chương trình kết thúc, kể cả khi ta không hề tạo ra bất cứ một đối tượng nào của lớp. Ví dụ:
#include <iostream>
using namespace std;

class CPrint
{
public:
CPrint() { cout << "CPrint constructor" << endl;}
};
class CMyClass
{
static CPrint myPrint;
};
CPrint CMyClass::myPrint;

int main()
{
return 0;
}
Khi chạy chương trình này thì dòng chữ CPrint constructor sẽ được in ra màn hình, mặc dù hàm main() chỉ có duy nhất lệnh return, và trong chương trình không tồn tại một đối tượng nào kiểu CMyClass.
- Đặc điểm thứ hai là ta có thể truy cập đến biến đó trực tiếp thông qua tên lớp. Ví dụ:
CMyClass
{
public:
CMyClass() {}
static int _data;
};
int CMyClass::_data = 5;
main()
{
int data;
CMyClass myClass;

myClass._data = 10; // truy cap theo cach binh thuong
data = CMyClass::_data; // truy cap thong qua ten lop
}
- Đăc điểm thứ ba và cũng là tính chất quan trọng nhất của biến static trong 1 lớp, đó là nó là biến chung cho tât cả các đối tượng có kiểu là lớp đó. Giả sử ta có 2 đối tượng kiểu CMyClass:
main()
{
CMyClass myClass1, myClass2;

myClass1._data = 10;
myClass2._data = 20;
cout << "data = " << myClass1._data << endl;
}
chương trình này sẽ in ra giá trị 20, mặc dù mới đầu chúng ta đã gán giá trị 10 cho _data trong đối tượng myClass1. Đó là bởi vì _data là biến static nên nó là chung cho tất cả các đối tượng kiểu CMyClass, và nếu ta thay đổi giá trị của nó ở một đối tượng này thì cũng tức là ta thay đổi nó ở tất cả các đối tượng còn lại.

2. Đối tượng của static là hàm.
Ngoài trường hợp đi kèm với 1 biến, từ khoá static còn có thể áp dụng cho 1 hàm. Khi dó có 2 khả năng có thể sảy ra: hàm đó thuộc class và hàm đó không thuộc một class nào cả.
a. Dùng static với hàm thuộc lớp. Khi đó cũng giống như là biến static thuộc lớp, ta có thể gọi hàm static trực tiếp thông qua tên lớp. Ví dụ:
class CMyClass
{
public:
CMyClass() {}
static void SetData(int data) { _data = data; }
static int GetData() const { return _data; }

private:
static int _data;
};
int CMyClass::_data;
int main()
{
CMyClass myClass;

myClass.SetData(10);
cout << "data = " << CMyClass::GetData() << endl;
return 0;
}
Một hàm thành viên là static thì nó khác gì với một hàm thành viên bình thường ? Trước hết hàm thành viên static chỉ có thể thao tác với các biến static của lớp. Nếu như _data trong ví dụ trên không phải là biến static thì cả 2 hàm GetData() và SetData() đều không thể truy cập đến _data được. Điểm khác thứ hai là chúng ta có thể gọi 1 hàm thành viên static mà không cần phải tạo ra đối tượng, bằng cách dùng tên lớp giống như ví dụ trên. Bạn cần chú ý là cả biến static và hàm static đều tuân theo quy tắc truy cập giống như các biên và hàm khác, tức là nếu chúng nằm trong phần private của lớp thì chỉ có những hàm thuộc lớp mới có thể sử dụng chúng. Vì thế thường thường các hàm static hay nằm ở phần public, còn các biến static thì hay nằm ở phần private.

b. Dùng static với một hàm nằm ngoài lớp. Nếu một hàm không thuộc một lớp nào thì nó là global trong chương trình. Giả sử chương trình của bạn gồm 2 file là unit1.cpp và unit2.cpp, khi đó các hàm trong unit2.cpp có thể gọi các hàm trong unit1.cpp. Nếu bạn muốn một hàm nào đó trong unit1.cpp chỉ được phép dùng bên trong file đó thôi thì bạn có thể định nghĩa nó là static (giống như là trường hợp với biến static vậy). Làm như thế có 2 cái lợi. Thứ nhất, nếu chúng ta cần thay đổi những hàm đó thì nó chỉ liến quan đến file đó thôi, chứ nó không ảnh hưởng tới những phần khác của chương trình. Thứ hai là bảo đảm không bị trùng lặp về signature của các hàm trong các file khác nhau.

Trich luoc tu vninformatics

Lobachevsky

For many years now, mr. danny kaye, who has been my particular idol since childbirth, has been doing a routine about the great russian director stanislavsky and the secret of success in the acti
Ofession. and I thought it would be interesting to stea... to adapt this idea to the field of mathematics. I always like to make explicit the fact that before I went off not too long ago to figh
The trenches, I was a mathematician by profession. I don't like people to get the idea that I have to do this for a living. I mean, it isn't as though I had to do this, you know, I could be maki
H, 3000 dollars a year just teaching.

Be that as it may, some of you may have had occasion to run into mathematicians and to wonder therefore how they got that way, and here, in partial explanation perhaps, is the story of the great
Ian mathematician nicolai ivanovich lobachevsky.



Who made me the genius I am today,
The mathematician that others all quote,
Who's the professor that made me that way?
The greatest that ever got chalk on his coat.

One man deserves the credit,
One man deserves the blame,
And nicolai ivanovich lobachevsky is his name.
Hi!
Nicolai ivanovich lobach-

I am never forget the day I first meet the great lobachevsky.
In one word he told me secret of success in mathematics:
Plagiarize!

Plagiarize,
Let no one else's work evade your eyes,
Remember why the good lord made your eyes,
So don't shade your eyes,
But plagiarize, plagiarize, plagiarize -
Only be sure always to call it please 'research'.

And ever since I meet this man
My life is not the same,
And nicolai ivanovich lobachevsky is his name.
Hi!
Nicolai ivanovich lobach-

I am never forget the day I am given first original paper
To write. it was on analytic and algebraic topology of
Locally euclidean parameterization of infinitely differentiable
Riemannian manifold.
Bozhe moi!
This I know from nothing.
But I think of great lobachevsky and get idea - ahah!

I have a friend in minsk,
Who has a friend in pinsk,
Whose friend in omsk
Has friend in tomsk
With friend in akmolinsk.
His friend in alexandrovsk
Has friend in petropavlovsk,
Whose friend somehow
Is solving now
The problem in dnepropetrovsk.

And when his work is done -
Ha ha! - begins the fun.
From dnepropetrovsk
To petropavlovsk,
By way of iliysk,
And novorossiysk,
To alexandrovsk to akmolinsk
To tomsk to omsk
To pinsk to minsk
To me the news will run,
Yes, to me the news will run!

And then I write
By morning, night,
And afternoon,
And pretty soon
My name in dnepropetrovsk is cursed,
When he finds out I publish first!

And who made me a big success
And brought me wealth and fame?
Nicolai ivanovich lobachevsky is his name.
Hi!
Nicolai ivanovich lobach -

I am never forget the day my first book is published.
Every chapter I stole from somewhere else.
Index I copy from old vladivostok telephone directory.
This book was sensational!
Pravda - well, pravda - pravda said: (russian double-talk)
It stinks.
But izvestia! izvestia said: (russian double-talk)
It stinks.
Metro-goldwyn-moskva buys movie rights for six million rubles,
Changing title to 'the eternal triangle',
With brigitte bardot playing part of hypotenuse.

And who deserves the credit?
And who deserves the blame?
Nicolai ivanovich lobachevsky is his name.
Hi!

Become an AIESECer


Dear my friend,

It has been a month of knowing you. At the first time reading your application form, I do appreciate a lot for your determination and passion to get involve with us. Having the chance to approach you directly, I have learned great lesson of your enthusiasm. Only you understand well and share with AIESEC the value that is: “the difference between a man and what he wants from life is often merely the will to try it and the faith to believe that it is possible”.

A single step can start new things, and I hope that your life will start from today when you are successful accepted to be an AIESECer. Any day you may wish for a new activity to do, any day you may wish for the start of the process of life changing, and today is this day !

Wish you have enough courage to begin new things

Wish you have enough love to share with others

Wish you have enough faith to be honest with yourself

More than belief, I know that we will hear good news from your development in the future.

Best regards,

Ly Thi Bich Nga
Vice president of Talent Management
AIESEC Ho Chi Minh city Local Committee

**“Be the CHANGE”**

*************************************LOCAL TRAINING SEMINAR**************************************

“PROUD to be AIESECers” is the main theme of our first local training seminar for new members of AIESEC Ho Chi Minh city Local committee. The main objective is to understand deeply the added value of AIESEC to the single person, and society. Most importantly, the seminar is considered as the MUST attending for new members in order to begin your AIESEC life.



The seminar will be hold in 2 days: 17th and 18th Oct at Drink and Talk coffee

** Agenda of 17th Oct:



**Agenda of 18th Oct:



**Click here for registering the seminar:
http://spreadsheets.google.com/viewform?formkey=dDIzR3g0Z3owOEkwUW5RUG5VZVZ5YXc6MA

--
AIESEC Ho Chi Minh Local Committee
AIESEC Viet Nam

Email: aiesec.hochiminh@gmail.com
URL: www.aiesechochiminh.org
Facebook: www.facebook.com/aiesechochiminh

"AIESEC - the international platform for young people to explore and develop their leadership potential, which at last has a positive impact on society."

Bai tap OOP


Hôm bữa tham dự buổi học C# của MSP, thầy giáo có cho 2 bài tập về nhà như sau:

bai 14:
Viet dinh nghia lop String de bieu dien khai niem chuoi ky tu voi cac phuong thuc thiet lap va huy bo, cac ham thanh phan, cac phep toan can thiet (ve mat chuc nang tuong tu nhu su dung thu vien string.h)

bai 15:
Hay dinh nghia lop BIGINT de co the xu ly cac so nguyen lon (so nguyen lon co the tu 1-200 chu so) nhu xu ly cac so kieu int.

Thêm vào đó có một số bài tập OOP mình sưu tầm trên mạng:
http://files.myopera.com/lobachevsky/OOP_FU/baitapoopCNTT.pdf

Tóan tử & mang nghĩa gì?


istream& operator>>(istream& is,CDateTime& dt)
{
is>>dt.time;
is>>dt.date;
return is;
}

ostream& operator<<(ostream& os,const CDateTime& dt){

os<<dt.time<<" - "<<dt.date;
return os;
}
//-------------------------------------------
Bạn nào bik về cái luồng xuất nhập chuẩn này không?


Chương trình đưa ra có rất nhiều điểm đáng để chúng ta phân tích kỹ hơn. Mình sẽ cố gắng giải thích cặn kẽ từng điểm một, nếu có chỗ nào chưa được chính xác hoặc còn thiếu sót gì, mong mọi người bổ sung thêm.

Trước hết lớp CDateTime ở đây khai báo 2 biến (là date và time) thuộc phần private của lớp, vì thế chỉ có những hàm thành viên của lớp mới có thể truy cập trực tiếp tới 2 biến này. Tuy nhiên C++ cho phép một hàm hoặc một lớp không phải thành viên của CdateTime vẫn có thể truy cập tới 2 biến đó. Muốn được như vậy, bạn phải dùng từ khoá friend để thông báo chó trình biên dịch biết ý định của bạn, là hãy coi những hàm / lớp đó như là thành viên của CDateTime. Trong ví dụ ở đây, 2 lớp istream và ostream không phải là một phần của lớp CDateTime, nhưng chúng vẫn có thể thao tác với date và time, nhờ có từ khoá friend đứng đằng trước chúng.

Hai lớp istream và ostream là 2 lớp thuộc thư viện C++. Chúng có định nghĩa 2 toán tử (<<) và (>>). Tất cả các kiểu dữ liệu built-in (như int, float, char...) đều được hỗ trợ trực tiếp bởi 2 toán tử này, vì thế trong chương trình bạn có thể sử dụng cin và cout (là các instance tương ứng của 2 lớp đó) để hiển thị dữ liệu ra màn hình, hoặc nhận dũ liệu từ bàn phím. Tuy nhiên, nếu bạn muốn sử dụng 2 toán tử này để làm công việc đó với những kiểu dữ liệu do bạn tự định nghĩa (như CDateTime trong vị du này) thì bạn bắt buộc phải định nghĩa lại 2 toán tử đó. Đó chính là lý do tại sao lại xuất hiện 2 dòng sau trong lớp Complex:

friend istream& operator >>(istream&,complex&);
friend ostream& operator <<(ostream&,complex&);

Bây giờ mình sẽ lần lượt trả lời những thắc mắc mà bạn nêu ra.

1. Tại sao 2 toán tử đó lại trả về 2 đối tượng kiểu istream& và ostream& ?

Trước hết, toán tử (<<) phải trả về đối tượng kiểu ostream và toán tử (>>) phải trả về đối tượng kiểu istream. Sở dĩ có yêu cầu đó, là để bạn có thể viết những lệnh tương tự như lệnh dưới đây trong chương trình:

cout << "Date: " << z << endl;

Như bạn thấy, cout chỉ cần viết một lần ở đầu dòng, sau đó bạn có thể sử dụng toán tử (<<) nhiều lần để hiển thị lần lượt những thông tin khác nhau. Dòng lệnh này vẫn thực hiện đúng những gì bạn muốn là bởi vì sau mỗi lần được gọi, toán tử (<<) lại trả về một đối tượng kiểu ostream. Nếu nó không trả lại đối tượng kiểu đó, thì để viết dòng lệnh trên, bạn sẽ phải gọi cout 3 lần tương ứng với những thông tin bạn muốn hiển thị.

Tới đây thì chúng ta đã rõ là 2 toán tử này phải trả về 2 đối tượng tương ứng, nhưng tại sao chúng ta lại phải khai báo là istream& và ostream& chứ không phải istream và ostream ? Đó là bởi vì C++ quy định chỉ được phép tồn tại duy nhất một instance của istream và một instance của ostream trong chương trình. Khi bắt đầu một chương trình thì 2 đối tượng tự động được sinh ra cho bạn, đó là cin (kiểu istream) và cout (kiểu ostream). Vì thế bạn không được phép sinh ra thêm bất kỳ một đối tượng nào khác thuộc 2 lớp đó. Mặt khác theo mặc định, C++ luôn trả về bản sao của một đối tượng, chứ không phải bản thân đối tượng đó. Nếu như vậy thì chúng ta đã không theo đúng quy định của C++ là chỉ được phép tồn tại duy nhất 1 đối tượng kiểu istream và 1 đối tượng kiểu ostream. Lối thoát duy nhất ở đây là chúng ta phải dùng cơ chế trả lại giá trị từ một hàm theo tham biến (reference). Khi đó bản thân đối tượng sẽ được trả lại, chứ không phải bản sao của nó.

2. Tại sao tham số thứ nhất của 2 toán tử lại là istream& và ostream& ?

Tất cả các toán tử trong C++ đều đòi hỏi tham số thứ nhất phải là đối tượng thuộc lớp mà tại đó, chúng được định nghĩa. Trong ví dụ ở đây, lớp CDateTime không hề định nghĩa 2 toán tử (<<) và (>>), mà nó chỉ định nghĩa lại 2 toán tử này thuộc lớp istream và ostream. Giả sử 2 toán tử này được định nghĩa trực tiếp trong CDateTime, khi đó từ khoá this sẽ được truyền cho 2 toán tử như là 2 tham số đầu tiên. Có điều bạn sẽ không bao giờ nhìn thấy nó, bởi vì nó là hidden argument, và những gì bạn thấy là 2 toán tử này chỉ nhận một tham số mà thôi. Tuy nhiên, trong ví dụ này CDateTime chỉ định nghĩa lại 2 toán tử thuộc 2 lớp khác, nên tham số đầu tiên bắt buộc phải là istream và ostream.

Lý do tại sao chúng lại được khai báo là istream& và ostream& chứ không phải là istream và ostream, hoàn toàn giống như yêu cầu về đối tượng được trả lại từ 2 toán tử này. Một lần nữa, mình xin nhắc lại là trong C++, các đối tượng được truyền cho hàm, và trả lại từ hàm theo giá trị, chứ không phải theo tham chiếu. Đó là điều mặc định trong C++.

Có thể là bạn sẽ thắc mắc, làm thế nào để trình biên dịch có thể bảo đảm là không tồn tại cùng một lúc 2 đối tượng cùng kiểu istream và ostream. Nếu bạn xem mã nguồn của 2 lớp này, bạn sẽ thấy là Default Constructor và Copy Constructor của 2 lớp này được đặt ở phần protected, vì thế mỗi lần trình biên dịch cần phải sinh ra một bản copy của cin hoặc cout, thì đều kết thúc bằng thông báo lỗi "Cannot access protected member function..."

3. Tại sao đối tượng kiểu CDateTime khi truyên cho 2 toán tử này lại phải là tham chiếu ?

Thực ra, chỉ có yêu cầu này đối với tham số của toán tử (>>) mà thôi. Đó là bởi vì toán tử này sẽ thay đổi giá trị của date và time, cho nên nếu bạn muốn những thay đổi đó có tác dụng thì phải truyền cho (>>) bản thân đối tượng, chứ không phải là bản sao. Đối với toán tử (<<) thì không có yêu cầu đó, bởi vì toán tử này không thay đổi gì cả, nó chỉ đọc giá trị cuả các biến đó thôi. Tuy nhiên, một đối tượng được truyền theo tham chiếu sẽ có một điểm lợi, đó là tránh được quá trình copy. Bạn hãy tưởng tượng nếu như CDateTime là một lớp có rất nhiều member data, thì khi truyền theo giá trị chương trình của bạn sẽ phải làm công việc copy tất cả những dữ liệu đó từ bản gốc sang bản sao, đó là một việc làm thừa. Chính vì thế mà ở đây, đối tượng kiểu CDateTime đều dược truyền cho 2 toán tử theo tham chiếu. Và thông thường, khi bạn truyền đối tượng theo tham chiếu với mục đích duy nhất là tránh quá trình copy các member data, bạn nên dùng thêm từ khoá const. Như thế bạn vừa tránh được lỗi nếu như bạn vô tình thay đổi gì đó trong đối tượng, đồng thời người khác khi đọc mã nguồn của bạn cũng sẽ hiểu ngay ý định của bạn.

Hiển nhiên là bạn không thể dùng từ khoá const đối với toán tử (>>) rồi, bởi vì khi đó thì toán tử này sẽ không thể thay đổi giá trị của Date và Time được nữa.

Một ngày bình yên


Hôm nay thật tuyệt. Mọi thứ cứ diễn ra trước mắt mình. Đầu tiên là thức dậy. Dậy sớm cũng khá mệt. Hôm qua thức khuya quá, đến 1 giờ sáng lận. Mình thức chỉ vì không ngủ được. Nằm trên giường mà đầu óc cứ nghĩ đâu đâu. Thế là mình dậy khá trễ. 8giờ sang mình dậy, người uể ỏai nghĩ trong bụng rằng không muốn đi đâu hết. Nhưng khi làm bài tóan cho tương lai, mình quyết định phải thức dậy và ra đi.
Hôm nay mình dự buổi interview vòng 3 của AIESEC. Trong người đang bệnh, ho nhiều, nhưng không lẽ lại bỏ giữa chừng. Thế là 8h40 mình lấy xe đạp lên đường. Đã 2 lần đi đến điểm giao lưu, phòng trà Drink & Talk, lần này mình rút ra nhiều kinh nghiệm nên hành trình được ngắn bớt. Chỉ mất gần 30’, mình đã có mặt tại điểm hẹn. Nhìn vào góc nhỏ nơi tụ họp của những người interview, mình nhận ra rằng hôm nay ít hơn hẵn. Thật sự rất ít. Chỉ có 2-3 bạn đang ngời chờ đợi đến lượt mình. Thế là mình tiến vào, khai báo tên và chọn một góc ngồi chờ đợi.

Mình chọn một bàn kế bên bàn của nhóm AIESEC. Bàn mình ngồi có 1 bạn nữ khá dễ thương. Mình cũng thấy ngại. Đã không ngồi bàn của nhóm AIESEC vì tòan các bạn nữ, nay lại vô tình ngồi đối diện với một bạn nữ khác. Ngồi lâu cũng thấy kỳ, thế là mình bắt đầu mở lời chào với bạn nữ cùng bàn. Mọi chuyện bắt đầu không suôn sẻ là mấy. Tất cả chỉ là lối trò chuyện xã giao, lấy lệ. Và mình thật sự không thích điều đó. Nếu được chọn lựa, mình sẽ không nói gì và ngồi chờ đợi. Nhưng có lẽ mọi chuyện không dừng ở đó. Bạn nữ bắt chuyện và mình trả lời. Tất cả cứ tiếp diễn theo chiều hướng tích cực hơn, gần gũi hơn. Dần già mình biết được bạn ấy là sinh viên năm nhất học viện hàng không, hôm nay tới Drink & Talk để cho biết cái quán này như thế nào . Rồi mình giới thiệu cho bạn về AIESEC. Rủ bạn ấy sang bàn của AIESEC để cùng trò chuyện cho vui. Mọi chuyện cứ theo cái cách của nó mà tiếp diễn. Nhưng đã lố thời gian phỏng vấn dự kiến của mình. Bây giờ đã là 10h, mình cứ ngồi đó, lắng nghe và suy tư. Nhiều người nghĩ mình là ít nói. Cái này phải coi lại. Mình ít nói với người khác chứ mình nói với chính bản thân rất nhiều – mình thích dùng cụm từ “độc thọai nội tâm” để miêu tả nó.




http://files.myopera.com/lobachevsky/OOP_FU/ass2.rara

Open day !!!

Lâu quá mình mới ghé vô Opera. Bây giờ mình mới thật sự thấy nó có ích. Từ khi dự cuộc phỏng vấn bên MSP, mình rút ra được nhiều điều hay, rất hay, rất có ích cho mình. Ra ngòai nhiều mới biết mình thiếu hụt nhiều thứ quá. Cái mình thiếu nhất chính là tri thức. Ai cũng có trình độ hơn mình. Và chính người phỏng vấn MSP đã chỉ cho mình thấy nhược điểm to lớn đó.
Nếu giả dụ mình cứ học bình thường, học cũng khá trong lớp, thì mình cũng là một học sinh, sinh viên khá. Nhưng đó chỉ là xét trong môi trường nhỏ bé của học xá. Khi ra ngòai, muốn trở thành một người nổi bật giữa bao người, thì mình cần có cái riêng. Và đó là điều mình đang cần, đang làm và phải đạt được.

Nghĩ về điều này cũng có khá nhiều thú vị. Chẳng hạn, khi mình học về pointer trong C++, mình phát hiện chính bản thân mình mắc phải một sự nhầm lẫn tai hại. Chính xác hơn là mình bị nhầm lẫn về khả năng của một dynamic memory. Khi tự học C++, đọc tới phần dynamic memory là mình lung túng nhất (trước khi học C++ trong trường). Mình thật sự không hiểu những điều sau đây:

-Tại sao người ta cần cấp phát một dynamic memory làm gì khi đã có static memory.
-Làm sao các phần tử của “mảng động” lại có thể lien kết với nhau nếu nó cấp một bộ nhớ ngẫu nhiên.
-Khi cấp một vùng nhớ động, ta có thể dung một biến để khởi tạo. Vậy ý nghĩa nó là gì.
-Và cuối củng là: Tại sao gọi nó là “động”.

Thật sự khi tự học đến phần này, mình đã tự tìm đủ mọi lý do để giải thích cho những câu hỏi trên. Những câu hỏi đó nếu được giảng dạy hàn lâm thì có lẽ điều đó không khó. Bất kỳ một bạn học lập trình nào cung có thể trả lời nhưng câu hỏi đó. Tuy nhiên, cái khác biệt chính là cái mình hiểu nó như thế nào.

Khi chưa được dạy C++, mình đã cố trả lời những câu hỏi ấy như sau (lúc này mình chẵng biết heap là gì):

-Người ta cấp phát bộ nhớ động để dễ dàng thao tác và xử lý với mảng. Mảng tĩnh cũng tốt nhưng có lẽ nó hơi cứng nhắc (vì nó là một khối bộ nhớ liền mạch đã được khai báo trước).

-Mình có đọc sơ qua về giáo trình Cơ sở dữ liệu bên Bách Khoa, thấy rằng một danh sách động được tổ chức bằng cách ghi nhớ địa chỉ của ô nhớ kế tiếp. Do đó mình nghĩ mảng động chắc cũng vậy. Mỗi phần tử của mảng cũng sẽ có 2 ô nhớ : 1 phần chứa dữ liệu, phần còn lại chứ address của ô nhớ kế.

- Cái này là một tai nạn trong nhận thức của mình. Cũng từ cuốn giáo trình Cơ sở dữ liệu, mình thấy rằng việc them hay bớt 1 thành phần (hay phần tử trong danh sách là rất dễ dàng). Vậy khi khai báo một mảng động, ta có thể dùng 1 biến để khởi tạo. Vậy nếu ta cho biến ấy tăng thì như một danh sách, mảng cũng tương tự tăng số lượng phần tử.(và ngược lại).

-Vậy tại sao nó là động. Nó động vì nó linh họat như một danh sách liên kết. Nó có thể cấp phát bất cứ đâu trong bộ nhớ và việc truy xuất trên nó thật dễ dàng.

Có lẽ nếu ai đã học lập trình thì đọc đến đây sẽ cừơi phá lên: “Ha ha sao thằng này ngu quá, có chút xíu vậy cũng không hiểu”. Ừ, mình thừa nhận là những điều trên đây không đúng hòan tòan. Nhưng đó là cái mình đã nghĩ, đã nhận xét dù lúc đó mình chẳng có chút ý niệm gì về bộ nhớ máy tính.

Chính cái ý niệm đó là một trở ngại của mình. Khi tham dự cuộc vui ACM trong trường (lúc này mình cũng chưa được dạy về C), mình đã dùng bộ nhớ động. Một số bài trong đề thi thật sự không khó, nếu không muốn nói là rất dễ. Ấy vậy mà lần nào nộp bài, hệ thống cũng báo là bài mình bị sai. Tức thật, tại sao mình test thì chạy ok mà khi nộp hệ thống lại báo sai. Tức lắm chứ. Mình nghĩ mình cũng không thể thiểu năng trí tuệ đến nỗi bài toán tìm kiếm đơn giản cũng không làm được. Tại sao mình test bằng tay thì chạy ngon lành mà lên đó thì bị break. Bộ hệ thống nó chơi mình hả.

Mưa Hồng - Khánh Ly











December 2009
M T W T F S S
November 2009January 2010
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31