Bagaimana cara membandingkan string dengan benar?

183

Saya mencoba mendapatkan program untuk membiarkan pengguna memasukkan kata atau karakter, menyimpannya, dan mencetaknya hingga pengguna mengetiknya lagi, keluar dari program. Kode saya terlihat seperti ini:

#include <stdio.h>

int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    gets(input);
    printf("I will now repeat this until you type it back to me.\n");

    while (check != input)
    {
        printf("%s\n", input);
        gets(check); 
    }

    printf("Good bye!");


    return 0;
}

Masalahnya adalah bahwa saya terus mendapatkan pencetakan dari string input, bahkan ketika input oleh pengguna (centang) cocok dengan yang asli (input). Apakah saya salah membandingkan keduanya?

nmagerko
sumber
13
gets( )telah dihapus dari standar. Gunakan fgets( )sebagai gantinya.
Edward Karak
1
Perhatikan bahwa jawaban untuk Mengapa ini strcmp()mengembalikan nol ketika inputnya sama menjelaskan bagaimana membandingkan string untuk kesetaraan, ketidaksetaraan, kurang dari, lebih besar dari, lebih kecil dari atau sama, dan lebih besar dari atau sama. Tidak semua perbandingan string adalah untuk kesetaraan. Perbandingan case sensitif berbeda lagi; perbandingan khusus lainnya (urutan kamus, misalnya) memerlukan pembanding yang lebih khusus, dan ada regex untuk perbandingan yang lebih kompleks.
Jonathan Leffler
Perhatikan juga bahwa pada dasarnya ada pertanyaan duplikat Bagaimana cara saya memeriksa apakah suatu nilai cocok dengan string yang ditanyakan bertahun-tahun sebelumnya.
Jonathan Leffler
Apakah ini menjawab pertanyaan Anda? Bagaimana cara memeriksa apakah suatu nilai cocok dengan string
Andreas
Pertanyaan ini bagus, tetapi penggunaannya gets()adalah no-go. Itu juga telah dihapus dari standar sejak C11 -> Silakan baca Mengapa fungsi mendapat begitu berbahaya sehingga tidak boleh digunakan?
RobertS mendukung Monica Cellio

Jawaban:

276

Anda tidak dapat (berguna) membandingkan string menggunakan !=atau ==, Anda perlu menggunakan strcmp:

while (strcmp(check,input) != 0)

Alasan untuk ini adalah karena !=dan ==hanya akan membandingkan alamat basis dari string tersebut. Bukan isi dawai itu sendiri.

Mistikal
sumber
10
sama di java, yang bisa dibandingkan dengan alamat.
Telerik
29
Menulis while (strcmp(check, input))sudah memadai dan dianggap praktik yang baik.
Shiva
tahu lebih banyak ... codificare.in/codes/c/...
Chanu panwar
7
Lebih aman menggunakan strncmp! Tidak ingin buffer overflow!
Floam
@ Floam Jika Anda tidak benar-benar memiliki string, tetapi urutan nol-padded dari karakter non-nol yang diketahui panjang, tentu saja, itu akan menjadi mantra yang tepat. Tapi itu sesuatu yang sangat berbeda!
Deduplicator
33

Ok beberapa hal: getstidak aman dan harus diganti fgets(input, sizeof(input), stdin)sehingga Anda tidak mendapatkan buffer overflow.

Selanjutnya, untuk membandingkan string, Anda harus menggunakan strcmp, di mana nilai balik 0 menunjukkan bahwa kedua string cocok. Menggunakan operator kesetaraan (mis. !=) Membandingkan alamat dari dua string, yang bertentangan dengan individu chardi dalamnya.

Dan juga perhatikan bahwa, sementara dalam contoh ini tidak akan menimbulkan masalah, fgetsmenyimpan karakter baris baru, '\n'di buffer juga; gets()tidak. Jika Anda membandingkan input pengguna dari fgets()string literal seperti "abc"itu tidak akan pernah cocok (kecuali buffer terlalu kecil sehingga '\n'tidak muat di dalamnya).

