[C/C++] Kiểm tra chuỗi nhập bằng scanf có là số?

Thực sự khi viết bài này mình đắn đo không biết nên viết tiêu đề của nó ra sao… “Kiểm tra số khi nhập vào có là số” @@ Hơi buồn cười vì đã gọi là số rồi thì kiểm tra làm gì, hay là “Kiểm tra số trong C” – cũng không chuẩn lắm với mục đích của bài này. Và cuối cùng thì quyết định đặt như trên với mục đích là khi nhập vào bằng scanf thì sẽ biết ngay đó có phải là số hay không.

Chương trình dưới đây sẽ thực hiện việc yêu cầu bạn nhập vào một số nguyên (int), nếu bạn nhập không đúng là số (dù là bất cứ chuỗi nào dạng “12dabc”, “abc123”, thậm chí là số thực 12.3) thì đều bắt bạn nhập lại.

check number in C

#include <stdio.h>
#include <stdlib.h>

int clean_stdin() {
	while (getchar() != 'n') {
	}
	return 1;
}

int main(void) {
	int input;
	char c;
	do {
		printf("Enter an integer: ");
	} while (((scanf("%d%c", &input, &c) != 2 || c != 'n') && clean_stdin()));

	printf("done, number is %d", input);
	return 0;
}

Mình giải thích một chút:

scanf(“%d%c”, &input, &c)
Lệnh này sẽ cho phép chúng ta nhập vào một số nguyên và một ký tự nào đó ngay sau số nguyên này và nó sẽ trả về giá trị là một số nguyên – số lượng biến mà nó nhận (quét) được theo đúng định dạng trong chuỗi định dạng.
– Nếu bạn nhập vào abc thì hàm này sẽ trả về giá trị là 0 vì nó không thể đọc được một giá trị phù hợp nào.
– Nếu bạn nhập vào 123 và nhấn Enter thì giá trị trả về là 2 đó là 2 giá trị được chấp nhận theo định dạng, 123 cho %d và Enter cho %c.
– Nếu bạn nhập vào 123abc và nhấn Enter thì giá trị trả về là 2 đó là 2 giá trị được chấp nhận theo định dạng, 123 cho %d và ký tự a cho %c.

scanf(“%d%c”, &input, &c) != 2 || c != ‘n’
Nó đảm bảo rằng số lượng dữ liệu mà scanf quét được không phải là 2 hoặc ký tự nhận được không phải là enter. Đặt điều kiện này trong while để máy có thể thực hiện đúng là nếu bạn nhập không phải số và ngay sau đó enter thì sẽ lặp lại.

(scanf(“%d%c”, &input, &c) != 2 || c != ‘n’) && clean_stdin()
Hàm clean_stdin() là hàm luôn trả về giá trị 1 (tức là luôn đúng) nó thự hiện việc xóa bộ đệm (stdin) bằng cách đọc hết toàn bộ ký tự sót lại trong bộ đệm (những ký tự mà scanf không thể đọc được với định dạng nhập của nó) cho đến khi đọc đến ký tự enter. Việc đưa nó vào trong điều kiện vòng lặp while nhằm quét sạch bộ đệm mỗi khi bạn nhập sai để phục vụ cho lần nhập lại tiếp theo.

Bài viết có tham khảo các bình luận tại stackoverflow.com