31/1/15

Một số bài tập cơ bản về ma trận, mảng hai chiều

Dưới đây là một số bài tập về ma trận dành cho các bạn học Nhập môn lập trình tham khảo.
Các ví dụ mình chỉ thao tác với ma trận nguyên bằng ngôn ngữ C, với ma trận thực cũng tương tự

1. Viết hàm nhập một ma trận
//Cách 1: Nhập m, n trong hàm
void InputMatrix(int a[][20], int &m, int &n)
{
   printf("Nhập số hàng m: ");
   scanf("%d", &m);
   printf("Nhập số cột n: ");
   scanf("%d", &n);
   for(int i = 0; i < m; i++)
      for(int j = 0; j < n; j++)
      {
         printf("A[%d][%d] = ", i, j);
         scanf("%d", &a[i][j]);
      }
}

//Cách 2: Nhập m, n ngoài hàm
void InputMatrix(int a[][20], int m, int n)
{
   for(int i = 0; i < m; i++)
      for(int j = 0; j < n; j++)
      {
         printf("A[%d][%d] = ", i, j);
         scanf("%d", &a[i][j]);
      }
}

2. Viết hàm xuất một ma trận
void OutputMatrix(int a[][20], int m, int n)
{
   for(int i = 0; i < m; i++)
   {
      for(int j = 0; j < n; j++)
         printf("%d\t", a[i][j]);
      printf("\n");
   }
}

3. Viết hàm tìm giá trị lớn nhất trong ma trận
int MaxOfMatrix(int a[][20], int m, int n)
{
   int max = a[0][0];
   for(int i = 0; i < m; i++)
      for(int j = 0; j < n; j++)
         if(a[i][j]>max)
            max = a[i][j];
   return max;
}

27/1/15

Cấp phát động cho mảng hai chiều trong C++

Mảng 2 chiều khá quen thuộc với chúng ta. Mình sẽ giới thiệu một vài cách cấp phát động mảng 2 chiều để các bạn lựa chọn cho phù hợp. Ở đây mình minh họa bằng C++, đối với các ngôn ngữ khác thì ý tưởng cũng tương tự vậy thôi. Lưu ý là C++ sẽ không tự động thu hồi tài nguyên động đã cấp phát cho dù có thoát khỏi chương trình, vì thế bắt buộc phải có thao tác giải phóng mảng 2 chiều.

Cách 1: Dùng con trỏ cấp 2
Ý tưởng: Để cấp phát động cho mảng 2 chiều, ta cấp phát bộ nhớ của từng chiều theo cú pháp của mảng một chiều. Tức là tạo m mảng 1 chiều, mỗi mảng có n phần tử.

Để làm điều này ta dùng 1 con trỏ cấp 2, cấp phát cho nó m con trỏ cấp 1, mỗi con trỏ cấp 1 ta lại cấp phát n phần tử.

Ví dụ:
int **a = new int*[m];
for(int i = 0; i<m; i++)
   a[i] = new int[n];

Với ví dụ trên, ta được một mảng động hai chiều các số nguyên có kích thước m x n.
Lưu ý là ta dùng một con trỏ cấp 2 cấp phát cho một mảng các phần tử có kiểu int* chứ không phải kiểu int thông thường. Kiểu int* chính là con trỏ cấp 1.

Để giải phóng bộ nhớ động, ta cũng phải giải phóng theo từng cột và từng hàng.

Ví dụ:
for(int i = 0; i<m; i++)
   delete []a[i];
delete []a;
Cách này phức tạp nhưng bạn sẽ có 1 mảng 2 chiều đúng nghĩa và có thể lấy phần tử bằng cách gọi a[i][j] thông thường như mảng tĩnh.

Cách 2: Dùng mảng 1 chiều để biểu diễn mảng 2 chiều
Ý tưởng: Cấp phát mảng 1 chiều có kích thước m x n và truy cập nó như một mảng 2 chiều với các chỉ số thông qua công thức liên hệ.

