Menu

C'de Metin Fonksiyonları: strlen, strcpy, strcat, strcmp ve Dahası

<string.h>'in çalışan bir turu: strlen ile ölçmek, strcpy ve strncpy ile kopyalamak, strcat ile birleştirmek, strcmp ile karşılaştırmak, strchr ve strstr ile aramak - ve hiçbirinin taşmaması için tamponları nasıl boyutlandıracağınız.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

<string.h> içindeki her fonksiyon, boş sonlandırıcıda duran, bir char dizisi üzerindeki küçük bir döngüdür. Bu anlaşıldığında kütüphane gizemli isimlerden oluşan bir liste gibi görünmeyi bırakır ve kendiniz yazacağınız bir avuç döngü gibi görünmeye başlar. Bu sayfa gerçek işin neredeyse tamamını taşıyanları - ve onların tamponlarınızın sonunun ötesine yazmasını engelleyen boyutlandırma kurallarını - ele alıyor.

Buradaki her şey tek bir include ister:

#include <string.h>

strlen: Kaç Karakter

strlen, sonlandırıcıya kadar (onu dahil etmeden) baytları sayar. size_t döndürür, dolayısıyla onu %zu ile yazdırın.

strlen 6'dır; sizeof 32'dir. Birincisi metin, ikincisi depolamadır - o ayrımın neden bu kadar önemli olduğu için bkz. metinler.

strlen her çağrıda tüm metni dolaşır, dolayısıyla onu değişmeyen aynı metin üzerindeki bir döngü koşuluna koymayın:

/* her yinelemede tüm metni yeniden sayar */
for (size_t i = 0; i < strlen(s); i++) { ... }

/* bir kez say */
size_t n = strlen(s);
for (size_t i = 0; i < n; i++) { ... }

strcpy ve strncpy: Kopyalamak

strcpy(dst, src), karakterleri artı sonlandırıcıyı kopyalar. dst'nin ne kadar büyük olduğu hakkında hiçbir fikre sahip değildir, dolayısıyla çağıran dst'nin en az strlen(src) + 1 bayt tuttuğunu garanti etmelidir.

strncpy en fazla bir sayı alır, ama meşhur bir tuzağı vardır: kaynak en az n bayt uzunluğundayken tam olarak n karakter kopyalar ve hiç sonlandırıcı koymaz. Her zaman kendiniz sonlandırın:

sizeof dst - 1 artı açık sonlandırıcı, ezberlenmesi gereken kalıptır. (strncpy ayrıca kısa kaynakları n bayta kadar sıfırla doldurur ki bu büyük tamponlar için boşa yapılan iştir - güvenlik için değil sabit genişlikli kayıtlar için tasarlanmıştı.)

strcat ve strncat: Birleştirmek

strcat(dst, src), src'yi dst'de zaten ne varsa onun sonuna ekler. Hedef, her iki metni artı bir sonlandırıcıyı tutmalıdır ve zaten geçerli bir metin içeriyor olmalıdır - ilk değersiz belleğe eklemek tanımsız davranıştır.

char path[64]; yerine char path[64] = "/home/ada"; olduğuna dikkat edin - ilk değer, onu ilk strcat için geçerli bir metin yapan şeydir.

strncat(dst, src, n), en fazla n karakter ekler ve her zaman bir sonlandırıcı koyar, dolayısıyla n, toplam tampon boyutu değil kalan alandır:

strncat(dst, src, sizeof dst - strlen(dst) - 1);

Tekrarlanan strcat çağrıları, sonunu bulmak için hedefi her seferinde yeniden tarar. Bir döngüde uzun bir metni böyle kurmak karesel maliyetlidir; büyükçe bir şey için kendi yazma konumunuzu takip edin ya da metin dönüşümü sayfasında ele alınan snprintf'i kullanın.

strcmp: Karşılaştırmak

== adresleri karşılaştırır, dolayısıyla aynı metni tutan iki ayrı dizi için yanlıştır. strcmp karakterleri karşılaştırır ve farkın işaretini döndürür.

Üç kural:

  • Eşitlik için strcmp(a, b) == 0 test edin. if (strcmp(a, b)) yazmak "eğer farklıysalar" demektir ki bu neredeyse herkese ters okunur.
  • Yalnızca işaret tanımlıdır. Sonucu 1 ya da -1 ile karşılaştırmayın.
  • Sıralama bayt değerine göredir, dolayısıyla ASCII'de "Zebra", "apple"'dan önce sıralanır. Büyük-küçük harf duyarsız karşılaştırma için önce iki kopyayı da küçük harfe çevirin - yaygın görülen strcasecmp bir POSIX uzantısıdır, standart C değildir.

