2014-07-02 14 views
6

Po przeczytaniu this zacząłem myśleć, że nauczyłem się łupu o printf(). Nagle znalazłem następujący fragment kodu z this książki:Ternary operator wewnątrz printf

int main() 
{ 
    char str[]="Hello"; 
    int i=5,j=10; 
    printf(i>j?"%50s":"%s",str); //unable to understand this 
    return 0; 
} 

Niespodziewanie Powyższy kod działa bez błędów i drukuje Witam. Według mojej wiedzy jest następujący składnia printf():

int printf(const char *format,argument_list); 

więc według tej składni, printf() powinien zacząć ciągu formatu. Ale jak widać w powyższym kodzie printf() zaczyna się od i>j. Czy to znaczy, że nie mam racji interpretując składnię printf()? Czy umieszczenie operatora trójskładnikowego wewnątrz printf() jest przypadkiem specjalnym?

EDIT

wiem o potrójnym operatora Pytam o pierwszy argument printf() który powinien być const char *, które nie wydają się w moim przykładzie.

+5

Wynik wyrażenia wewnątrz pierwszego parametru musi być wskaźnikiem do stałej tablicy znaków, więc nic zaskakującego. –

+0

masz na myśli wszystko, nawet bez podwójnych cudzysłowów jest wskaźnikiem na stały ciąg –

+1

być może rzeczy staną się bardziej przejrzyste, jeśli napiszesz to w ten sposób: 'printf ((i> j?"% 50s ":"% s "), str)' –

Odpowiedz

6

Operator warunkowy:

i>j?"%50s":"%s" 

jest ekspresja i musi być ocenione przed wywołaniem funkcja może sama być oceniane. Możemy zobaczyć, przechodząc do projektu C99 standardowej sekcji nazywa 6.5.2.2Funkcja który mówi:

Argumentem może być wyrazem dowolnego typu obiektu. Przygotowując się do wywołania funkcji , argumenty są obliczane, a każdemu parametrowi przypisywana jest wartość odpowiedniego argumentu. 81)

Jaki jest wynik oceny operatora warunkowego? Jeśli idziemy do sekcji 6.5.15operator warunkowy mówi (podkr):

Pierwszy argument jest oceniany; istnieje punkt sekwencji po jego ocenie . Drugi argument jest oceniany tylko wtedy, gdy pierwszy porównuje nierówny z 0; trzeci argument jest oceniany tylko wtedy, gdy pierwszy jest porównywany z 0; wynikiem jest wartość drugiego lub trzeciego argumentu (zależnie od tego, która z wartości jest oceniana), przeliczona na typ opisany poniżej: .

więc w obu przypadkach wynik jest ciągiem dosłowne które rozpadają się wskaźnik do char, który spełnia wymóg pierwszy argument printf.

+0

Niezła eksplanacja !! Ale nadal mam wątpliwości w wyrażeniu i> j? "% 50s": "% s", to znaczy nie uważam, że jest to const char *, myślę, że powinno to być ujęte w znaki podwójnego cudzysłowu. Czy nie jest? –

+0

Ok teraz rozumiem to , który jest po wyrażeniu oceny tylko "% s" jest przekazywany jako argument do printf() –

+0

@ A.s.Bhullar dokładnie, to jest poprawne. –

1

Czy to znaczy, że nie mam racji interpretując składnię printf()?

Nie, nie interpretujesz źle.

Czy umieszczenie operatora trójskładnikowego wewnątrz printf() jest przypadkiem specjalnym?

W C, można powiedzieć, że jej wyrazem zamiast oświadczenia

Twój kod jest równoważny:

if (i > j) 
    printf("%50s", str); 
else 
    printf("%s", str); 
1

Operator trójargumentowy jest po prostu inline if, który jest używany jako wyraz (podczas gdy zwykły if jest używany do tworzenia bloku). Twoja linia jest równa:

if (i > j) 
    printf("%50s", str); 
else 
    printf("%s", str); 
3

Ten kod jest normalny i nie jest żadnym specjalnym przypadkiem. Wymaganie dla printf polega na tym, że pierwszy argument powinien być typu const char*, ale niekoniecznie oznacza, że ​​musi być literałem łańcuchowym, takim jak "%s". Wszystko to oznacza, że ​​jako pierwszy argument należy podać wyrażenie typu const char*. I i>j?"%50s":"%s" spełnia to wymaganie.

+0

Czy możesz podać jakiś przykład const char *, który nie jest w pełni zawinięty wewnątrz podwójnego cudzysłowu? –

+1

'i> j?"% 50s ":"% s "' jest typu 'const char *' (technicznie jest to 'const char []' ale nie ma to znaczenia), więc domyślam się, że to jest twój przykład. Innym przykładem może być 'func()', gdzie 'func' jest funkcją zwracającą' const char * '. –

0

Istnieje zestawienie formy: warunek? Skutek: alternatywa.

Warunek jest sprawdzany, a jeśli jest prawdziwy, otrzymasz wynik. inaczej dostaniesz alternatywę.

Na przykład:

5>3 ? 10 : 5 

5> 3 jest prawdą, więc dostaniesz 10.

1
if(i>j) 
    printf("%50s",str); 
else 
    printf("%s",str); 

Dlatego Hello zostanie wydrukowany w obu sytuacjach

1

myślę, że dobrze zrozumiał składni printf ale myślę, że brakuje czegoś o składni C.

istnieć formę "zwarta wtedy jak" oświadczenie sformatowane tak: (? stanprawda: fałszywe)

Na przykład można zrobić:

int a=5; 
int b=(a==5 ? 128 : 256); 
int c=(a!=5 ? 8 : 9); 

W w tym przypadku b = 128 i c = 9.

Innym przykładem:

int flag=1; 
printf("The value is: %s", (flag!=0 ? "true" : "false)); 

W tym przypadku można zobaczyć: Wartość prawda

Na przykład:

printf(i>j?"%50s":"%s",str); 

jeśli jest wyższa niż j ty użyj formatu "% 50s", a jeśli jest niższy, używaj formatu "% s"

Może to wyglądać następująco:

if (i>j) 
    printf("%50s",str); 
else 
    printf("%s",str); 

Możesz zobaczyć zaletę testu kompaktowego.

1

P: Czy to znaczy, że nie mam racji interpretując składnię printf()?
A: Nie, po prostu trzeba powiększyć to, co jest dozwolone.

Pytanie: Czy umieszczenie operatora trójskładnikowego wewnątrz funkcji printf() jest przypadkiem specjalnym?
A: Nie ?: nie jest wyjątkowy, ale czasami mylące na pierwszy rzut oka.

Format dostarczony pod numer printf() nie musi być literałem. Może to być dowolna zmienna łańcuchowa.

int main() { 
    char str[]="Hello"; 
    char *format; 
    int i,j; 

    i = 5; j = 10; 
    format = i > j ? "%50s" : "%s"; 
    printf(format, str); 

    i = 10; j = 5; 
    format = i > j ? "%50s" : "%s"; 
    printf(format, str); 
    return 0; 
} 
2

Jest to operator trójargumentowy iw tym stanie i> j jest tak fałszywe% s zostanie przekazany jako parametr do printf, która drukuje wartość tablicy znaków, który jest cześć.