Thi Kỹ Thuật Lập Trình

Standard

http://vuducvuong-soict-hut.blogspot.com/

(code của thầy không được đẹp lắm – có lẽ vì để vừa vặn khổ A4, xin phép được giữ nguyên gốc).

Thi 90 phút, sau 30 phút vẫn chưa làm được bài nào😦 Ngay khi đọc mấy bài liên quan đến file mình đã choáng rồi, phải mượn sách thằng bạn đọc gấp. Trước giờ dùng C++ chứ có dùng C mấy đâu :-S

Câu 1 : (0.75 đ) Hãy sửa các lỗi cú pháp của đoạn mã trên rồi viết lại để cho kết quả tương đương nhưng sáng sủa và dễ hiểu hơn ( các biến đã khai báo đầy đủ)

if (argc==3)
	if ( ( fin = fopen(argv[1] , "r")) != NULL)
		if ((fout = fopen(argv[24*], "w")) != NULL) {
			while ((c = getc(fin)) != EOF)
				putc(c, fout);
			fclose(fin); fcloseCfout);
		} else
			printf ("Can't open output %s\nn, argv[2]) ;
		else
			printf( "Can't open input file %s\nn, argv[1]) ;
	else
		printf ("Usage: cp input file output file\n”) ;

Bài này mất một chút thời gian ở việc kiểm tra coi tham số gọi mấy cái fopen, putc, fclose có đúng chưa, rồi thì sửa tí code cho đẹp (đảo cái lỗi cú pháp lên đầu). Cuối giờ thì thằng bạn kêu là cái dấu ‘ ở chữ can’t là không hợp lệ, mình cũng chả nghĩ gì, xóa luôn. Theo thầy chữa thì đấy là ký tự đặc biệt, phải dùng \’, mình test trên VS chả sao cả :))

Câu 2 : (1.đ) Phân tích ví dụ sau và nếu có sai hãy chỉ ra lỗi và sửa lại sao cho đúng với mọi dữ liệu:

char  c;
...
do
{   c = getchar();
	putchar(c);
} while c != EOF ;

Nhìn ngắn vậy mà những 1 điểm nên mình có một vài băn khoăn nhất định. Mình cũng chả làm được gì mấy, ngoài đảo cái while lên trên, vì thực ra mình không hiểu đoạn code này nó làm cái gì cả, getchar() với putchar() mình đều chưa dùng bao giờ, EOF thì mình không biết nó bằng bao nhiêu.

Thầy chữa rằng bài này lỗi duy nhất là EOF = 255 còn c là kiểu signed char, nên c không bao giờ bằng EOF. Mình test trên VS thì thấy EOF = -1, và quá trình so sánh diễn ra rất bình thường. Nếu thầy kiên quyết giữ ý kiến thì mình mất hoàn toàn 1 điểm ở bài này.

Thầy đã đúng, câu này quả thực rất hay 😀

Câu 3 : (2.5 đ) Viết hàm  đệ quy    int  TongChuSoChan(int n)  để tính tổng các chữ số Chẵn của 1 số nguyên n bất kỳ, sau đó viết lại hàm dưới dạng không đệ quy

Ví dụ : n = 346751 thì kết quả là : 6 + 4 = 10.

n= -258014 thì kết quả là : 2 + 8 + 4 = 14

Bài này mình làm cuối cùng, những bài khác nhìn chung là mình mất khá nhiều thời gian. Lúc đầu nhìn thấy khử đệ quy mình nghĩ là sẽ dùng stack – tương đối phức tạp nên bỏ qua. Giờ không nhớ lúc đó mình làm thế nào (vội mà), nhưng có lẽ là đúng. Khách quan thì bài này khá cơ bản, 2.5đ là hơi nhiều.

Câu 4 : (1 đ)   Tối ưu đoạn code sau :

float a,d; int b,c;   /* nh?p giá tri b,c */
for (int i=0; i0)   {
		a=  i*10*(8*b*b  -6*b –20 +sin(c));
		d=  (24*b*b -18*b -(60- 3*sin(c))) * 30*i;
		printf(“ a=%f ,d= %f ”,a, d);
    }    else {
		d=  (6*b*b  -18*b  - (60- 3*sin(c))) *30*i;
		a=  i*10*(2*b*b  -6*b –20 +sin(c));
		printf(“ a=%f ,d= %f ”,a, d);
    }
}

