Header <ctype.h> menyediakan fungsi klasifikasi dan konversi karakter. Berbeda dengan membandingkan kode ASCII manual (c >= 'A' && c <= 'Z'), fungsi isalpha, isdigit, dan kawan-kawan bekerja portabel di semua locale dan tahan terhadap karakter non-ASCII. Header ini sangat berguna saat kita memvalidasi input pengguna, mem-parse token, atau mengubah case string. Pada chapter ini kita akan meninjau fungsi klasifikasi (isalpha, isdigit, isalnum, isspace) dan fungsi konversi (toupper, tolower) beserta idiom penanganannya.
Klasifikasi Karakter: isalpha, isdigit, isalnum, isspace #
Semua fungsi klasifikasi di <ctype.h> menerima argumen bertipe int yang harus berupa unsigned char (nilai 0-255) atau konstanta EOF (-1). Memasukkan char bertanda secara langsung berbahaya: bila char bertanda dan karakter memiliki bit tertinggi 1 (misalnya karakter Latin-1 di atas 127), nilainya menjadi negatif dan dapat memicu undefined behavior—karena itu kita selalu cast ke unsigned char lebih dulu.
#include <stdio.h>
#include <ctype.h>
int main(void) {
/* isalpha, isdigit, isalnum, isspace */
const char *s = "Budi berusia 25 tahun.";
printf("Karakter di string \"%s\":\n", s);
printf("%-4s | %-7s | %-7s | %-7s | %-7s\n",
"char", "alpha", "digit", "alnum", "space");
for (size_t i = 0; s[i] != '\0'; i++) {
unsigned char c = (unsigned char)s[i];
printf("'%c' | %-7s | %-7s | %-7s | %-7s\n",
(isprint(c) ? c : '.'),
isalpha(c) ? "ya" : "tidak",
isdigit(c) ? "ya" : "tidak",
isalnum(c) ? "ya" : "tidak",
isspace(c) ? "ya" : "tidak");
}
return 0;
}Output yang Dihasilkan:
Karakter di string "Budi berusia 25 tahun.":
char | alpha | digit | alnum | space
'B' | ya | tidak | ya | tidak
'u' | ya | tidak | ya | tidak
'd' | ya | tidak | ya | tidak
'i' | ya | tidak | ya | tidak
' ' | tidak | tidak | tidak | ya
'b' | ya | tidak | ya | tidak
'e' | ya | tidak | ya | tidak
'r' | ya | tidak | ya | tidak
'u' | ya | tidak | ya | tidak
's' | ya | tidak | ya | tidak
'i' | ya | tidak | ya | tidak
'a' | ya | tidak | ya | tidak
' ' | tidak | tidak | tidak | ya
'2' | tidak | ya | ya | tidak
'5' | tidak | ya | ya | tidak
' ' | tidak | tidak | tidak | ya
't' | ya | tidak | ya | tidak
'a' | ya | tidak | ya | tidak
'h' | ya | tidak | ya | tidak
'u' | ya | tidak | ya | tidak
'n' | ya | tidak | ya | tidak
'.' | tidak | tidak | tidak | tidak Mari kita telaah baris-baris kode di atas:
- Baris 6 (
const char *s = "Budi berusia 25 tahun.";): string uji berisi campuran huruf, spasi, digit, dan tanda baca. - Baris 12 (
unsigned char c = (unsigned char)s[i];): cast wajib. Tanpa cast ini, karakter dengan bit tertinggi 1 akan menjadi nilai negatif bilacharbertanda—lalu fungsiis*dapat mengakses array di luar batas dan undefined behavior. - Baris 14-19 (
isalpha,isdigit,isalnum,isspace):isalphamengembalikan nilai non-zero bila karakter adalah huruf;isdigituntuk'0'-'9';isalnumadalah gabunganisalpha || isdigit;isspaceuntuk' ','\t','\n','\r','\f','\v'. - Baris 15 (
isprint(c) ? c : '.'): tampilkan karakter hanya bila bisa dicetak (isprint), selain itu tampilkan'.'—berguna bila string mengandung karakter kontrol.
Konversi Case: toupper dan tolower #
Fungsi toupper mengubah huruf kecil menjadi huruf besar; tolower sebaliknya. Karakter yang bukan huruf dikembalikan apa adanya. Return value bertipe int, jadi kita perlu cast ke char bila ingin disimpan di array char.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
/* Ubah string menjadi huruf besar */
static void ke_huruf_besar(char *s) {
for (size_t i = 0; s[i] != '\0'; i++) {
s[i] = (char)toupper((unsigned char)s[i]);
}
}
/* Ubah string menjadi huruf kecil */
static void ke_huruf_kecil(char *s) {
for (size_t i = 0; s[i] != '\0'; i++) {
s[i] = (char)tolower((unsigned char)s[i]);
}
}
int main(void) {
char asli[] = "Belajar Pemrograman C, 2024!";
char buf1[64], buf2[64];
strcpy(buf1, asli);
strcpy(buf2, asli);
ke_huruf_besar(buf1);
ke_huruf_kecil(buf2);
printf("Asli : %s\n", asli);
printf("Besar : %s\n", buf1);
printf("Kecil : %s\n", buf2);
/* Demonstrasikan toupper pada karakter non-huruf */
printf("\n toupper('5') = '%c' (tidak berubah)\n",
(char)toupper((unsigned char)'5'));
printf(" toupper('a') = '%c'\n",
(char)toupper((unsigned char)'a'));
return 0;
}Output yang Dihasilkan:
Asli : Belajar Pemrograman C, 2024!
Besar : BELAJAR PEMROGRAMAN C, 2024!
Kecil : belajar pemrograman c, 2024!
toupper('5') = '5' (tidak berubah)
toupper('a') = 'A'Fungsi ke_huruf_besar dan ke_huruf_kecil menelusuri string karakter per karakter dan memanggil toupper/tolower untuk setiapnya. Karakter '5' tidak berubah karena bukan huruf—konversi dilewatkan. Perhatikan bahwa asli tetap utuh karena kita menyalinnya ke buf1 dan buf2 lebih dulu dengan strcpy; kedua fungsi mengubah buffer tujuan in-place.
Studi Kasus: Menghitung Kata dalam String #
Mari kita rangkum dengan kasus nyata: menghitung jumlah kata dalam sebuah kalimat. Kita definisikan “kata” sebagai run karakter alfabet yang dipisahkan oleh karakter lain. State machine sederhana dengan flag dalam_kata cukup untuk masalah ini.
#include <stdio.h>
#include <ctype.h>
/* Hitung jumlah kata dalam sebuah string */
static int hitung_kata(const char *s) {
int jumlah = 0;
int dalam_kata = 0;
for (size_t i = 0; s[i] != '\0'; i++) {
unsigned char c = (unsigned char)s[i];
if (isalpha(c)) {
if (!dalam_kata) {
jumlah++;
dalam_kata = 1;
}
} else {
dalam_kata = 0;
}
}
return jumlah;
}
int main(void) {
const char *kalimat[] = {
"Halo dunia!",
"Saya belajar C hari ini.",
"12345 6789",
""
};
size_t n = sizeof(kalimat) / sizeof(kalimat[0]);
for (size_t i = 0; i < n; i++) {
printf("\"%s\" -> %d kata\n", kalimat[i], hitung_kata(kalimat[i]));
}
return 0;
}Output yang Dihasilkan:
"Halo dunia!" -> 2 kata
"Saya belajar C hari ini." -> 5 kata
"12345 6789" -> 0 kata
"" -> 0 kataLogika kuncinya: setiap transisi dari “tidak dalam kata” ke “dalam kata” (yaitu saat bertemu huruf setelah karakter non-huruf) menandai awal satu kata baru. Beberapa spasi berturut-turut diabaikan karena dalam_kata sudah 0 setelah spasi pertama. String "12345 6789" menghasilkan 0 karena isalpha mengembalikan false untuk digit—bila kita ingin digit dihitung sebagai kata, ganti isalpha(c) menjadi isalnum(c).