13.y — Używanie odniesienia do języka

W zależności od tego, na jakim etapie jesteś w nauce języków programowania (a konkretnie C++), LearnCpp.com może być jedynym źródłem, którego używasz do nauki C++ lub coś sprawdzić. LearnCpp.com ma na celu wyjaśnianie pojęć w sposób przyjazny dla początkujących, ale po prostu nie może omówić wszystkich aspektów języka. Gdy zaczniesz zgłębiać tematy wykraczające poza tematy omówione w tych samouczkach, nieuchronnie natkniesz się na pytania, na które te samouczki nie dają odpowiedzi. W takim przypadku będziesz musiał skorzystać z zasobów zewnętrznych.

Jednym z takich zasobów jest Stack Overflow, w którym możesz zadawać pytania (lub lepiej, przeczytać odpowiedź na to samo pytanie, które ktoś wcześniej zadał). Czasem jednak lepszym pierwszym przystankiem jest przewodnik informacyjny. W przeciwieństwie do tutoriali, które skupiają się na najważniejszych tematach i używają nieformalnego/wspólnego języka, aby ułatwić naukę, podręczniki opisują C++ precyzyjnie, używając formalnej terminologii. Z tego powodu materiały referencyjne są zwykle wyczerpujące, dokładne i… trudne do zrozumienia.

W tej lekcji pokażemy, jak używać cppreference, popularnego standardowego źródła, do którego odwołujemy się podczas lekcji, poprzez zapoznanie się z 3 przykładami.

Przegląd

Cppreference wita Cię przeglądem Podstawowy język i biblioteki:

przegląd preferencji cpp

Stąd możesz dostać się do wszystkiego, co cppreference ma do zaoferowania, ale łatwiej jest skorzystać z funkcji wyszukiwania lub wyszukiwarki. Przegląd to świetne miejsce do odwiedzenia po ukończeniu samouczków na LearnCpp.com, aby zagłębić się w biblioteki i zobaczyć, co jeszcze język ma do zaoferowania, o czym możesz nie wiedzieć.

Górna połowa tabeli pokazuje funkcje aktualnie dostępne w języku, podczas gdy dolna połowa pokazuje specyfikacje techniczne, czyli funkcje, które mogą, ale nie muszą zostać dodane do C++ w przyszłej wersji, lub które zostały już częściowo zaakceptowane w tym języku. Może to być przydatne, jeśli chcesz zobaczyć, jakie nowe możliwości zostaną wkrótce wprowadzone.

Począwszy od C++ 11, cppreference oznacza wszystkie funkcje standardową wersją językową, w której zostały dodane. Wersja standardowa to mała zielona liczba, którą możesz zobaczyć obok niektórych łączy na powyższym obrazku. Funkcje bez numeru wersji są dostępne od C++ 98/03. Numery wersji znajdują się nie tylko w przeglądzie, ale wszędzie w cpppreference, informując dokładnie, czego można, a czego nie można użyć w konkretnej wersji C++.

Ostrzeżenie

Jeśli korzystasz z wyszukiwarki, a specyfikacja techniczna została właśnie przyjęta do standardu, możesz zostać przekierowany do specyfikacji technicznej, a nie do oficjalnego odniesienia, które może się różnić.

Wskazówka

Cppreference jest odniesieniem zarówno dla C++, jak i C. Ponieważ C++ ma takie same nazwy funkcji jak C, możesz się znaleźć w referencji C po wyszukaniu czegoś. Adres URL i pasek nawigacyjny na górze cppreference zawsze pokazują, czy przeglądasz odwołanie do C lub C++.

std::string::length

Zaczniemy od sprawdzenia funkcji, którą znasz z poprzedniej lekcji, std::string::length, która zwraca długość łańcucha.

W prawym górnym rogu cppreference wyszukaj „string”. Spowoduje to wyświetlenie długiej listy typów i funkcji, z których w tej chwili istotna jest tylko górna część.

string search

Mogliśmy od razu wyszukać „długość łańcucha”, ale aby pokazać jak najwięcej w tej lekcji, wybierzemy dłuższą drogę. Kliknięcie „Biblioteka ciągów” przenosi nas do strony opisującej różne rodzaje ciągów znaków obsługiwanych przez C++.