Những bài kiểu này làm khá mệt, vì phải biến đổi đủ thứ. Mình nhìn thấy b*b thì nghĩ ngay đến việc chuyển về tích của 2 đa thức bậc 1, nhưng lúc tìm nghiệm thì gặp chút khó khăn🙂 Lâu không tính bằng tay nên tính delta xong thì lúc tính nghiệm mình bị nhầm dấu, cuối cùng lôi máy tính ra cho nhanh (nội quy không cho dùng máy tính). Lạ cái là cấm nhưng thấy mình dùng thầy cũng không nói gì :-S Một vài tinh chỉnh khác thì chắc ai cũng như ai, đều làm được.

Bổ sung thêm là có thể bỏ biến d để tiết kiệm được bộ nhớ!

Câu 5 : (1,0 đ)   Cho mảng matrix  gồm nrow hàng và ncol cột (nrow, ncol >=100). Đoạn code sau in các phần tử của mảng này theo hàng:

int dem = 0;
for (int r = 0; r < nrow; r++ )
	for (int c = 0; c < ncol ; c++) {
		if  (dem % ncol == 0)
			printf (“%d    \n“,  matrix[r][c]);
		else printf (“%d    “,  matrix[r][c]);
			dem++;
	}

Bài này đọc qua mình nghĩ ngay là thầy cố tình để lỗi ở việc xuống dòng, nên theo hướng bỏ biến dem và xuống dòng khi hết vòng lặp cột – mình nghĩ làm thế là đã tăng hiệu quả thêm khá nhiều rồi, vì không phải tính phần dư + so sánh. Tuy nhiên theo bài chữa của thầy thì việc xuống dòng không sai, cái cần tối ưu hóa là thay duyệt bằng mảng 2 chiều thì duyệt theo mảng 1 chiều. Có điều với suy nghĩ ban đầu của mình (rằng đoạn code có lỗi khi xuống dòng) thì nếu chuyển qua truy xuất bằng mảng 1 chiều sẽ vẫn phải tính phần dư + so sánh (tất cả là nrow * ncol phép toán) ~> so với hướng làm của mình không hơn là bao.

Nhiều khả năng mình cũng sẽ mất toàn bộ 1 điểm ở bài này, đã gửi mail cho thầy rồi nhưng không có mấy hy vọng.

Theo như email của thầy thì đúng là có chút sai sót việc xuống dòng (câu này do thầy Bá ra đề), thầy có nói thêm nếu vẫn truy cập theo mảng 2 chiều nhưng bỏ biến dem (xuống dòng sau vòng lặp cột) thì sẽ được 0.5 điểm.

Câu 6 : (2 đ) Cho một danh sách liên kết đơn với các nút được khai báo như sau :

struct node
{  int info;
 struct node *next;
};

Hãy xây dựng hàm đệ quy  sao chép danh sách đó sang 1 danh sách khác.

Bài này không có gì để bàn ngoài việc thầy không nói rõ về các tham số truyền vào hàm. Mình truyền 2 tham số (source và dest) còn thầy chỉ truyền 1 tham số (source). Lại phải chờ vào sự thông cảm của thầy thôi🙂

Câu 7: (1. đ)

Cho biết giá trị của các phần tử của mảng A sau khi thực hiện đoạn lệnh dưới đây và giải thích vì sao?

int  A[]  =  {2,  4,  6,  8};
int  b,*p  =  A;
*p++ ;
*p += 2;  b=*p-- ;
p  += 2;
*p += b;

