Vui vui với C

Lưu Điền Trang
(ZER0)

Điều hành viên
Các bạn có thể cho biết sự khác biệt giữa các câu lệnh if sau trong ngôn ngữ lập trình C (hoặc C++)?

1.
if (a != 0 && b >= 5)

if (a && b >= 5)

2.
if (a != 0 && b >= 5)

if (a != 0 & b >= 5)

3.
if (a && b >= 5)

if (a & b >= 5)


Cheer,
ĐTrang

PS: Đã có lời giải, nhưng bạn hãy cứ thử suy nghĩ xem. :)
 
Chỉnh sửa lần cuối:
thêm tí cho vui. Đố mọi ngưòi biết chương trình sau làm gì :D

#include <stdio.h>
#include <math.h>
double l;main(_,o,O){return putchar((_--+22&&_+44&&main(_,-43,_),_&&o)?(main(-43,++o,O),((l=(o+21)/sqrt(3-O*22-O*O),l*l<4&&(fabs(((time(0)-607728)%2551443)/405859.-4.7+acos(l/2))<1.57))[" #"])):10);}
 
khó quá, mời Trang và anh Điềm giải thích

khó quá, khó quá, mong hai người giải thích để sau này không phạm những sai lầm khi viết chương trình :)
XS
 
Bài của anh Trang dễ thôi.
Em chưa thử nhưng căn cứ vào precedence of operator là có được câu trả lời.
Thứ tự như sau: (giảm dần tu tren -> duoi, tu trai -> phai)
< <= > >= == !=
&
&&
Thành ra:
1a quá dễ
1b a sẽ nhận giá trị so sánh là 0 hoặc 1 (nói nôm na) va thực hiện phép toán logic với giá trị trả về của b >=5 (cũng là 0 hoặc 1)

Bài 2 cũng vậy, do phép bitwise And và phép and logic đều đứng sau comparison operator nên thực hiện thứ tự giống nhau. Nhưng cái hay là lần này phep bitwise AND (&) coi như thực hiện giữa hai số 0 và 1 nên kết quả cũng giống && nốt.

Bài 3 nhìn hơi lạ, nhưng cũng dzậy à.


Hic hic, còn đoạn code của chị Điềm nữa.
Em đã thử bằng Borland C++ 5 for Windows rồi, nhưng nó báo lỗi tùm lum. Thật ra nhìn kĩ thì các lỗi chỉ xoay quanh cái dòng main của anh. Có vẻ như anh ko gõ bừa đâu, anh thử xem lại nhá.
 
hihi, còn nhiều cái hay ho để đố lém, chỉ về C thôi.
Có những cái mà phải hiểu sâu bên trong máy tính mới giải thích được.
Để mai em lên thư viện tìm về cho các anh chị coi. (trong trường hợp quyển sách ấy chưa bị mượn)
 
Câu 2 và 3 có một sự khác biệt quan trọng mà em Quân chưa trả lời được. Anh không hỏi là câu lệnh if này làm gì mà chỉ hỏi sự khác nhau của chúng thôi.

Cheer,
ĐTrang
 
Trong bitwise operators thì operands bắt buộc phải là integral. Chú gì về học lại căn bản đi.
 
Phép toán logic của C (C++) trả về 1 cho True và 0 cho False là giá trị integer thành ra dùng phép toán bitwise cho giá trị logic ở đây vẫn được.
Còn với C# thì phải cast boolean sang integer thì mới được.
 
Chỉnh sửa lần cuối:
:razz:

Câu 2 thì có logical operator ở cả 2 vế nên returns là 0 hoặc 1, nhưng câu 3 chỉ có b >= 5 còn a đâu có xác định nhỉ?
 
Chỉnh sửa lần cuối:
Almost there!! ;)

Cứ giả thiết là a và b là 2 số integer.
 
Chỉnh sửa lần cuối:
ok :D
Đơn giản bitwise là arithmetic chứ không phải logical, nên returns của nó không giống của logical.

Ví dụ:
Phép toán bool (b>=5) returns 1.
a = 1; a & b>=5 returns 1
a = 100; a & b>=5 returns 0

Trong khi với a#0, a && b>=5 luôn luôn trả lại 1.
 
Chỉnh sửa lần cuối:
Tran Trung Quan đã viết:
...


Hic hic, còn đoạn code của chị Điềm nữa.
Em đã thử bằng Borland C++ 5 for Windows rồi, nhưng nó báo lỗi tùm lum. Thật ra nhìn kĩ thì các lỗi chỉ xoay quanh cái dòng main của anh. Có vẻ như anh ko gõ bừa đâu, anh thử xem lại nhá.

