2013-10-02 21 views
6

Ben bir dize ve bir uzunluğa içeren bir yapı var. Ancak, bu yapının içeriğini printf benzeri bir işlev kullanarak çıktılamak istiyorum. data, bir nul sonlandırıcısına sahip olmayabilir (veya yanlış yere sahip olabilir), bu yüzden %s kullanamıyorum. Ancak belirteci, size_t sahipken int gerektirir.Printf Değişken dize uzunluğu Specifier

Şimdi sorun şu ki, string printf kullanarak nasıl çıktı verebilirim?

+7

* Bir 'size_t 'değerini" int "' ye dönüştürebilirsiniz, buradaki değer uyuyorsa ... –

+3

@KerrekSB Eğer uzunluk bir" int "değerine uymuyorsa, bu ilginç bir 'printf' olacaktır. Çağrı :-)) Taşması gerektiğinden emin olmalı. – cnicutar

+6

Eğer 'data' yazdırılamayan karakterler içeriyorsa (boş karakter gibi), '% s' istemezsiniz. Bir döngü yaz. –

cevap

3

basit bir çözüm sadece kullanmak olacaktır biçimlendirilmemiş çıkışı:

fwrite(x.data, 1, x.len, stdout); 

bir döngü içinde kullanılması gerektiğini, böylece fwrite, herşeyi yazamayabilir, bu durum aslında kötü şeklidir;

for (size_t i, remaining = x.len; 
    remaining > 0 && (i = fwrite(x.data, 1, remaining, stdout)) > 0; 
    remaining -= i) { 
} 

x.len SIZE_T_MAX daha büyük olduğundan emin olun.

+0

+1 bunu kendi başıma bırakmak üzereydi. Daha basit olması zor. – WhozCraig

+0

Ama snprintf gibi bir şey kullanmak isteseydim, bu da işe yaramazdı. Bu durumda verileri kopyalayabilirim, diğer formatlama belirleyicilerini kullanabilmeyi tercih ederim ('% i' gibi). –

+0

@drderp: Anlamıyorum. Snprintf'i nasıl kullanırdınız?Bir dosya yerine bir bellek yerine yazmak için 'memcpy' kullanabilirsiniz ... –

1

Dizgiyi printf kullanarak nasıl verebilirim?

Tek bir aramada? Anlamsız bir şekilde yapamazsınız, çünkü garip yerlerde boş sonlandırıcıların olabileceğini söylüyorsunuz. Genelde, arabellek yazdırılamayan karakterler içeriyorsa, dizginizi çıktılarken bu karakterleri nasıl yazdırmak istediğinizi (veya kullanmamanızı) öğrenmeniz gerekir. Bir döngü yazın, her karakteri test edin ve mantığınız dikte ettiğinde yazdırın (ya da yazdırmayın).

11

dize içinde hiç gömülü boş karakteri yok varsayarsak, döküm sonrası %.*s belirtici kullanabilirsiniz size_tint bir etmek:

string_t *s = ...; 
printf("The string is: %.*s\n", (int)s->len, s->data); 

da dize uzunluğu daha az olduğunu farz ediyor That INT_MAX. INT_MAX'dan daha uzun bir diziniz varsa, başka sorunlarınız da vardır (bir şey için 2 milyar karakter basmak oldukça zaman alacaktır).

+0

çok olası değil, ama OP * 16 bit 'int' ile gömülü veya tarihi bir aygıtı hedefleyebilir * – user4815162342

+0

Bu gerçekten bunu yapmak için en iyi yol mu? Davranışları ilk kez not ettiğimde ilk sorum, "Neden bir" size_t "olmasın?" –

+0

@JeremyRodi: Emin değilim, ama benim tahminim, 'size_t' yerine "int" kullanması, çünkü C dilinin standardize edilmesinden önce yazılmış olan kod ile geriye dönük uyumluluk için, "size_t" türünden önce bile mevcut. –