Phần tử a[i][j] tương ứng với phần tử a[i*n + j] trong mảng.
Ví dụ:
int *a = new int[m*n]; //cấp phát xong
//khởi tạo bằng 0
for(int i = 0; i < m; i++)
   for(int j = 0; j < n; j++)
      a[i*n+j] = 0; 
Việc giải phóng vô cùng đơn giản, chỉ cần 1 lệnh delete.
delete []a;

Với cách này bạn sẽ phải truy cập mảng 2 chiều thông qua công thức liên hệ, tuy nhiên, cách này sẽ hữu ích với những trường hợp như cộng 2 ma trận cùng loại, v.v...

23/1/15

Từ vựng về Windows trong tiếng Nhật

Để đọc được các từ vựng, các bạn phải nắm vững bảng chữ Hiragana và Katakana. Các từ bằng Kanji mình sẽ phiên âm ra Hiragana.

Tiếng NhậtHiraganaTiếng Anh/Nghĩa
デスクトップDesktop
コントロールパネルControl Panel
スタートStart
フォルダーFolder
ファイルFile
ごみ箱ごみばこRecycle Bin
タスクバーTaskbar
最近表示した場所さいきんひょうじしたばしょRecent Places
スリープSleep
シャットダウンShutdown
リスタート/再起動さいきどうRestart
設定せっていSettings

Tên một số ứng dụng:

20/1/15

Nhập xuất cơ bản trong C và C++

C và C++ có sự khác nhau trong nhập xuất dữ liệu lên màn hình. Trong khi C cung cấp hàm printf()scanf() dùng xuất và nhập có định dạng thì C++ cung cấp các luồng nhập, xuất là cin, cout.

Để sử dụng được printf()scanf() trong C, bạn phải khai báo thư viện stdio.h. Hai hàm này có thể in và đọc dữ liệu nhập từ màn hình theo các định dạng khác nhau được điều khiển bởi người dùng nên được gọi là các hàm nhập xuất có định dạng.

Hàm printf
Cú pháp: printf("chuỗi điều khiển", danh sách tham số);
Hàm printf() được dùng để hiển thị dữ liệu trên thiết bị xuất chuẩn - console. Danh sách tham số có thể là hằng, biến, biểu thức hay lời gọi hàm và được phân cách bởi dấu phẩy. Mỗi tham số cần có một mã định dạng tương ứng kiểu dữ liệu trong chuỗi điều khiển. Mã định dạng này còn gọi là đặc tả. Một đặc tả gồm dấu % và theo sau là các ký tự c, d, f, lf, ... tương ứng kiểu dữ liệu của tham số.

Ngoài ra trong chuỗi điều khiển còn có thể chứa các lệnh điều khiển theo sau dấu \ hoặc %. Ví dụ: \n để xuống dòng, \\ để in ký tự \, \t để in tab, %% để in dấu %, ...

Ví dụ:
int a = 1, b = 2;
printf("Kết quả: %d\n", a+b);
printf("Cách ");
printf("khác:\n");
printf("%d + %d = %d\n", a, b, a+b);

Kết quả:
Kết quả: 3
Cách khác: 
1 + 2 = 3

Từ vựng về Tin học tiếng Nhật

Để đọc được các từ vựng này các bạn phải nắm thật vững bảng chữ Hiragana và Katakana (yêu cầu tối thiểu khi học tiếng Nhật). Đa số các từ vựng về Tin học được mượn từ nước ngoài nên được viết bằng Katakana. Tuy vậy một số từ được viết bằng Kanji và mình sẽ phiên âm ra Hiragana.

Tiếng NhậtHiraganaTiếng Anh/Nghĩa
パソコンPersonal Computer/Máy tính cá nhân
コンピューターComputer/Máy tính
タブレットTablet/Máy tính bảng
マウスMouse/Chuột
キーボードKeyboard/Bàn phím
ラップトップLaptop
ソフトウェアSoftware/Phần mềm
ハードウェアHardware/Phần cứng
デバイスDevice/Thiết bị
ゲームGame
サウンドSound/Âm thanh
システムSystem/Hệ thống
オペレーティング・システムOperating system/Hệ điều hành
バッテリBattery/Pin
モニター画面がめんMonitor screen/Màn hình
センサーSensor/Cảm biến
スキャンScan/Máy quét
カメラCamera