Strona biblioteki strings

Jeśli zajrzymy do sekcji „std::basic_string”, zobaczymy listę typedefs, a na tej liście znajduje się std::string.

Kliknięcie „std::string” prowadzi do strony dla std::basic_string. Nie ma strony dla std::string, ponieważ std::string jest typedef for std::basic_string<char>, co ponownie można zobaczyć na liście typedef :

typedef

Klasa <char> oznacza, że ​​każdy znak ciągu jest typu char. Zauważysz, że C++ oferuje inne ciągi znaków, które używają różnych typów znaków. Mogą one być przydatne, gdy używasz Unicode zamiast ASCII.

W dalszej części tej samej strony znajduje się lista funkcji składowych (zachowań charakterystycznych dla typu). Jeśli chcesz wiedzieć, co możesz zrobić z typem, ta lista jest bardzo wygodna. Na tej liście znajdziesz wiersz dla length (oraz size).

Podążanie za linkiem prowadzi nas do szczegółowego opisu funkcji length i size, które robią to samo.

Góra każdej strony zaczyna się od krótkiego podsumowania funkcji i składni, przeciążeń lub deklaracji:

Przeciążenia długości stringów

Tytuł strony pokazuje nazwę klasy i funkcji ze wszystkimi parametrami szablonu. Tę część możemy pominąć. Poniżej tytułu widzimy wszystkie różne przeciążenia funkcji (różne wersje funkcji o tej samej nazwie) i standard językowy, do którego się odnoszą.

Poniżej możemy zobaczyć parametry pobierane przez funkcję i znaczenie zwracanej wartości.

Ponieważ std::string::length to prosta funkcja, na tej stronie nie ma zbyt wiele treści. Wiele stron pokazuje przykładowe zastosowania dokumentowanej przez nich funkcji, podobnie jak ta:

Przykład długości stringu

Gdy będziesz jeszcze uczyć się C++, w przykładach pojawią się funkcje, których nie widziałeś wcześniej. Jeśli jest wystarczająco dużo przykładów, prawdopodobnie jesteś w stanie zrozumieć ich wystarczającą ilość, aby mieć pojęcie o tym, jak używana jest dana funkcja i co robi. Jeśli przykład jest zbyt skomplikowany, możesz poszukać przykładu gdzie indziej lub przeczytać odniesienia do części, których nie rozumiesz (możesz kliknąć funkcje i typy w przykładach, aby zobaczyć, co robią).

Teraz wiemy, co std::string::length robi, ale wiedzieliśmy to wcześniej. Rzućmy okiem na coś nowego!

std::cin.ignore

W lekcji 9.5 — std::cin i obsługa nieprawidłowych danych wejściowych, o którym mówiliśmy std::cin.ignore, który służy do ignorowania wszystkiego aż do końca wiersza. Jednym z parametrów tej funkcji jest długa i pełna wartość. Co to było znowu? Nie możesz po prostu użyć dużej liczby? Co w ogóle daje ten argument? Rozwiążmy to!

Wpisanie „std::cin.ignore” w wyszukiwaniu cppreference daje następujące wyniki:

Wyniki wyszukiwarki
  • std::cin, std::wcin - Chcemy .ignore, a nie zwykły std::cin.
  • std::basic_istream<CharT,Traits>::ignore - Ej, co to jest? Pomińmy na razie.
  • std::ignore - Nie, to nie to.
  • std::basic_istream - To też nie to.

Nie ma tego, co teraz? Przejdźmy do std::cin i stamtąd ruszajmy dalej. Na tej stronie nie ma nic od razu oczywistego. Na górze możemy zobaczyć deklarację std::cin i std::wcin, która mówi nam, który nagłówek musimy dołączyć, aby użyć std::cin:

Declaration

Widzimy, że std::cin jest obiektem typu std::istream. Przejdźmy do linku do std::istream:

basic_istream