Phê bình chú dám gọi anh là chị. [-x

Đoạn code đó dùng ANSI C, compile bằng mấy cái Borland C++ hay VC++ etc không được đâu (hoặc là phải setup mây cái flag nào đó). Dùng gcc thêm -ansi dảm bảo chạy ngon lành.

Cái đó cũng không phải của anh, thấy vui vui nên post cho mọi nguời thấy cấu trúc lỏng lẻo của C cho phép viết đuợc đủ thứ rắm rối. :mrgreen:
 
À tiện thể hỏi mọi nguời: class trong C++ có default constructor không? Nghĩa là khi viết một class có phải viết cho nó ít nhất một constructor không?
 
C++ có default constructor. Còn gọi là synthesized constructor. Có điều khi đó mình chỉ có thể define objects mà không initialize explicitly được. Synthesized constructor sẽ take care of this part, tùy thuộc vào context requires default-initializing hay value-initializing.
- Nếu data member là built-in type, sẽ được value-initalizing sets về 0, sau đó default-initialzing một undefined value.
- Nếu data member là object của class (có constructor(s)), việc initialize sẽ phụ thuộc vào constructor(s) của class đó.
- Trường hợp cuối, data member là object của một class không có constructor, khi đó việc initialize, value hay default, sẽ phụ thuộc vào data members của class đó, và được thực hiện recursively.
 
Hoan hô đã có câu trả lời.

Về câu hỏi số 1, thực ra cả
if (a != 0 && b >= 5)if (a && b >= 5) đều giống nhau. Và cách viết rút gọn như vậy rất phổ biến trong khi lập trình C.

Câu hỏi số 2 vẫn chưa có lời giải nhưng Trang nói luôn. Về ý nghĩa logic thì hai mệnh đề if (a != 0 && b >= 5)if (a != 0 & b >= 5) đều sẽ cho kết quả giống nhau. Vì C gán giá trị logic {False, True} cho {0,1} nên phép bitwise AND sẽ cho kết quả đúng như phép logic AND. Điểm khác biệt duy nhất là ở câu if (a != 0 & b >= 5) phép so sánh thứ hai (b>=5) luôn luôn được thực hiện không cần biết a có khác 0 hay không. Trong khi câu if (a != 0 && b >= 5) chỉ thực hiện phép so sánh thứ hai khi a khác 0. Bạn có thể tận dụng điều này trong lập trình rất hữu ích. Nhưng thật cẩn thận vì bạn dễ mắc phải sai lầm trong câu 3.

Câu hỏi số 3, bạn đã hiểu được câu if (a != 0 & b >= 5) và là một lập trình viên C "xịn" bạn sẽ muốn rút gọn lại thành if (a & b >= 5) và mắc phải sai lầm mà em Châu đã miêu tả. Bạn thử lại mà xem, với a chẵn hay lẻ sẽ cho giá trị logic khác nhau nếu b thực sự lớn hơn hoặc bằng 5. Nếu b nhỏ hơn 5 thì bạn đã may mắn vì mệnh đề vẫn cho giá trị đúng.

Hẹn gặp lại tuần sau với một câu hỏi nữa. :)
Cheer,
ĐTrang
 
Chỉnh sửa lần cuối:
Mấy câu đố này hay lắm :). Rất là thú vị.

Tuy nhiên ngoài lề một chút thì mình nghĩ khi lập trình nên tránh tối đa chuyện viết tắt, vì sẽ làm cho chương trình khó hiểu. Còn các thủ thuật như trong câu 2 thì (a!=0 && b >= 5) vừa dễ hiểu, vừa có thể tiết kiệm được CPU time một chút nên ko nói làm gì. Tuy nhiên có nhiều thủ thuật khác tiết kiệm được một tí CPU thôi mà làm cho chương trình trở nên rối rắm ko cần thiết, những đoạn code đó là extremly error prone, khi dùng mọi người nên hạn chế, chỉ sử dụng thật cẩn thận khi thật sự cần thiết.
 
Cảm ơn anh Trang, nhưng em thấy.... cứ đúng thứ tự mà làm thì chẳng lầm lẫn vào đâu được.
Viết tắt cũng được, nhưng chốt lại là đừng có nghĩ tắt thôi.
Huhu, quyển sách bị mượn mất rôi.
 
Tran Trung Quan đã viết:
Cảm ơn anh Trang, nhưng em thấy.... cứ đúng thứ tự mà làm thì chẳng lầm lẫn vào đâu được.
Viết tắt cũng được, nhưng chốt lại là đừng có nghĩ tắt thôi.
Huhu, quyển sách bị mượn mất rôi.

Vấn đề là có phải lúc nào cũng có thể làm đúng thứ tự ko :). Thường rất hay gặp là mình viết code còn chưa xong thì yêu cầu bài toán đã phải thay đổi một tí rồi. Thế là phải đè ra viết lại. Việt lại thì phải đọc lại để hiểu, mà viết tắt quá thì đọc khó lắm :). Chưa kể là nếu mình viết xong rồi người khác phải sửa thì còn đau đầu hơn gấp tỉ lần. Vả lại mấy kiểu tiết kiệm như thế thường khiến cho sửa chỗ này thì lại gây hỏng cho chỗ khác nữa.
 
Nhan co may cao thu C++ o day cho minh hoi mot phat:

Minh lap trinh tinh toan rat hay bi loi vuot qua o nho. Thuong loi nay do minh tro den hoac ghi vao mot dia chi nam ngoai nhung dia chi duoc khai bao cua mot bang. Lam the nao de kiem tra & tim ra cai loi nay nhanh nhat? Thuong thi minh phai insert cac lenh cout << "message" << endl; vao giua cac vong lap de biet xem no bi vuot qua o nho o vong lap nao. Nhung cach nay kha mat thoi gian. Mot nguoi ban chi cho cach dung chuong trinh Valgrind nhung minh chua biet dung.

Moi moi nguoi nhao dzo!
 
Hi Phương,

Nếu chương trình dùng mảng tĩnh và không có code để detect lỗi tràn bộ nhớ thì trước sau gì cũng dính chưởng. Vậy nên phòng bệnh hơn là chữa bệnh.

Nếu chương trình tính toán cần nhiều bộ nhớ thì có thể dùng bộ nhớ động. Mỗi khi cần thì allocate thêm một chút. Nhưng nếu allocate theo kiểu addition (trong từng vòng lặp) thì sẽ bị O(n). Một cách khéo léo hơn là nhân đôi số bộ nhớ mỗi khi cần để có O(ln(n)). Chỉ cần vài lần nhân đôi là bác đã có đủ bộ nhớ để tính toán rồi.

Nếu không muốn rắc rối thì ngay từ đầu viết một class Mảng Động rồi cứ thế dùng cho các chương trình về sau này.

Hehe, good luck.

ĐTrang
 
Back
Bên trên