Cấp phát động trong C/C++

Bộ nhớ động có lợi hơn bộ nhớ tĩnh rất nhiều, có thể cấp phát thêm hoặc thu hồi lại bộ nhớ. Do đó, bộ nhớ động rất linh hoạt và tiết kiệm hơn so với sử dụng bộ nhớ tĩnh. Một mảng động chứa các phần tử được cấp phát bộ nhớ động, do đó có thể thêm phần tử, xoá phần tử,... nên quản lý bộ nhớ hiệu quả hơn.

Ngôn ngữ C cung cấp cho chúng ta 4 hàm: malloc, calloc , realloc để cấp phát và free để thu hồi. C++ cung cấp 2 toán tử: new để cấp phát và delete để thu hồi. Do C/C++ không có chế độ thu hồi tự động nên khi ta cấp phát động thì ta phải có thu hồi bộ nhớ động.

Trong C, bốn hàm malloc, calloc, reallocfree nằm trong thư viện stdlib.h hoặc alloc.h, trước khi sử dụng các bạn phải khai báo thư viện này.

Hàm malloc
Cú pháp: void* malloc(size_t size);
Ý nghĩa: Cấp phát vùng nhớ động có kích thức size byte.

Để đảm bảo cấp phát đủ bộ nhớ cho một mảng, ta thường sử dụng malloc(n*sizeof(data_type)) với n là số phần tử. Toán tử sizeof(kiểu_dữ_liệu) trả về kích thước của kiểu dữ liệu (do kích cỡ một kiểu dữ liệu không cố định ở những kiến trúc máy tính khác nhau).
Với một mảng có kiểu dữ liệu xác định nên ta phải ép kiểu để phù hợp với kiểu dữ liệu của mảng.
Hàm malloc chỉ cấp phát mà không khởi tạo giá trị ban đầu cho các biến.

Ví dụ:
Code C:
//cấp phát mảng động kiểu int với 5 phần tử
int *p = (int*)malloc(5*sizeof(int));

//cấp phát chuỗi động có 11 phần tử
char *str = (char*)malloc(11*sizeof(char));

17/1/15

Cách khởi tạo số ngẫu nhiên trong C/C++

Khởi tạo số ngẫu nhiên thường được dùng để giảm bớt công đoạn nhập số cho mảng một chiều, ma trận,... Để khởi tạo số ngẫu nhiên ta cần biết đến hàm srand()rand() trong stdlib.h. Trong C++ 2 hàm này có sẵn trong iostream.

Hàm srand
Cú pháp: void srand (unsigned int seed);
Dùng để khởi tạo một số ngẫu nhiên theo một số seed. Số ngẫu nhiên được tạo là pseudo-random, tức là số ngẫu nhiên giả, có thể đoán được số kế tiếp. Mỗi một số seed sẽ cho ra một bộ số random khác nhau.
Để cho mỗi số seed khác nhau người ta thường dùng kèm với unsigned int time(NULL) trong thư viện time.h, hàm time(NULL) trả về số giây đã trôi qua kể từ ngày 1/1/1970.
Hàm srand() thường được gọi trước khi gọi hàm rand().

Hàm rand
Cú pháp: int rand(void);
Trả về một số nguyên random giả trong khoảng từ 0 đến RAND_MAX. Hằng RAND_MAX được định nghĩa trong stdlib.h đảm bảo ít nhất bằng 32767.
Nếu chỉ dùng hàm rand() thì sẽ cho ra những số random giống nhau mỗi lần chạy, vì vậy người ta thường khai báo srand(time(NULL)) trước để kết quả random mỗi lần mỗi khác nhau.

16/1/15

Một số bài tập cơ bản về mảng một chiều

Hầu hết những bài tập dưới đây là rất cơ bản dành cho các bạn mới học Nhập môn lập trình tham khảo.