Trzymaj się! Widzieliśmy to std::basic_istream wcześniej, gdy szukaliśmy „std::cin.ignore” w naszej wyszukiwarce. Okazuje się, że istream jest nazwą typedef dla basic_istream, więc może jednak nasze wyszukiwanie nie było takie złe.

Przewijając tę ​​stronę, witają nas znajome funkcje:

Funkcje członkowskie

Użyliśmy już wielu z tych funkcji: operator>>, get, getline, ignore. Przewiń tę stronę, aby dowiedzieć się, co jeszcze znajduje się w std::cin. Następnie kliknij ignore, bo to nas interesuje.

ignore

Na górze strony znajduje się sygnatura funkcji oraz opis działania funkcji i jej dwóch parametrów. Znaki = po parametrach wskazują a argument domyślny (omówiliśmy to w lekcji 11.5 -- Domyślne argumenty). Jeśli nie podamy argumentu dla parametru, który ma wartość domyślną, zostanie użyta wartość domyślna.

Pierwszy punktor odpowiada na wszystkie nasze pytania. Widzimy, że std::numeric_limits<std::streamsize>::max() ma specjalne znaczenie dla std::cin.ignore, ponieważ wyłącza sprawdzanie liczby znaków. Oznacza to std::cin.ignore będzie ignorował znaki, dopóki nie znajdzie separatora lub nie zabraknie znaków do sprawdzenia.

W wielu przypadkach nie musisz czytać całego opisu funkcji, jeśli już go znasz, ale zapomniałeś, co oznaczają parametry lub zwracana wartość. W takich sytuacjach wystarczy przeczytać opis parametru lub wartości zwracanej.

Parametry i wartość zwracana

Opis parametru jest krótki. Nie zawiera specjalnej obsługi std::numeric_limits<std::streamsize>::max() ani innych warunków zatrzymania, ale służy jako dobre przypomnienie.

Przykład gramatyki języka

Oprócz biblioteki standardowej, cppreference dokumentuje również gramatykę języka. Oto poprawny program:

#include <iostream>

int getUserInput()
{
  int i{};
  std::cin >> i;
  return i;
}

int main()
{
  std::cout << "How many bananas did you eat today? \n";

  if (int iBananasEaten{ getUserInput() }; iBananasEaten <= 2)
  {
    std::cout << "Yummy\n";
  }
  else
  {
    std::cout << iBananasEaten << " is a lot!\n";
  }

  return 0;  
}

Dlaczego w warunku if-statement znajduje się definicja zmiennej? Użyjmy cppreference, aby dowiedzieć się, co robi, wyszukując „wyrażenie cppreference if” w naszej ulubionej wyszukiwarce. Takie postępowanie prowadzi nas do instrukcje if. Na górze znajduje się opis składni.

Przyjrzyj się składni if-statement. Jeśli usuniesz wszystkie opcjonalne części, otrzymasz if-statement który już znasz. Przed condition znajduje się opcjonalny init-statement, który wygląda tak, jak w powyższym kodzie.

if ( init-statement condition ) statement-true
if ( init-statement condition ) statement-true else statement-false

Poniżej opisu składni znajduje się wyjaśnienie każdej części składni, w tym init-statement. Mówi, że init-statement jest zazwyczaj deklaracją zmiennej z inicjatorem.

Po składni znajduje się wyjaśnienie if-statements i proste przykłady:

Wyjaśnienie na przykładach

Wiemy już jak działa if-statements , a przykłady nie zawierają init-statement, więc przewijamy trochę w dół, aby znaleźć sekcję poświęconą do if-statements za pomocą inicjatorów:

Instrukcje if z inicjatorem

Najpierw pokazano, jak można zapisać init-statement bez faktycznego użycia init-statement. Teraz wiemy, co robi dany kod. Jest to zwykła deklaracja zmiennej, po prostu włączona do if-statement.

Następne zdanie jest interesujące, ponieważ pozwala nam wiedzieć, że nazwy z init-statement są dostępne w oba oświadczenia (statement-true i statement-false). Może to być zaskakujące, ponieważ w przeciwnym razie można by założyć, że zmienna jest dostępna tylko w statement-true.