AusCBloke
sumber
Bisakah Anda memperjelas hubungan / masalah "\ n" dan string literal? Saya mendapatkan hasil yang tidak sama dalam membandingkan string (baris) file dengan seluruh file lainnya.
tidak kompeten
@incompetent - jika Anda membaca baris dari file dengan fgets(), maka string mungkin "abc\n"karena fgets()menjaga baris baru. Jika Anda membandingkannya dengan "abc", Anda akan mendapatkan 'tidak sama' karena perbedaan antara terminasi null byte "abc"dan baris baru dalam data yang dibaca. Jadi, Anda harus zap baris baru. Cara satu garis yang dapat diandalkan untuk melakukan itu adalah buffer[strcspn(buffer, "\n")] = '\0';yang memiliki manfaat bekerja dengan benar terlepas dari apakah ada data dalam buffer, atau apakah data itu berakhir dengan baris baru atau tidak. Cara lain untuk mengubah saluran baru dengan mudah macet.
Jonathan Leffler
Jawaban ini membahas masalah kode secara akurat, sedangkan jawaban yang paling banyak dipilih dan diterima hanya mencakup untuk menjawab judul pertanyaan. Apalagi menyebutkan paragraf terakhir adalah super. +1
RobertS mendukung Monica Cellio
11

Gunakan strcmp.

Ini ada di string.hperpustakaan, dan sangat populer. strcmpmengembalikan 0 jika string sama. Lihat ini untuk penjelasan yang lebih baik tentang apa yang strcmpkembali.

Pada dasarnya, Anda harus melakukan:

while (strcmp(check,input) != 0)

atau

while (!strcmp(check,input))

atau

while (strcmp(check,input))

Anda dapat memeriksa ini , tutorial tentang strcmp.

Ashish Ahuja
sumber
7

Anda tidak dapat membandingkan array secara langsung seperti ini

array1==array2

Anda harus membandingkannya char-by-char; untuk ini, Anda dapat menggunakan fungsi dan mengembalikan nilai boolean (True: 1, False: 0). Kemudian Anda dapat menggunakannya dalam kondisi pengujian loop sementara.

Coba ini:

#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    scanf("%s",input);
    printf("I will now repeat this until you type it back to me.\n");
    scanf("%s",check);

    while (!checker(input,check))
    {
        printf("%s\n", input);
        scanf("%s",check);
    }

    printf("Good bye!");

    return 0;
}

int checker(char input[],char check[])
{
    int i,result=1;
    for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
        if(input[i] != check[i]) {
            result=0;
            break;
        }
    }
    return result;
}
mugetsu
sumber
1
Bisakah Anda menambahkan detail lebih lanjut tentang solusi Anda?
abarisone
ya ini adalah pengganti untuk fungsi dan solition strcmp tanpa menggunakan string.h header @Jongware
mugetsu
2
Ini tidak bekerja. Ketika checkerditemukan '\0'di salah satu string, itu tidak memeriksa string yang lain '\0'. Fungsi mengembalikan 1("sama") bahkan jika satu string hanya awalan dari yang lain (misalnya, "foo"dan "foobar").
lukasrozs
1
Saya akan menggunakan ||sebagai gantinya &&.
lukasrozs
3

Selamat datang di konsep penunjuk. Generasi pemrogram pemula telah menemukan konsep itu sulit dipahami, tetapi jika Anda ingin tumbuh menjadi programmer yang kompeten, Anda akhirnya harus menguasai konsep ini - dan terlebih lagi, Anda sudah mengajukan pertanyaan yang tepat. Itu bagus.

Apakah jelas bagi Anda alamat itu apa? Lihat diagram ini:

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    7   |
----------     ----------

Dalam diagram, bilangan bulat 1 disimpan dalam memori di alamat 0x4000. Kenapa di alamat? Karena ingatannya besar dan dapat menyimpan banyak bilangan bulat, sama seperti sebuah kota besar dan dapat menampung banyak keluarga. Setiap bilangan bulat disimpan di lokasi memori, karena setiap keluarga berada di rumah. Setiap lokasi memori diidentifikasi oleh alamat , karena setiap rumah diidentifikasi oleh alamat.