1. Viết hàm nhập mảng một chiều các số nguyên
Phải luôn luôn định trước số phần tử cần dùng cho mảng. Trong C/C++, mảng được đánh chỉ số từ 0.
Nếu là mảng các số thực chỉ việc thay int a[] thành float a[] và đổi mã đặc tả của hàm scanf trong vòng lặp thành %f.
Code C:
//Cách 1: Nhập n trong hàm nhập mảng
void InputArray1(int a[], int &n)
{
   printf("Nhập số phần tử: ");
   scanf("%d", &n);
   for(int i = 0; i < n; i++);
   {
      printf("A[%d] = ", i);
      scanf("%d", &a[i]);
   }
}

//Cách 2: Nhập n ngoài hàm nhập mảng
void InputArray2(int a[], int n)
{
   for(int i = 0; i < n; i++)
   {
      printf("A[%d] = ", i);
      scanf("%d", &a[i]);
   }
}

2. Viết hàm xuất mảng một chiều các số nguyên
Code C:
void OutputArray(int a[], int n)
{
   for(int i = 0; i < n; i++)
      printf("%d\t", a[i]);
}

12/1/15

Các vấn đề cơ bản về số nguyên tố trong lập trình

Số nguyên tố là số chỉ có 2 ước, đó là 1 và chính nó, tức là nó chỉ chia hết cho số 1 và chính nó. Số 1 và 0 không được coi là số nguyên tố. Các bài toán cơ bản về số nguyên tố gồm kiểm tra một số nguyên n có phải là số nguyên tố và tìm các số nguyên tố nhỏ hơn hoặc bằng một số nguyên cho trước.

Kiểm tra một số nguyên có là số nguyên tố
Ý tưởng: Kiểm tra xem số n có chia hết cho từng số nhỏ hơn nó hay không. Nếu có thì không là số nguyên tố, nếu tất cả đều không có thì là số nguyên tố.

Cài đặt bằng C: Nếu số n là 1 hoặc 0 thì không là số nguyên tố. Dùng một vòng for chạy từ 2 đến n-1 để kiểm tra xem n có chia hết cho bất kỳ số nào trong đó không, nếu có thỉ không là số nguyên tố, nếu tất cả đều không thì là số nguyên tố. Trong một hàm nếu gặp lệnh return, hàm sẽ trả về giá trị và kết thúc hàm nên có thể viết gọn như sau:

int IsPrime(int n)
{
   if (n < 2) return 0;
   for(int i = 2; i < n; i++)
      if(n%i==0) return 0; 
   return 1; 
}

Tuy nhiên có thể nhận thấy việc kiểm tra đến n-1 là không cần thiết. Vì nếu n có các ước thì các ước của nó chắc chắn không vượt qua căn bậc 2 của n. Như vậy điều kiện trong vòng for sẽ được đổi thành i <= sqrt(n), nhưng để gọi hàm sqrt() cần phải khai báo thư viện math.h, ép kiểu n sang kiểu thực,... khá rườm rà nên ta có thể đổi thành i*i <= n để tiện hơn.

10/1/15

Các hàm xử lý chuỗi trong C

C cung cấp rất nhiều hàm xử lý chuỗi và tất cả đều nằm trong thư viện string.h nên trước khi dùng cần phải khai báo bằng từ khoá #include.
Các hàm thường được dùng phổ biến:

strlen
Cú pháp: unsigned int strlen(const char *str);
Chức năng: Trả về độ dài của chuỗi. Độ dài chuỗi được xác định bởi ký tự null nên không bị nhầm lẫn với chiều dài mảng ký tự.
Ví dụ: char str[100]="abcd";
Hàm strlen(str) sẽ trả về 4, trong khi toán tử sizeof(str) trả về 100.

Code C:
//Ví dụ về hàm strlen
#include<stdio.h>
#include<string.h>

void main()
{
   char str[100];
   printf("Nhập chuỗi: ");
   gets(str);
   printf("Độ dài chuỗi: %d", strlen(str));
}

strcpy
Cú pháp: char* strcpy(char *destination, const char *source);
Chức năng: Sao chép chuỗi source vào chuỗi destination và trả về chuỗi destination. Lưu ý chuỗi destination phải có kích thước bằng hoặc lớn hơn chuỗi source và chưa có giá trị nào.