Thắc mắc duy nhất của mình là về câu lệnh *p++. Mình biết ++ trước rồi *, nhưng mình không nghĩ là câu lệnh như thế lại hợp lệ, vì lấy giá trị nhưng không gán vào đâu cả. Cũng là do mình thiếu kinh nghiệm, về kiểm tra lại thì thấy kể cả câu lệnh a; cũng còn hợp lệ cơ mà😀 Mất khá nhiều thời gian cho bài này.

Câu 8: (0.75 đ)  Hãy tinh chỉnh đoạn mã lệnh sau bằng  các  kỹ thuật  đã học  và giải thích lý do ( các hàm trong đoạn lệnh đã tối ưu).

int x,y,z;  /* nhập x,y,z ….*/
for ( int  i = 0 ; i < n ; i++ ) {
	if ( x == y /512 )      Do1(i);
	else if ( x == 2*y*64 + z*128 )
		Do2(i);
	else      Do3(i);
}

Chỉ 0.75 điểm thôi, nên sau khi chuyển phép so sánh ra ngoài, đảo chiều vòng lặp, thay nhân bằng dịch bit thì mình nghĩ không còn gì để lưu luyến thêm.

Một vài tâm sự:

Mình có đọc trên blog của thầy về đáp án bài thi khóa trước, theo đó thầy đều đảo chiều vòng lặp, ví dụ:

câu 4 : (0.75đ) toi uu doan code sau :

float f(float *a, float *b, int n) {
	float ta, tb , sum = 0.0;
	int i = 0;
	ta = a[i]; tb = b[i];
	for (i = 1; i < n; i++) {
		sum += ta + tb;
		ta = a[i]; tb = b[i]; }
	sum += ta + tb;
	return sum;
}

Rà soát đoạn code trên, ta thấy bản chất của đoạn code là tính tổng n phần tử của 2 mảng a và b. Vì vậy chỉ cần loại bỏ các biến trung gian và tinh chỉnh như sau :

float f(float *a, float *b, int n) {
    float sum = 0.0;
    for (int i = n-1;  i>=0 ;  i--)  sum += a[i] + b[i];
    return sum;
}

Mình biết rằng so sánh bằng thì nhanh hơn so sánh lớn nhỏ, nhưng chuyển từ so sánh < sang so sánh >= thì mình chẳng thấy nó hơn chút nào cả (mình nghĩ để so sánh thì phải trừ đi rồi xét cờ, kể cả so sánh với 0 thì cũng đâu thể xét luôn giá trị thanh ghi mà suy ra được). Trong phòng thi mình cũng liều, hỏi thầy luôn về vấn đề này. Khổ nỗi thầy lại bảo rằng nó vẫn hiệu quả hơn😦 Mình chẳng biết phải làm thế nào, hiểu mà không dám làm theo cách mình hiểu (thi cử mà, quan trọng là điểm cao, chứ không phải thể hiện mình đúng) – mình quyết định có bài đảo có bài không để đảm bảo an toàn :(( . Cuối cùng đọc bài giải của thầy thì không có bài nào phải đảo chiều vòng lặp :-S Làm mình mất bao nhiêu thời gian.

Thêm nữa, trong quá trình dạy thầy không hề nói phải học C, thực tế là có lúc thầy dùng C, có lúc dùng C++, mà những lần dùng C thì đều là những cú pháp chung của cả 2 ngôn ngữ nên không vấn đề gì. Nhưng đi thi thầy lại chơi vào C làm mình khổ vô cùng =(( Thà thầy dùng giả mã còn đỡ, chứ mình toàn C++ với mấy bài tập linh tinh, đâu phải câu lệnh nào cũng biết :(( Những cái cần tinh chỉnh thầy dùng cú pháp chung của 2 ngôn ngữ là được rồi, thêm fopen(), fclose(), putc(), getchar()… làm mình chóng hết cả mặt, thời gian đã eo hẹp lại còn phải mở sách ra tra (sách cũng là mượn của thằng bạn chứ mình có biết là được mang tài liệu đâu)😐

3 thoughts on “Thi Kỹ Thuật Lập Trình

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s