Dua kotak dalam diagram mewakili dua lokasi memori yang berbeda. Anda dapat menganggap mereka seolah-olah mereka adalah rumah. Bilangan bulat 1 berada di lokasi memori di alamat 0x4000 (pikirkan, "4000 Elm St."). Bilangan bulat 7 berada di lokasi memori di alamat 0x4004 (pikirkan, "4004 Elm St.").

Anda mengira program Anda membandingkan angka 1 dengan angka 7, tetapi ternyata tidak. Itu membandingkan 0x4000 dengan 0x4004. Jadi apa yang terjadi ketika Anda memiliki situasi ini?

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    1   |
----------     ----------

Kedua bilangan bulat itu sama tetapi alamatnya berbeda. Program Anda membandingkan alamat.

thb
sumber
2

Setiap kali Anda mencoba membandingkan string, bandingkan dengan masing-masing karakter. Untuk ini, Anda dapat menggunakan fungsi string bawaan yang disebut strcmp (input1, input2); dan Anda harus menggunakan file header yang disebut#include<string.h>

Coba kode ini:

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

int main() 
{ 
    char s[]="STACKOVERFLOW";
    char s1[200];
    printf("Enter the string to be checked\n");//enter the input string
    scanf("%s",s1);
    if(strcmp(s,s1)==0)//compare both the strings  
    {
        printf("Both the Strings match\n"); 
    } 
    else
    {
        printf("Entered String does not match\n");  
    } 
    system("pause");  
} 
Vishwanath Tallalli
sumber
0

Bagaimana cara membandingkan string dengan benar?

char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow

// insufficient
while (check != input)

// good
while (strcmp(check, input) != 0)
// or 
while (strcmp(check, input))

Mari kita gali lebih dalam untuk melihat mengapa check != inputtidak cukup .

Dalam C, string adalah spesifikasi perpustakaan standar.

Sebuah String adalah urutan bersebelahan karakter diakhiri oleh dan termasuk karakter null pertama.
C11 §7.1.1 1

inputdi atas bukan string . inputadalah array 40 dari char .

Isi inputbisa menjadi string .

Dalam kebanyakan kasus, ketika sebuah array digunakan dalam ekspresi, itu dikonversi ke alamat elemen pertama.

Di bawah ini mengkonversi checkdan inputke masing-masing alamat elemen pertama, kemudian alamat tersebut dibandingkan.

check != input   // Compare addresses, not the contents of what addresses reference

Untuk membandingkan string , kita perlu menggunakan alamat itu dan kemudian melihat data yang mereka tuju.
strcmp()melakukan pekerjaan . §7.23.4.2

int strcmp(const char *s1, const char *s2);

The strcmpFungsi membandingkan string ditunjukkan oleh s1ke string yang ditunjukkan oleh s2.

The strcmpkembali fungsi suatu yang lebih besar bilangan bulat dari, sama dengan, atau kurang dari nol, sesuai sebagai string yang ditunjukkan oleh s1lebih besar dari, sama dengan, atau kurang dari string yang ditunjukkan oleh s2.

Tidak hanya kode yang dapat menemukan apakah string memiliki data yang sama, tetapi mana yang lebih besar / kurang ketika mereka berbeda.

Di bawah ini benar ketika string berbeda.

strcmp(check, input) != 0

Untuk wawasan, lihat Membuat strcmp()fungsi saya sendiri

chux - Pasang kembali Monica
sumber
-2
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char s1[50],s2[50];
        printf("Enter the character of strings: ");
        gets(s1);
        printf("\nEnter different character of string to repeat: \n");
        while(strcmp(s1,s2))
        {
            printf("%s\n",s1);
            gets(s2);
        }
        return 0;
    }

Ini adalah solusi yang sangat sederhana di mana Anda akan mendapatkan output seperti yang Anda inginkan.

Rupani TD
sumber
2
gets();bukan bagian dari standar C sejak C11.
chux
2
strcmp(s1,s2)adalah UB karena s2isinya tidak ditentukan pada awalnya.
chux
Akan lebih bagus jika Anda juga bisa memberikan output potongan ini, dalam beberapa bentuk atau lainnya.
not2qubit