strncmp(a, b, n) yalnızca ilk n karakteri karşılaştırır ki bu bir öneki test etmenin temiz yoludur:

strchr ve strstr: Aramak

strchr(s, ch), bir karakterin ilk geçişini bulur; strrchr sonuncusunu bulur. strstr(haystack, needle) bir alt metin bulur. Üçü de özgün metnin içine bir gösterici ya da eşleşme yoksa NULL döndürür.

Döndürülen göstericiyi başlangıçtan çıkarmak indeksi verir; tipi ptrdiff_t'dir ve %td ile yazdırılır. Sonuç özgün dizinin içini gösterdiği için at + 1, hiç kopyalama olmadan metnin geri kalanıdır - çok yaygın bir C deyimi.

Dereferans etmeden önce her zaman NULL kontrolü yapın. @ içermeyen bir metinde strchr(email, '@') + 1, NULL'dan bir adres hesaplar ve program artık tanımlı değildir.

Bir Metni Bölmek

Bir bölme fonksiyonu yoktur, ama strchr artı bir sonlandırıcı işi yerinde halleder. Bu örnek bir e-postayı kullanıcı ve alan adı olarak keser:

memcpy, sonlandırıcıları umursamadan kesin bir bayt sayısı kopyalar ki uzunluğu zaten bildiğinizde istediğiniz budur. Sonlandırıcı ardından elle yazılır.

İşlenmiş Bir Örnek: Bir İsmi Normalleştirmek

Turu bir araya getirelim - kırpma, karşılaştırma, kopyalama ve birleştirme:

Her yazma hedefin kendi sizeof'uyla sınırlıdır ve her strncpy'yi açık bir sonlandırıcı izler. Tutarlı uygulanan o disiplin, C metin kodunu güvenli kılan şeydir.

Akılda Tutulacak Boyutlandırma Kuralları

  • strcpy, hedefte strlen(src) + 1 bayt boş yer ister.
  • strcat, strlen(dst) + strlen(src) + 1 ister.
  • strncpy'den sonra dst[n - 1] = '\0' yazın.
  • strncat için sayı, kalan alandır: sizeof dst - strlen(dst) - 1.
  • Sonucu kullanmadan önce strchr ve strstrNULL için denetleyin.
  • sizeof dst'yi yalnızca dst gerçek bir diziyken kullanın. char *dst alan bir fonksiyonun içinde sizeof göstericinin boyutunu verir - tampon uzunluğunu ayrı bir parametre olarak geçirin.

Sıkça Sorulan Sorular

C'de strcmp ne döndürür?

İki metin özdeş olduğunda sıfır, birincisi ikinciden önce sıralandığında negatif bir değer ve sonra sıralandığında pozitif bir değer. Yalnızca işaret anlamlıdır - asla -1 ya da 1 döndürdüğünü varsaymayın. İstediğiniz test neredeyse her zaman if (strcmp(a, b) == 0)'dır.

C'de metinleri neden == ile karşılaştıramam?

a == b, karakterleri değil iki adresi karşılaştırır. "kedi" tutan iki ayrı dizi farklı adreslerde yaşar, dolayısıyla metin eşleşse bile karşılaştırma yanlıştır. <string.h>'deki strcmp(a, b) == 0'ı kullanın.

strcpy ile strncpy arasındaki fark nedir?

strcpy, hedefin ne kadar büyük olduğu hakkında hiçbir fikri olmadan kaynağın '\0''ına kadar kopyalar. strncpy en fazla n bayttan sonra durur - ama kaynak o kadar uzunsa hiç sonlandırıcı kopyalamaz, dolayısıyla dst[n - 1] = '\0'; yazmanız gerekir. Hiçbiri kendiliğinden güvenli değildir; boyut disiplini sizindir.

C'de bir alt metni nasıl bulurum?

strstr(haystack, needle), ilk geçişe bir gösterici ya da yoksa NULL döndürür. Özgün metnin içine bir gösterici döndürdüğü için found - haystack size indeksi verir. Tek bir karakter ararken strchr kullanın.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA