Membandingkan dua string adalah operasi yang sering diperlukan: memvalidasi password, mencari duplikat dalam daftar, atau mengurutkan array nama. Sayangnya, operator == di C tidak membandingkan isi string—ia hanya membandingkan alamat pointer. Untuk membandingkan isi, kita memakai strcmp dari header <string.h>. Fungsi ini membandingkan dua string secara leksikografis (byte demi byte) dan mengembalikan nilai negatif, nol, atau positif tergantung urutan relatifnya. Akan tetapi, nilai numerik selain nol implementation-defined: ada compiler yang mengembalikan -1/0/1, ada pula yang mengembalikan selisih byte yang sebenarnya (misalnya -32 atau 32). Pada chapter ini kita akan memahami kontrak strcmp, mendemonstrasikan sifat implementation-defined-nya, dan melihat pemakaian praktisnya dalam sorting.

Penggunaan Dasar strcmp #

strcmp(a, b) membandingkan string a dan b byte demi byte mulai dari karakter pertama. Bila ditemukan byte yang berbeda, strcmp mengembalikan nilai bertanda yang merefleksikan urutan leksikografis: negatif bila a mendahului b, positif bila a mengikuti b. Bila seluruh byte sama sampai null terminator, return value adalah 0.

c
#include <stdio.h>
#include <string.h>

int main(void) {
    /* Perbandingan string identik */
    int r1 = strcmp("apel", "apel");
    int r2 = strcmp("apel", "jeruk");
    int r3 = strcmp("jeruk", "apel");

    printf("strcmp(\"apel\", \"apel\")  = %d\n", r1);
    printf("strcmp(\"apel\", \"jeruk\") = %d\n", r2);
    printf("strcmp(\"jeruk\", \"apel\") = %d\n", r3);

    /* Pola pemakaian: hanya tandanya yang bermakna */
    if (strcmp("apel", "apel") == 0) {
        printf("Kedua string sama persis.\n");
    }
    if (strcmp("apel", "jeruk") < 0) {
        printf("\"apel\" mendahului \"jeruk\" urutan leksikografis.\n");
    }
    return 0;
}

Output yang Dihasilkan:

text
strcmp("apel", "apel")  = 0
strcmp("apel", "jeruk") = -1
strcmp("jeruk", "apel") = 1
Kedua string sama persis.
"apel" mendahului "jeruk" urutan leksikografis.

Pada output di atas, strcmp("apel", "apel") = 0 karena kedua string identik. strcmp("apel", "jeruk") = -1 (negatif) karena 'a' (ASCII 97) lebih kecil dari 'j' (ASCII 106). strcmp("jeruk", "apel") = 1 (positif) karena 'j' lebih besar dari 'a'. Yang penting untuk diingat: dalam implementasi glibc ini, return value selalu -1, 0, atau 1. Namun kontrak C standard hanya menjamin tanda—nilai numeriknya implementation-defined dan bisa berbeda di compiler atau library lain.

Implementation-Defined Return Value #

Mari kita tunjukkan secara konkret bahwa nilai return strcmp berbeda-beda tergantung implementasi. Pada glibc modern, nilai biasanya -1/0/1. Kita juga akan membandingkan dengan strncmp yang membatasi jumlah byte yang diperbandingkan.

c
#include <stdio.h>
#include <string.h>

/* Demonstrasikan return value implementation-defined */
int main(void) {
    /* Bandingkan string yang berbeda di karakter pertama */
    int r1 = strcmp("A", "B");   /* A=65, B=66 */
    int r2 = strcmp("B", "A");
    int r3 = strcmp("a", "A");   /* a=97, A=65, beda 32 */

    printf("strcmp(\"A\",\"B\") = %d  (harus negatif)\n", r1);
    printf("strcmp(\"B\",\"A\") = %d  (harus positif)\n", r2);
    printf("strcmp(\"a\",\"A\") = %d  (negatif/positif tergantung compiler)\n", r3);

    /* strncmp: bandingkan maksimal n karakter pertama */
    int r4 = strncmp("file.txt", "file.csv", 5);
    printf("strncmp(\"file.txt\",\"file.csv\", 5) = %d  (5 char pertama sama)\n", r4);

    int r5 = strncmp("file.txt", "file.csv", 6);
    printf("strncmp(\"file.txt\",\"file.csv\", 6) = %d  (char ke-6 beda)\n", r5);
    return 0;
}

Output yang Dihasilkan:

text
strcmp("A","B") = -1  (harus negatif)
strcmp("B","A") = 1  (harus positif)
strcmp("a","A") = 1  (negatif/positif tergantung compiler)
strncmp("file.txt","file.csv", 5) = 0  (5 char pertama sama)
strncmp("file.txt","file.csv", 6) = 17  (char ke-6 beda)

Mari kita telaah baris-baris kode di atas:

  1. Baris 9 (int r1 = strcmp("A", "B");): membandingkan 'A' (65) dengan 'B' (66). Pada glibc, return value adalah -1 (negatif) yang menandakan "A" mendahului "B". Pada implementasi lain, return value bisa -1 atau -65 (selisih aktual 65-66=-1).
  2. Baris 10 (int r2 = strcmp("B", "A");): kasus kebalikan, return value 1 (positif).
  3. Baris 11 (int r3 = strcmp("a", "A");): 'a' (97) vs 'A' (65), selisih aktual 32. Pada glibc modern return value 1, tetapi pada compiler/library lama bisa jadi 32. Inilah inti sifat implementation-defined.
  4. Baris 15 (strncmp("file.txt", "file.csv", 5)): membandingkan hanya 5 byte pertama. Karena keduanya diawali "file." (5 byte sama), return value 0.
  5. Baris 18 (strncmp("file.txt", "file.csv", 6)): membandingkan 6 byte. Byte ke-6 berbeda ('t' vs 'c'). Selisih aktual 116 - 99 = 17. Pada glibc, return value 17—ini menarik karena menunjukkan bahwa untuk strncmp glibc mengembalikan selisih byte aktual, bukan -1/0/1. Perilaku ini masih implementation-defined dan tidak boleh diandalkan.

Pemakaian Praktis: Login dan Sorting #

strcmp adalah dasar untuk berbagai operasi string: validasi login, pencarian binary search, dan sorting. Berikut dua contoh praktis.

c
#include <stdio.h>
#include <string.h>

int main(void) {
    /* Login sederhana menggunakan strcmp */
    const char *user = "budi";
    const char *pass = "rahasia123";

    const char *input_user = "budi";
    const char *input_pass = "salah";

    if (strcmp(user, input_user) == 0 &&
        strcmp(pass, input_pass) == 0) {
        printf("Login berhasil.\n");
    } else {
        printf("Login gagal: user atau password salah.\n");
    }

    /* Urutkan array string pakai strcmp */
    const char *buah[] = {"mangga", "apel", "jeruk", "pepaya"};
    int n = 4;
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (strcmp(buah[i], buah[j]) > 0) {
                const char *tmp = buah[i];
                buah[i] = buah[j];
                buah[j] = tmp;
            }
        }
    }
    printf("Buah terurut: ");
    for (int i = 0; i < n; i++) {
        printf("%s ", buah[i]);
    }
    printf("\n");
    return 0;
}

Output yang Dihasilkan:

text
Login gagal: user atau password salah.
Buah terurut: apel jeruk mangga pepaya 

Pada contoh login, kita membandingkan user dengan input_user dan pass dengan input_pass. Karena pass = "rahasia123" berbeda dengan input_pass = "salah", strcmp mengembalikan non-zero sehingga kondisi gabungan && gagal—login ditolak. Pada contoh sorting, kita memakai selection sort yang membandingkan buah[i] dengan buah[j]. Bila strcmp(buah[i], buah[j]) > 0 (berarti buah[i] mengikuti buah[j] secara leksikografis), kedua pointer ditukar. Setelah loop selesai, array {"mangga", "apel", "jeruk", "pepaya"} terurut menjadi {"apel", "jeruk", "mangga", "pepaya"}.

Ringkasan Konsep #

strcmp membandingkan dua string secara leksikografis dan mengembalikan nilai bertanda: negatif bila string pertama mendahului yang kedua, nol bila identik, positif bila string pertama mengikuti yang kedua. Nilai numerik selain nol implementation-defined—-1/1 pada beberapa library, selisih byte aktual pada library lain. Aturan praktis: hanya tanda yang bermakna. Gunakan pembanding == 0, < 0, atau > 0—jangan pernah mengasumsikan nilai numerik spesifik. strncmp(a, b, n) adalah varian yang membatasi perbandingan ke n byte pertama, berguna untuk membandingkan prefix. strcmp adalah dasar untuk operasi string seperti validasi, pencarian, dan sorting. Pada chapter berikutnya kita akan membahas strchr dan strstr—fungsi untuk mencari karakter dan substring di dalam string.