C++
Kontrola przepływu
Szukaj…
Uwagi
Sprawdź temat pętli dla różnych rodzajów pętli.
walizka
Wprowadza etykietę przypadku instrukcji switch. Argument musi być ciągłym wyrażeniem i odpowiadać typowi warunku przełączenia. Po wykonaniu instrukcji switch przeskoczy ona do etykiety sprawy z operandem równym warunkowi, jeśli taki istnieje.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
przełącznik
Zgodnie ze standardem C ++
Instrukcja
switch
powoduje przekazanie kontroli do jednej z kilku instrukcji w zależności od wartości warunku.
Po switch
słowa kluczowego następuje nawias kwadratowy i blok, który może zawierać etykiety case
i opcjonalną etykietę default
. Po wykonaniu instrukcji switch kontrola zostanie przeniesiona na etykietę case
o wartości zgodnej z wartością warunku, jeśli istnieje, lub na etykietę default
, jeśli istnieje.
Warunek musi być wyrażeniem lub deklaracją, która ma albo liczbę całkowitą lub typ wyliczenia, albo typ klasy z funkcją konwersji na typ liczby całkowitej lub wyliczenia.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
złapać
catch
kluczowe catch
wprowadza moduł obsługi wyjątków, czyli blok, do którego zostanie przekazana kontrola, gdy zostanie zgłoszony wyjątek kompatybilnego typu. Po słowie kluczowym catch
znajduje się nawiasowa deklaracja wyjątku , która ma formę podobną do deklaracji parametru funkcji: nazwa parametru może zostać pominięta, a wielokropek ...
jest dozwolony, co pasuje do dowolnego typu. Procedura obsługi wyjątków obsłuży wyjątek tylko wtedy, gdy jego deklaracja jest zgodna z typem wyjątku. Aby uzyskać więcej informacji, zobacz wyłapywanie wyjątków .
try {
std::vector<int> v(N);
// do something
} catch (const std::bad_alloc&) {
std::cout << "failed to allocate memory for vector!" << std::endl;
} catch (const std::runtime_error& e) {
std::cout << "runtime error: " << e.what() << std::endl;
} catch (...) {
std::cout << "unexpected exception!" << std::endl;
throw;
}
domyślna
W instrukcji switch wprowadza etykietę, do której nastąpi przeskoczenie, jeśli wartość warunku nie jest równa żadnej z wartości etykiet sprawy.
char c = getchar();
bool confirmed;
switch (c) {
case 'y':
confirmed = true;
break;
case 'n':
confirmed = false;
break;
default:
std::cout << "invalid response!\n";
abort();
}
Definiuje domyślnego konstruktora, konstruktora kopiowania, konstruktora przenoszenia, destruktora, operatora przypisania kopii lub operatora przypisania przeniesienia, aby zachować jego domyślne zachowanie.
class Base {
// ...
// we want to be able to delete derived classes through Base*,
// but have the usual behaviour for Base's destructor.
virtual ~Base() = default;
};
gdyby
Wprowadza instrukcję if. Słowo kluczowe if
muszą być przestrzegane przez warunek nawiasy, które mogą być wyrazem lub oświadczenie. Jeśli warunek jest prawdziwy, podstacja po warunku zostanie wykonana.
int x;
std::cout << "Please enter a positive number." << std::endl;
std::cin >> x;
if (x <= 0) {
std::cout << "You didn't enter a positive number!" << std::endl;
abort();
}
jeszcze
Po pierwszym zastąpieniu instrukcji if może następować słowo kluczowe else
. Podstacja po słowie kluczowym else
zostanie wykonana, gdy warunek jest falsey (to znaczy, gdy pierwsza podstacja nie zostanie wykonana).
int x;
std::cin >> x;
if (x%2 == 0) {
std::cout << "The number is even\n";
} else {
std::cout << "The number is odd\n";
}
iść do
Przechodzi do instrukcji oznaczonej etykietą, która musi znajdować się w bieżącej funkcji.
bool f(int arg) {
bool result = false;
hWidget widget = get_widget(arg);
if (!g()) {
// we can't continue, but must do cleanup still
goto end;
}
// ...
result = true;
end:
release_widget(widget);
return result;
}
powrót
Zwraca kontrolę z funkcji do jej obiektu wywołującego.
Jeśli return
ma operand, operand jest konwertowany na typ zwracany przez funkcję, a przekonwertowana wartość jest zwracana do obiektu wywołującego.
int f() {
return 42;
}
int x = f(); // x is 42
int g() {
return 3.14;
}
int y = g(); // y is 3
Jeśli return
nie ma operandu, funkcja musi mieć void
typ return. W szczególnym przypadku funkcja zwracająca void
może również zwrócić wyrażenie, jeśli ma ono typ void
.
void f(int x) {
if (x < 0) return;
std::cout << sqrt(x);
}
int g() { return 42; }
void h() {
return f(); // calls f, then returns
return g(); // ill-formed
}
Kiedy main
zwraca, std::exit
jest domyślnie wywoływane z wartością zwracaną, a zatem wartość jest zwracana do środowiska wykonawczego. (Jednak powrót z main
niszczy automatyczne zmienne lokalne, a bezpośrednie wywoływanie std::exit
nie.)
int main(int argc, char** argv) {
if (argc < 2) {
std::cout << "Missing argument\n";
return EXIT_FAILURE; // equivalent to: exit(EXIT_FAILURE);
}
}
rzucać
Kiedy
throw
występuje w wyrażeniu z operandem, jego efektem jest zgłoszenie wyjątku , który jest kopią operandu.void print_asterisks(int count) { if (count < 0) { throw std::invalid_argument("count cannot be negative!"); } while (count--) { putchar('*'); } }
Gdy
throw
występuje w wyrażeniu bez argumentu, jego efektem jest ponowne zwrócenie bieżącego wyjątku . Jeśli nie ma bieżącego wyjątku, wywoływane jeststd::terminate
.try { // something risky } catch (const std::bad_alloc&) { std::cerr << "out of memory" << std::endl; } catch (...) { std::cerr << "unexpected exception" << std::endl; // hope the caller knows how to handle this exception throw; }
Kiedy
throw
występuje w deklaratorze funkcji, wprowadza dynamiczną specyfikację wyjątków, która zawiera listę wyjątków, które funkcja może propagować.// this function might propagate a std::runtime_error, // but not, say, a std::logic_error void risky() throw(std::runtime_error); // this function can't propagate any exceptions void safe() throw();
Dynamiczne specyfikacje wyjątków są przestarzałe od C ++ 11.
Zauważ, że dwa pierwsze zastosowania throw
wymienione powyżej stanowią wyrażenia, a nie wyrażenia. (Typ wyrażenia void
jest void
.) Umożliwia to zagnieżdżenie ich w wyrażeniach, na przykład:
unsigned int predecessor(unsigned int x) {
return (x > 0) ? (x - 1) : (throw std::invalid_argument("0 has no predecessor"));
}
próbować
Po słowie kluczowym try
następuje blok lub lista inicjalizująca konstruktora, a następnie blok (patrz tutaj ). Po bloku try występuje jeden lub więcej bloków catch . Jeśli wyjątek propaguje się poza blok try, każdy z odpowiednich bloków catch po bloku try ma możliwość obsługi wyjątku, jeśli typy są zgodne.
std::vector<int> v(N); // if an exception is thrown here,
// it will not be caught by the following catch block
try {
std::vector<int> v(N); // if an exception is thrown here,
// it will be caught by the following catch block
// do something with v
} catch (const std::bad_alloc&) {
// handle bad_alloc exceptions from the try block
}
Struktury warunkowe: if, if..else
jeśli i jeszcze:
służył do sprawdzania, czy podane wyrażenie zwraca wartość prawda czy fałsz i działa w ten sposób:
if (condition) statement
warunkiem może być dowolne poprawne wyrażenie C ++, które zwraca coś, co można sprawdzić pod kątem prawdy / fałszu, na przykład:
if (true) { /* code here */ } // evaluate that true is true and execute the code in the brackets
if (false) { /* code here */ } // always skip the code since false is always false
warunkiem może być na przykład dowolna funkcja, zmienna lub porównanie
if(istrue()) { } // evaluate the function, if it returns true, the if will execute the code
if(isTrue(var)) { } //evalute the return of the function after passing the argument var
if(a == b) { } // this will evaluate the return of the experssion (a==b) which will be true if equal and false if unequal
if(a) { } //if a is a boolean type, it will evaluate for its value, if it's an integer, any non zero value will be true,
jeśli chcemy sprawdzić wiele wyrażeń, możemy to zrobić na dwa sposoby:
za pomocą operatorów binarnych :
if (a && b) { } // will be true only if both a and b are true (binary operators are outside the scope here
if (a || b ) { } //true if a or b is true
używając if / ifelse / else :
dla prostego przełącznika albo if albo else
if (a== "test") {
//will execute if a is a string "test"
} else {
// only if the first failed, will execute
}
dla wielu opcji:
if (a=='a') {
// if a is a char valued 'a'
} else if (a=='b') {
// if a is a char valued 'b'
} else if (a=='c') {
// if a is a char valued 'c'
} else {
//if a is none of the above
}
należy jednak zauważyć, że zamiast tego należy użyć „ przełącznika ”, jeśli kod sprawdza wartość tej samej zmiennej
Instrukcje skoku: przerwa, kontynuacja, goto, wyjście.
Instrukcja przerwy:
Używając break możemy pozostawić pętlę, nawet jeśli warunek jej końca nie jest spełniony. Można go użyć do zakończenia nieskończonej pętli lub do wymuszenia jej zakończenia przed jej naturalnym końcem
Składnia jest następująca
break;
Przykład : często stosujemy break
w przypadkach switch
, tzn. Gdy spełniony jest warunek przełączenia przypadek i, wykonywany jest blok kodu tego warunku.
switch(conditon){
case 1: block1;
case 2: block2;
case 3: block3;
default: blockdefault;
}
w tym przypadku, jeśli przypadek 1 jest spełniony, wówczas wykonywany jest blok 1, tak naprawdę chcemy, aby przetwarzany był tylko blok 1, ale zamiast tego po przetworzeniu bloku 1 pozostałe bloki, blok2, blok3 i błąd domyślny są również przetwarzane, mimo że tylko przypadek 1 został spełniony Aby tego uniknąć, używamy break na końcu każdego bloku, takiego jak:
switch(condition){
case 1: block1;
break;
case 2: block2;
break;
case 3: block3;
break;
default: blockdefault;
break;
}
więc przetwarzany jest tylko jeden blok, a sterowanie wychodzi z pętli przełączającej.
break może być również użyty w innych pętlach warunkowych i bezwarunkowych, takich jak if
, while
, for
itp;
przykład:
if(condition1){
....
if(condition2){
.......
break;
}
...
}
Kontynuuj instrukcję:
Instrukcja kontynuacji powoduje, że program pomija resztę pętli w bieżącej iteracji, tak jakby osiągnięto koniec bloku instrukcji, powodując, że przeskakuje ona do następnej iteracji.
Składnia jest następująca
continue;
Przykład rozważ następujące kwestie:
for(int i=0;i<10;i++){
if(i%2==0)
continue;
cout<<"\n @"<<i;
}
co daje wynik:
@1
@3
@5
@7
@9
i ten kod jest przetwarzany za każdym razem, gdy warunek i%2==0
jest continue
, powoduje to, że kompilator pomija cały pozostały kod (drukowanie @ i i) i wykonywana jest instrukcja inkrementacji / dekrementacji pętli.
Instrukcja goto:
Pozwala na absolutny skok do innego punktu w programie. Tej funkcji należy używać ostrożnie, ponieważ jej wykonanie ignoruje wszelkie ograniczenia dotyczące zagnieżdżania. Punkt docelowy jest identyfikowany przez etykietę, która jest następnie używana jako argument dla instrukcji goto. Etykieta składa się z poprawnego identyfikatora, po którym następuje dwukropek (:)
Składnia jest następująca
goto label;
..
.
label: statement;
Uwaga: Używanie instrukcji goto jest wysoce odradzane, ponieważ utrudnia śledzenie przepływu kontrolnego programu, przez co program jest trudny do zrozumienia i trudny do modyfikacji.
Przykład:
int num = 1;
STEP:
do{
if( num%2==0 )
{
num = num + 1;
goto STEP;
}
cout << "value of num : " << num << endl;
num = num + 1;
}while( num < 10 );
wynik :
value of num : 1
value of num : 3
value of num : 5
value of num : 7
value of num : 9
za każdym razem, gdy warunek num%2==0
jest spełniony, goto wysyła kontrolę wykonania na początek pętli do-while
while.
Funkcja wyjścia:
exit
to funkcja zdefiniowana w cstdlib
. exit
ma na celu zakończenie działającego programu za pomocą określonego kodu wyjścia. Jego prototyp to:
void exit (int exit code);
cstdlib
definiuje standardowe kody wyjścia EXIT_SUCCESS
i EXIT_FAILURE
.