C Language
Urvalsförklaringar
Sök…
if () Uttalanden
Ett av de enklaste sätten att kontrollera programflödet är genom att använda if
val-uttalanden. Huruvida ett kodblock ska köras eller inte ska köras kan avgöras av detta uttalande.
Syntaxen för if
markeringssats i C kan vara följande:
if(cond)
{
statement(s); /*to be executed, on condition being true*/
}
Till exempel,
if (a > 1) {
puts("a is larger than 1");
}
Där a > 1
är ett villkor som måste utvärderas till true
för att utföra påståenden inuti if
blocket. I detta exempel skrivs "a är större än 1" endast om a > 1
är sant.
if
urvalssatser kan utelämna lindringarna {
och }
om det bara finns ett uttalande i blocket. Exemplet ovan kan skrivas om till
if (a > 1)
puts("a is larger than 1");
Men för att utföra flera uttalanden inom block måste hängslen användas.
Villkoret för if
kan inkludera flera uttryck. if
kommer bara att utföra handlingen om slutresultatet av uttrycket är sant.
Till exempel
if ((a > 1) && (b > 1)) {
puts("a is larger than 1");
a++;
}
kör endast printf
och a++
om både a
och b
är större än 1
.
if () ... annat uttalanden och syntax
Medan if
utför en åtgärd när dess villkor utvärderas till true
, if
/ else
kan du ange de olika åtgärderna när villkoret är true
och när villkoret är false
.
Exempel:
if (a > 1)
puts("a is larger than 1");
else
puts("a is not larger than 1");
Precis som if
uttalandet, när blocket inom if
eller else
är bestående av endast ett uttalande, då hängslen kan utelämnas (men detta rekommenderas inte eftersom det lätt kan införa problem ofrivilligt). Men om det finns mer än ett uttalande i if
eller else
blocket, måste hängslen användas på det specifika blocket.
if (a > 1)
{
puts("a is larger than 1");
a--;
}
else
{
puts("a is not larger than 1");
a++;
}
switch () Uttalanden
switch
uttalanden är användbara när du vill att ditt program ska göra många olika saker beroende på värdet på en viss testvariabel.
Ett exempel på användning av switch
uttalande är så här:
int a = 1;
switch (a) {
case 1:
puts("a is 1");
break;
case 2:
puts("a is 2");
break;
default:
puts("a is neither 1 nor 2");
break;
}
Detta exempel motsvarar
int a = 1;
if (a == 1) {
puts("a is 1");
} else if (a == 2) {
puts("a is 2");
} else {
puts("a is neither 1 nor 2");
}
Om värdet på a
är en, då switch
uttalande används a is 1
kommer att skrivas ut. Om värdet på a
är 2 kommer a is 2
skrivas ut. Annars skrivs a is neither 1 nor 2
ut.
case n:
används för att beskriva var exekveringsflödet hoppar in när värdet som skickas för att switch
uttalande är n . n måste vara kompileringstidskonstant och samma n kan existera högst en gång i ett switch
uttalande.
default:
används för att beskriva det när värdet inte matchade något av valen för case n:
Det är en bra praxis att inkludera ett default
i varje switch-uttalande för att fånga oväntat beteende.
En break;
uttalande krävs för att hoppa ut ur switch
.
Obs: Om du av misstag glömmer att lägga till en break
efter att ett case
, kommer kompilatorn att anta att du tänker "falla igenom" och alla efterföljande ärendeuttalanden, om några, kommer att köras (såvida inte ett brytande uttalande finns i något av de efterföljande fallen), oavsett om den eller de efterföljande ärendeklarationerna matchar eller inte. Den här egenskapen används för att implementera Duff's Device . Detta beteende anses ofta vara en brist i specifikationen för C-språket.
Nedan är ett exempel som visar effekter av frånvaro av break;
:
int a = 1;
switch (a) {
case 1:
case 2:
puts("a is 1 or 2");
case 3:
puts("a is 1, 2 or 3");
break;
default:
puts("a is neither 1, 2 nor 3");
break;
}
När värdet på a
är 1 eller 2, a is 1 or 2
och a is 1, 2 or 3
kommer båda att skrivas ut. När a
är 3, skrivs endast a is 1, 2 or 3
. Annars skrivs a is neither 1, 2 nor 3
ut.
Observera att default
inte är nödvändigt, särskilt när den uppsättning värden som du får i switch
är klar och känd vid kompileringstiden.
Det bästa exemplet är att använda en switch
på enum
.
enum msg_type { ACK, PING, ERROR };
void f(enum msg_type t)
{
switch (t) {
case ACK:
// do nothing
break;
case PING:
// do something
break;
case ERROR:
// do something else
break;
}
}
Det finns flera fördelar med att göra detta:
- de flesta kompilatorer kommer att rapportera en varning om du inte hanterar ett värde (detta skulle inte rapporteras om ett
default
var närvarande) - av samma anledning, om du lägger till ett nytt värde i
enum
, kommer du att meddelas alla platser där du har glömt att hantera det nya värdet (med ettdefault
måste du manuellt utforska din kod som söker efter sådana fall) - Läsaren behöver inte ta reda på "vad som är doldt som
default:
", vare sig det finns andraenum
eller om det är ett skydd för "bara i fall". Och om det finns andraenum
, använde kodaren avsiktligtdefault
för dem eller finns det ett fel som introducerades när han lade till värdet? - hantering av varje
enum
gör koden självförklarande eftersom du inte kan gömma sig bakom ett vildkort, du måste uttryckligen hantera var och en av dem.
Ändå kan du inte hindra någon att skriva ond kod som:
enum msg_type t = (enum msg_type)666; // I'm evil
Således kan du lägga till en extra kontroll innan du växlar för att upptäcka den, om du verkligen behöver det.
void f(enum msg_type t)
{
if (!is_msg_type_valid(t)) {
// Handle this unlikely error
}
switch(t) {
// Same code than before
}
}
om () ... annars Stege Kedja två eller fler om () ... annars uttalanden
Medan if ()... else
uttalandet tillåter att bara definiera ett (standard) beteende som uppstår när villkoret inom if ()
inte är uppfylld, kedjar två eller fler if () ... else
uttalanden gör det möjligt att definiera ett par mer beteende innan du går till den sista else
grenen som fungerar som en "standard", om någon.
Exempel:
int a = ... /* initialise to some value. */
if (a >= 1)
{
printf("a is greater than or equals 1.\n");
}
else if (a == 0) //we already know that a is smaller than 1
{
printf("a equals 0.\n");
}
else /* a is smaller than 1 and not equals 0, hence: */
{
printf("a is negative.\n");
}
Häckt om () ... annars VS om () .. annars Stege
Kapslade if()...else
uttalanden tar mer körningstid (de är långsammare) i jämförelse med en if()...else
stege eftersom de kapslade if()...else
säger alla inre villkorliga uttalanden en gång de yttre villkorad if()
-säkringen är uppfylld, medan if()..else
stegen kommer att stoppa tillståndstestning när någon av if()
eller else if()
villkorliga uttalanden är sanna.
En if()...else
stege:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a, b, c;
printf("\nEnter Three numbers = ");
scanf("%d%d%d", &a, &b, &c);
if ((a < b) && (a < c))
{
printf("\na = %d is the smallest.", a);
}
else if ((b < a) && (b < c))
{
printf("\nb = %d is the smallest.", b);
}
else if ((c < a) && (c < b))
{
printf("\nc = %d is the smallest.", c);
}
else
{
printf("\nImprove your coding logic");
}
return 0;
}
Anses i allmänhet vara bättre än motsvarande kapslade if()...else
:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a, b, c;
printf("\nEnter Three numbers = ");
scanf("%d%d%d", &a, &b, &c);
if (a < b)
{
if (a < c)
{
printf("\na = %d is the smallest.", a);
}
else
{
printf("\nc = %d is the smallest.", c);
}
}
else
{
if(b < c)
{
printf("\nb = %d is the smallest.", b);
}
else
{
printf("\nc = %d is the smallest.", c);
}
}
return 0;
}