Klasa init-statement przykładach użycia funkcji i typów, których jeszcze nie omówiliśmy. Nie musisz rozumieć wszystkiego, co widzisz, aby zrozumieć, jak działa init-statement . Pomińmy wszystko, co jest zbyt zagmatwane, dopóki nie znajdziemy czegoś, z czym możemy pracować:

// Iterators, we don't know them. Skip.
if (auto it = m.find(10); it != m.end()) { return it->second.size(); }

// [10], what's that? Skip.
if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }

// std::lock_guard, we don't know that, but it's some type. We know what types are!
if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; }

// This is easy, that's an int!
if (int s; int count = ReadBytesWithSignal(&s)) { publish(count); raise(s); }

// Whew, no thanks!
if (auto keywords = {"if", "for", "while"};
    std::any_of(keywords.begin(), keywords.end(),
                [&s](const char* kw) { return s == kw; })) {
  std::cerr << "Token must not be a keyword\n";
}

Najprostszym przykładem wydaje się być ten z int. Następnie zwracamy uwagę na średnik i pojawia się inna definicja, dziwna… Wróćmy do std::lock_guard przykładu.

if (std::lock_guard lock(mx); shared_flag)
{
  unsafe_ping();
  shared_flag = false;
}

Na podstawie tego stosunkowo łatwo jest zobaczyć, jak działa init-statement . Zdefiniuj zmienną (lock), następnie średnik i warunek. Dokładnie tak się stało w naszym przykładzie.

Ostrzeżenie dotyczące dokładności cppreference

Cppreference nie jest oficjalnym źródłem dokumentacji — jest to raczej wiki. Dzięki wiki każdy może dodawać i modyfikować treść — treść pochodzi od społeczności. Chociaż oznacza to, że ktoś może łatwo dodać błędne informacje, dezinformacja jest zazwyczaj szybko wychwytywana i usuwana, co sprawia, że cppreference jest wiarygodnym źródłem.

Jedynym oficjalnym źródłem C++ jest standard (bezpłatne wersje robocze na github), który jest dokumentem formalnym, którego nie można łatwo wykorzystać jako odniesienie.

Czas quizu

Pytanie nr 1

Co wypisze poniższy program? Nie uruchamiaj go, użyj odniesienia, aby dowiedzieć się, co erase robi.

#include <iostream>
#include <string>

int main()
{
  std::string str{ "The rice is cooking" };

  str.erase(4, 11);

  std::cout << str << '\n';

  return 0;
}

Wskazówka

Gdy znajdziesz erase w cppreference, możesz zignorować przeciążenia używające iteratorów.

Wskazówka

Indeksy w C++ zaczynają się od 0. Znak pod indeksem 0 w ciągu „House” to „H”, przy 1 to „o” i tak on.

Pokaż rozwiązanie

Pytanie nr 2

W poniższym kodzie zmodyfikuj str tak, aby jego wartość brzmiała „Wczoraj widziałem niebieski samochód”. bez powtarzania ciągu. Na przykład nie rób tego:

str = "I saw a blue car yesterday.";

Wystarczy wywołać tylko jedną funkcję, aby zamienić „czerwony” na „niebieski”.

#include <iostream>
#include <string>

int main()
{
  std::string str{ "I saw a red car yesterday." };  

  // ...

  std::cout << str << '\n'; // I saw a blue car yesterday.

  return 0;
}

Pokaż wskazówkę

Pokaż wskazówkę

Pokaż wskazówkę

Pokaż wskazówkę

Pokaż rozwiązanie

guest
Twój adres e-mail nie zostanie wyświetlony
Znalazłeś błąd? Zostaw komentarz powyżej!
Komentarze związane z poprawkami zostaną usunięte po przetworzeniu, aby pomóc zmniejszyć bałagan. Dziękujemy za pomoc w ulepszaniu witryny dla wszystkich!
Awatary z https://gravatar.com/ są połączone z podanym adresem e-mail.
Powiadamiaj mnie o odpowiedziach:  
171 Komentarze
Najnowsze
Najstarsze Najczęściej głosowane
Wbudowane opinie
Wyświetl wszystkie komentarze