├── .github
└── workflows
│ └── action.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs
├── .vuepress
│ ├── assets
│ │ ├── codeblocks.png
│ │ ├── compilador_pt1.png
│ │ ├── compilador_pt2.png
│ │ ├── falcon.jpg
│ │ ├── falcon_pt1.png
│ │ ├── falcon_pt10.png
│ │ ├── falcon_pt11.png
│ │ ├── falcon_pt12.png
│ │ ├── falcon_pt2.png
│ │ ├── falcon_pt3.png
│ │ ├── falcon_pt4.png
│ │ ├── falcon_pt5.png
│ │ ├── falcon_pt6.png
│ │ ├── falcon_pt7.png
│ │ ├── falcon_pt8.png
│ │ ├── falcon_pt9.png
│ │ ├── qt.png
│ │ ├── replit.png
│ │ ├── vetor_pt1.png
│ │ └── vetor_pt2.png
│ ├── config.js
│ └── public
│ │ └── images
│ │ ├── footer_4noobs.svg
│ │ └── he4rtlogo.png
├── README.md
└── tutorial
│ ├── README.md
│ ├── secao010.md
│ ├── secao011.md
│ ├── secao0111.md
│ ├── secao0112.md
│ ├── secao012.md
│ ├── secao013.md
│ ├── secao0131.md
│ ├── secao014.md
│ ├── secao015.md
│ ├── secao016.md
│ ├── secao0161.md
│ ├── secao017.md
│ ├── secao0171.md
│ ├── secao0172.md
│ ├── secao0173.md
│ ├── secao1.md
│ ├── secao11.md
│ ├── secao2.md
│ ├── secao3.md
│ ├── secao4.md
│ ├── secao5.md
│ ├── secao51.md
│ ├── secao52.md
│ ├── secao6.md
│ ├── secao61.md
│ ├── secao62.md
│ ├── secao7.md
│ ├── secao71.md
│ ├── secao72.md
│ ├── secao8.md
│ ├── secao81.md
│ ├── secao82.md
│ ├── secao83.md
│ ├── secao84.md
│ ├── secao85.md
│ ├── secao9.md
│ └── secao91.md
├── package.json
└── yarn.lock
/.github/workflows/action.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to GH-Pages
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 |
7 | jobs:
8 | build:
9 |
10 | runs-on: ubuntu-latest
11 |
12 | strategy:
13 | matrix:
14 | node-version: [12.x]
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v1
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 | - name: Install dependencies
23 | run: yarn
24 | - name: Run build
25 | run: yarn build
26 | - name: Deploy
27 | uses: JamesIves/github-pages-deploy-action@3.7.1
28 | with:
29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 | BRANCH: gh-pages
31 | FOLDER: docs/.vuepress/dist
32 | CLEAN: true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/node
2 | # Edit at https://www.gitignore.io/?templates=node
3 |
4 | ### Node ###
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | .vscode
14 | docs/.vuepress/dist
15 |
16 | # Diagnostic reports (https://nodejs.org/api/report.html)
17 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
18 |
19 | # Runtime data
20 | pids
21 | *.pid
22 | *.seed
23 | *.pid.lock
24 |
25 | # Directory for instrumented libs generated by jscoverage/JSCover
26 | lib-cov
27 |
28 | # Coverage directory used by tools like istanbul
29 | coverage
30 | *.lcov
31 |
32 | # nyc test coverage
33 | .nyc_output
34 |
35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
36 | .grunt
37 |
38 | # Bower dependency directory (https://bower.io/)
39 | bower_components
40 |
41 | # node-waf configuration
42 | .lock-wscript
43 |
44 | # Compiled binary addons (https://nodejs.org/api/addons.html)
45 | build/Release
46 |
47 | # Dependency directories
48 | node_modules/
49 | jspm_packages/
50 |
51 | # TypeScript v1 declaration files
52 | typings/
53 |
54 | # TypeScript cache
55 | *.tsbuildinfo
56 |
57 | # Optional npm cache directory
58 | .npm
59 |
60 | # Optional eslint cache
61 | .eslintcache
62 |
63 | # Optional REPL history
64 | .node_repl_history
65 |
66 | # Output of 'npm pack'
67 | *.tgz
68 |
69 | # Yarn Integrity file
70 | .yarn-integrity
71 |
72 | # dotenv environment variables file
73 | .env
74 | .env.test
75 |
76 | # parcel-bundler cache (https://parceljs.org/)
77 | .cache
78 |
79 | # next.js build output
80 | .next
81 |
82 | # nuxt.js build output
83 | .nuxt
84 |
85 | # vuepress build output
86 | .vuepress/dist
87 |
88 | # Serverless directories
89 | .serverless/
90 |
91 | # FuseBox cache
92 | .fusebox/
93 |
94 | # DynamoDB Local files
95 | .dynamodb/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Giovane Cardoso, Thiago Rezende
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Tutorial de C++ da He4rt Developers
9 |
10 |
11 |
12 |
13 | ## Conteúdo
14 |
15 | - **Para não precisar rodar o projeto localmente, pode acessar diretamente por** [aqui](https://novout.github.io/cpp4noobs/)
16 |
17 |
18 |
19 | ## Sobre o Projeto
20 |
21 | Produzido com a colaboração de integrantes da **He4rt Developers**, esse tutorial tem como objetivo principal apresentar e ensinar a linguagem de programação C++ de uma maneira fácil, descomplicada e acessível para todos.
22 |
23 | ### Desenvolvido Com
24 |
25 | - [NodeJS](https://nodejs.org)
26 | - [VuePress](https://vuepress.vuejs.org/)
27 |
28 |
29 |
30 | ## Iniciando
31 |
32 | Para fazer uma cópia e rodar o projeto localmente, siga estes passos.
33 |
34 | ### Pré-requisitos
35 |
36 | Os programas a seguir são necessários para estender, modificar e utilizar o projeto.
37 |
38 | - [NodeJS](https://nodejs.org)
39 | - [Yarn](https://yarnpkg.com)
40 |
41 | ### Instalação
42 |
43 | 1. Clone o repositorio
44 |
45 | ```sh
46 | git clone https://github.com/Novout/cpp4noobs.git
47 | ```
48 |
49 | 2. Instale as dependências
50 |
51 | ```sh
52 | yarn install
53 | ```
54 |
55 |
56 |
57 | ## Como Usar
58 |
59 | Para iniciar o servidor de desenvolvimento utilize o seguinte comando
60 |
61 | ```sh
62 | yarn dev
63 | ```
64 |
65 | Para realizar a build do projeto execute o seguinte comando
66 |
67 | ```sh
68 | yarn build
69 | ```
70 |
71 | ## Contribuidores
72 |
73 | [](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/0)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/1)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/2)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/3)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/4)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/5)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/6)[](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/7)
74 |
75 |
76 |
77 | ## Como Contribuir
78 |
79 | Contribuições fazem com que a comunidade open source seja um lugar incrível para aprender, inspirar e criar. Todas contribuições
80 | são **extremamente apreciadas**
81 |
82 | 1. Realize um Fork do projeto
83 | 2. Adicione o conteúdo (`git add -A`)
84 | 3. Crie um branch com a nova feature (`git checkout -b feature/featureBraba`)
85 | 4. Realize o Commit (`git commit -m 'adicionando conteudo brabo'`)
86 | 5. Realize o Push no Branch (`git push origin feature/featureBraba`)
87 | 6. Abra um Pull Request
88 |
89 |
90 |
91 | ## Licença
92 |
93 | Distribuido sobre a licença `MIT`. Leia o arquivo `LICENSE` para mais informações.
94 |
95 |
96 |
97 | ## Contato
98 |
99 | He4rt Developers - [@He4rt_Developers](https://twitter.com/He4rtDevs)
100 |
101 | Thiago Rezende - [@HorusHe4rt](https://twitter.com/HorusHe4rt) - bitrateti@gmail.com
102 |
103 | Giovane Cardoso - [@NovoutT](https://twitter.com/NovoutT) - novout@hotmail.com
104 |
105 | Link do Projeto: [https://github.com/Novout/He4rt-CPP-Tutorial](https://github.com/Novout/cpp4noobs)
106 |
107 | ## Base
108 |
109 | O tutorial tem como base os sites [LearnCPP](https://www.learncpp.com) e [cppreference](https://en.cppreference.com/w/).
110 |
--------------------------------------------------------------------------------
/docs/.vuepress/assets/codeblocks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/codeblocks.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/compilador_pt1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/compilador_pt1.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/compilador_pt2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/compilador_pt2.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon.jpg
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt1.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt10.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt11.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt12.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt2.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt3.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt4.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt5.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt6.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt7.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt8.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/falcon_pt9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/falcon_pt9.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/qt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/qt.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/replit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/replit.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/vetor_pt1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/vetor_pt1.png
--------------------------------------------------------------------------------
/docs/.vuepress/assets/vetor_pt2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/assets/vetor_pt2.png
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | base: "/cpp4noobs/",
3 | title: "Curso de CPP da He4rt Developers",
4 | theme: "yuu",
5 | description: "C++",
6 | themeConfig: {
7 | yuu: {
8 | defaultDarkTheme: true,
9 | defaultColorTheme: "purple",
10 | },
11 | nav: [
12 | { text: "Home", link: "/" },
13 | { text: "Tutorial", link: "/tutorial/" },
14 | { text: "He4rt", link: "https://twitter.com/He4rtDevs" }
15 | ],
16 | sidebar: {
17 | "/tutorial/": [
18 | "",
19 | "secao1",
20 | "secao11",
21 | "secao2",
22 | "secao3",
23 | "secao4",
24 | "secao5",
25 | "secao51",
26 | "secao52",
27 | "secao6",
28 | "secao61",
29 | "secao62",
30 | "secao7",
31 | "secao71",
32 | "secao72",
33 | "secao8",
34 | "secao81",
35 | "secao82",
36 | "secao83",
37 | "secao84",
38 | "secao85",
39 | "secao9",
40 | "secao91",
41 | "secao010",
42 | "secao011",
43 | "secao0111",
44 | "secao0112",
45 | "secao012",
46 | "secao013",
47 | "secao0131",
48 | "secao014",
49 | "secao015",
50 | "secao016",
51 | "secao0161",
52 | "secao017",
53 | "secao0171",
54 | "secao0172",
55 | "secao0173"
56 | ]
57 | }
58 | }
59 | };
60 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/footer_4noobs.svg:
--------------------------------------------------------------------------------
1 |
2 |
265 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/images/he4rtlogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Novout/cpp4noobs/edf0c6476cbd5daf29892422ea0b0ea3efc9156b/docs/.vuepress/public/images/he4rtlogo.png
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /images/footer_4noobs.svg
4 | actionText: Inicie Agora →
5 | actionLink: /tutorial/
6 | features:
7 | - title: Completo
8 | details: Nosso tutorial tem como objetivo oferecer desde o básico ao intermediário da linguagem C++
9 | - title: Didática
10 | details: Buscamos uma didática interativa e direta buscando uma curva de aprendizado exponencial.
11 | - title: Prática
12 | details: Temos vários exemplos em cada seção para estimular a criatividade do leitor e permitir aplicar os conceitos mostrados.
13 | footer: MIT Licensed | Copyright © 2019-present He4rt Developers
14 | ---
15 |
--------------------------------------------------------------------------------
/docs/tutorial/README.md:
--------------------------------------------------------------------------------
1 | # 0 - Bem-Vindo ao Tutorial!
2 |
3 | ```cpp{0}
4 | #include
5 |
6 | int main()
7 | {
8 | std::cout << "Neste curso voce ira aprender toda a base do CPP." << std::endl;
9 | }
10 | ```
11 |
12 | * O mínimo necessário é ter conhecimento sobre Lógica de Programação
13 |
14 | * Teremos tópicos totalmente opcionais com o objetivo de agregar maior conhecimento relacionado ao C++.
15 |
16 | * Como se trata de um curso apenas escrito, terá link's adicionais para te auxiliar no andamento do curso.
17 |
18 | * Qualquer dúvida ou reclamação,fale diretamente conosco! discord.io/He4rt
19 |
20 | ### Criadores do Curso
21 |
22 | * NovoutHe4rt - Giovane Cardoso
23 |
24 | * HorusHe4rt - Thiago Rezende
25 |
26 | * PoorlyDefinedBehaviour
27 |
--------------------------------------------------------------------------------
/docs/tutorial/secao010.md:
--------------------------------------------------------------------------------
1 | # 10 - Namespace
2 |
3 | Agora imagine uma situação que você possua duas funções em header com o mesmo nome. Esse tipo de abordagem não pode ser possível sem a utilização de espaço de nome(namespace).
4 |
5 | Um espaço para nome define uma área de código na qual todos os identificadores são garantidos como exclusivos. Por padrão, variáveis globais e funções normais são definidas no espaço para nome global. Apesar de não ser necessário, podemos acessá-lo manualmente, colocando `::` antes do nome da variável ou da função.
6 |
7 | `main.cpp`
8 |
9 | ```cpp{0}
10 | #include
11 |
12 | #include "a.hpp"
13 | #include "b.hpp"
14 |
15 | int A = 5;
16 |
17 | int soma(int a, int b)
18 | {
19 | return a + b;
20 | }
21 |
22 | int main(int, char**)
23 | {
24 | /* Usando :: antes da função soma para indicar que ela está no namespace global */
25 | std::cout << ::soma(1, 2);
26 | }
27 | ```
28 |
29 | `a.hpp`
30 |
31 | ```cpp{0}
32 | int soma(int a)
33 | {
34 | return (a + a);
35 | }
36 | ```
37 |
38 | `b.hpp`
39 |
40 | ```cpp{0}
41 | int soma(int a, int b, int c)
42 | {
43 | return (a + b + c);
44 | }
45 | ```
46 |
47 | A variável global `A` e a função `soma()` são definidas no espaço para nome global.
48 |
49 | No programa de exemplo acima que teve a colisão de nomenclatura, quando main.cpp # incluiu a.hpp e b.hpp, as duas versões de soma () foram incluídas no espaço de nomes global, motivo pelo qual a colisão de nomenclatura resultou.
50 |
51 | Para ajudar a evitar problemas nos quais dois trechos de código independentes têm colisões de nomes entre si quando usados juntos, o C++ nos permite declarar nossos próprios namespaces por meio da palavra-chave namespace. Qualquer coisa declarada dentro de um espaço para nome definido pelo usuário pertence a esse espaço para nome, não ao espaço para nome global.
52 |
53 | Aqui está um exemplo dos cabeçalhos no primeiro exemplo reescritos usando namespaces:
54 |
55 | `main.cpp`
56 |
57 | ```cpp{0}
58 | #include
59 |
60 | #include "a.hpp"
61 | #include "b.hpp"
62 |
63 | int A = 5;
64 |
65 | int soma(int a, int b)
66 | {
67 | return a + b;
68 | }
69 |
70 | int main(int, char**)
71 | {
72 | std::cout << soma(1, 2);
73 | }
74 | ```
75 |
76 | `a.hpp`
77 |
78 | ```cpp{0}
79 | namespace A
80 | {
81 |
82 | int soma(int a)
83 | {
84 | return (a + a);
85 | }
86 | }
87 | ```
88 |
89 | `b.hpp`
90 |
91 | ```cpp{0}
92 | namespace B
93 | {
94 | int soma(int a, int b, int c)
95 | {
96 | return (a + b + c);
97 | }
98 | }
99 | ```
100 |
101 | O que aconteceu foi que, quando tentamos chamar a função soma(), o compilador procurou no espaço de nomes global para ver se poderia encontrar uma definição de soma(). No entanto, como nenhuma das nossas funções soma() vive mais no espaço de nomes global, ele considerou a função soma() do escopo global!
102 |
103 | A primeira maneira de dizer ao compilador para procurar um identificador em um espaço de nome específico é usar o operador de resolução de escopo. Esse operador permite prefixar um nome de identificador com o espaço para nome que você deseja usar.
104 |
105 | ```cpp{0}
106 | #include
107 |
108 | #include "a.hpp"
109 | #include "b.hpp"
110 |
111 | int A = 5;
112 |
113 | int soma(int a, int b)
114 | {
115 | return a + b;
116 | }
117 |
118 | int main(int, char**)
119 | {
120 | std::cout << A::soma(4, 3) << '\n'; // soma que pertence ao namespace A
121 | std::cout << B::soma(4, 3, 6) << '\n'; // soma que pertence ao namespace B
122 | }
123 | ```
124 |
125 | Também podemos ter namespaces dentro de namespaces:
126 |
127 | ```cpp{0}
128 | #include
129 |
130 | namespace A
131 | {
132 | namespace B
133 | {
134 | auto soma = [](int a, int b) { return a + b; };
135 | }
136 | }
137 |
138 | int main(int, char**)
139 | {
140 | std::cout << A::B::soma(1,2);
141 | }
142 |
143 | ```
144 |
145 | Vale ressaltar que os namespaces em C++ não foram projetados como uma maneira de implementar uma hierarquia de informações - eles foram projetados principalmente como um mecanismo para evitar colisões de nomes. Como prova disso, observe que a totalidade da biblioteca de modelos padrão reside no espaço de nome singular `std::` . Algumas linguagens mais recentes (como C#) diferem do C++ nesse sentido.
146 |
147 | Em geral, evite aninhar espaços para nome, se possível, e existem poucas boas razões para aninhar neles com mais de 2 níveis de profundidade. No entanto, nas lições posteriores, veremos outros casos relacionados em que o operador de resolução do escopo precisa ser usado mais de uma vez.
148 |
--------------------------------------------------------------------------------
/docs/tutorial/secao011.md:
--------------------------------------------------------------------------------
1 | # 11 - Introdução a Ponteiros
2 |
3 | Na seção 5, vimos que uma variável é um nome para um espaço de memória que contem um valor. Quando nosso programa instancia uma variável, um endereço de memória livre é automaticamente interligado a variável, e qualquer valor que definimos para a variavel é armazenado nesse endereço de memória.
4 |
5 | Por exemplo:
6 |
7 | ```cpp{0}
8 | int x;
9 | ```
10 |
11 | Quando esta declaração é executada pela CPU, uma parte da memória da RAM será atribuida a variavel x. Por exemplo, digamos que a variável x tenha a localização de memória 140. Sempre que o programa vir a variável x em uma expressão ou instrução, ela saberá que deve procurar no local da memória 140 para obter o valor.
12 |
13 | O bom das variáveis é que não precisamos nos preocupar com o endereço de memória específico atribuído. Nós apenas nos referimos à variável por seu identificador dado, e o compilador traduz este nome para o endereço de memória apropriadamente designado.
14 |
15 | No entanto, essa abordagem tem algumas limitações, que discutiremos nesta e nas próximas lições.
16 |
17 | ## Operador de endereço - (&)
18 |
19 | O operador de endereço (&) nos permite ver qual endereço de memória esta atribuído a uma variável. Isso fica mais claro a diante:
20 |
21 | ```cpp{0}
22 | #include
23 |
24 | int main()
25 | {
26 | int x = 5;
27 | std::cout << x << '\n'; // exibe o valor da variavel x
28 | std::cout << &x << '\n'; // exibe o endereco de memória da variavel x
29 |
30 | return 0;
31 | }
32 | ```
33 |
34 | O programa acima imprimiu:
35 |
36 | ```
37 | 5
38 | 0027FEA0
39 | ```
40 |
41 | O endereço de uma variável nao é obrigado a ser o mesmo em todas as máquinas.
42 |
43 | ## Operador de de-referência - (\*)
44 |
45 | Obter o endereço de uma variável não é muito útil por si só.
46 |
47 | O operador de remoção de referência (\*) nos permite acessar o valor em um determinado endereço:
48 |
49 | ```cpp{0}
50 | #include
51 |
52 | int main()
53 | {
54 | int x = 5;
55 | std::cout << x << '\n'; // exibe o valor da variavel x
56 | std::cout << &x << '\n'; // exibe o endereco de memória da variavel x
57 | std::cout << *(&x) << '\n'; // exibe o valor presente no endereco de memória davariavel x
58 |
59 | return 0;
60 | }
61 | ```
62 |
63 | O programa acima imprimiu:
64 |
65 | ```
66 | 5
67 | 0027FEA0
68 | 5
69 | ```
70 |
71 | ## Ponteiros
72 |
73 | Com o operador de endereço e os operadores de referência, podemos falar sobre ponteiros. Um ponteiro é uma variável que contém um endereço de memória como seu valor.
74 |
75 | Os ponteiros costumam ser vistos como uma das partes mais confusas da linguagem C++, mas são surpreendentemente simples quando explicados corretamente.
76 |
77 | ### Declarando um ponteiro
78 |
79 | As variáveis de ponteiro são declaradas como variáveis normais, apenas com um asterisco entre o tipo de dados e o nome da variável. Note que este asterisco não é um operador de de-referência. Faz parte da sintaxe de declaração do ponteiro.
80 |
81 | ```cpp{0}
82 | int *iPtr; // um ponteiro para um valor de tipo int
83 | double *dPtr; // um ponteiro para um valor do tipo double
84 |
85 | int *iPtr4, *iPtr5; // declarar mais de um ponteiro em uma linha
86 | ```
87 |
88 | ### Definindo um valor para um ponteiro
89 |
90 | Como os ponteiros só contêm endereços, quando atribuímos um valor a um ponteiro, esse valor precisa ser um endereço. Uma das coisas mais comuns a fazer com ponteiros é que eles mantenham o endereço de uma variável diferente.
91 |
92 | Para obter o endereço de uma variável, usamos operador de endereço (&) que vimos anteriormente:
93 |
94 | ```cpp{0}
95 | int value = 5;
96 | int *ptr = &value; // inicializa ptr com o endereço de memória da variavel value
97 | ```
98 |
99 | Para demonstrar que ptr tem o mesmo endereço de memória de value use o codigo a seguir:
100 |
101 | ```cpp{0}
102 | #include
103 |
104 | int main()
105 | {
106 | int value = 5;
107 | int *ptr = &value; // inicializa ptr com o endereço de memória da variavel value
108 |
109 | std::cout << &value << '\n'; // exibe o edereco da variavel value
110 | std::cout << ptr << '\n'; // exibe o endereco que ptr esta armazenando
111 |
112 | return 0;
113 | }
114 | ```
115 |
116 | O programa acima imprimiu:
117 |
118 | ```
119 | 0012FF7C
120 | 0012FF7C
121 | ```
122 |
123 | ### De-referênciando ponteiros
124 |
125 | Quando temos uma variável de ponteiro apontando para algo, a outra coisa comum a fazer com ela é cancelar o ponteiro para obter o valor do que está apontando. Um ponteiro de-referênciado avalia o conteúdo do endereço para o qual está apontando.
126 |
127 | ```cpp{0}
128 | int value = 5;
129 | std::cout << &value; // exibe o endereco de value
130 | std::cout << value; // exibe o conteudo
131 |
132 | int *ptr = &value; // ptr aponta para value
133 | std::cout << ptr; // exibe o conteudo de ptr, que é o endereco de value
134 | std::cout << *ptr; // de-referência ptr, retornando o valor contido no endereco
135 | ```
136 |
137 | O programa acima imprimiu:
138 |
139 | ```
140 | 0012FF7C
141 | 5
142 | 0012FF7C
143 | 5
144 | ```
145 |
146 | ### Mais sobre ponteiros
147 |
148 | Essa sessão tem o objetivo de introduzir os ponteiros, por isso não houve nenhum conceito mais complexo envolvendo eles.
149 |
150 | As aplicações, casos de uso, vantagens e desvantagens da utilização de ponteiros são tratadas em sessões adiante.
151 |
--------------------------------------------------------------------------------
/docs/tutorial/secao0111.md:
--------------------------------------------------------------------------------
1 | # 11.1 - Referências
--------------------------------------------------------------------------------
/docs/tutorial/secao0112.md:
--------------------------------------------------------------------------------
1 | # 11.2 - Smart Pointers
2 |
3 | Na seção 11, vimos que um ponteiro é um tipo que pode conter um endereço de memória.
4 |
5 | Infelizmente quando se aprende ponteiros, a maioria dos cursos não mostra a forma correta de usá-los.
6 |
7 | Como vimos na seção 11, podemos alocar um espaço de memória usando a keyword new e sempre que à usamos,
8 | precisamos usar a keyword delete para liberar tal espaço de memória.
9 |
10 | ```cpp{0}
11 | #include
12 |
13 | int main()
14 | {
15 | /* Alocando 4 bytes de memória e salvando o endereço dessa memória na variável a */
16 | int *a = new int;
17 |
18 | /* De-referênciando o endereço que está salvo na variável a e atribuindo o valor 10 */
19 | *a = 10;
20 |
21 | /** De-referênciando o endereço que está salvo na variável a e,
22 | * mostrando o valor que está salvo nesse endereço
23 | */
24 | std::cout << *a << '\n; // 10
25 |
26 | /* Liberando a memória que foi alocada */
27 | delete a;
28 | }
29 | ```
30 |
31 | Existem casos onde essa é a forma correta de lidar com ponteiros, mas uma boa regra para se seguir é a seguinte:
32 |
33 | Nunca use new e delete, sempre que possível, use smart pointers.
34 |
35 | ## O problema
36 |
37 | Conforme a complexidade de um programa aumenta, memory leaks(Vazamentos de memória) começam a aparecer.
38 |
39 | O que é memory leak? Veja a seguinte situação:
40 |
41 | ```cpp{0}
42 | #include
43 |
44 | void memory_leak() {
45 | /* Alocando 4 bytes de memória e salvando o endereço dessa memória na variável a */
46 | int *a = new int;
47 |
48 | /* De-referênciando o endereço que está salvo na variável a e atribuindo o valor 10 */
49 | *a = 10;
50 |
51 | /** De-referênciando o endereço que está salvo na variável a e,
52 | * mostrando o valor que está salvo nesse endereço
53 | */
54 | std::cout << *a << '\n; // 10
55 |
56 | /**
57 | * Aqui deveriamos usar a keyword delete para liberar a memória que foi alocada.
58 | * Mas por algum motivo, esquecemos de fazer isso.
59 | * Assim que a variável a sair do escopo da função, não teremos mais como acessá-la,
60 | * sendo assim, não será possível liberar a memória.
61 | */
62 | }
63 |
64 | int main()
65 | {
66 | for(int i = 0; i < 1000; ++i){
67 | memory_leak();
68 | }
69 | }
70 | ```
71 |
72 | Isso é um memory leak, já percebeu que certos programas consumem mais e mais memória
73 | depois de certo tempo de execução? Esse pode ser um dos motivos.
74 |
75 | ## A solução
76 |
77 | Felizmente, existem soluções para que você nunca tenha que se preocupar com a liberação de memória alocada.
78 |
79 | Uma dessas soluções se chama Smart Pointers.
80 |
81 | O que são:
82 |
83 | Smart pointers são ponteiros, dentro de uma estrutura que é responsável por liberar a memória
84 | alocada assim que a variável sair do escopo.
85 |
86 | Quem são:
87 |
88 | std::unique_ptr
89 | std::shared_ptr
90 | std::weak_ptr
91 |
92 | Para usá-los precisamos incluir o header ``
93 |
94 | Usando std::unique_ptr
95 |
96 | Syntax para criar um std::unique_ptr
97 |
98 | Ao invés de usar new TIPO, chamamos a função std::make_unique\() para criar um ponteiro.
99 |
100 | ```cpp{0}
101 | #include
102 | #include
103 |
104 | void no_memory_leak()
105 | {
106 | /**
107 | * Da mesma forma que um ponteiro aloca 4 bytes de memória para o tipo int,
108 | * um unique_ptr também irá alocar 4 bytes.
109 | */
110 | std::unique_ptr a = std::make_unique();
111 |
112 | /** Embora smart pointers sejam estruturas por volta de um ponteiro, podemos tratá-los
113 | * como se fossem ponteiros normais, na maior parte dos casos.
114 | * Uma das diferenças é que não precisamos deletá-los, pois,
115 | * são deletados automaticamente assim que saem do escopo em que foram criados.
116 | */
117 | *a = 10;
118 |
119 | std::cout << *a << '\n'; // 10;
120 |
121 | /* Smart pointers não precisam ser deletados manualmente */
122 | }
123 |
124 | int main()
125 | {
126 | for(int i = 0; i < 1000; ++i){
127 | no_memory_leak();
128 | }
129 | }
130 | ```
131 |
132 | Usando std::shared_ptr
133 |
134 | Syntax para criar um std::shared_ptr
135 |
136 | Ao invés de usar new TIPO, chamamos a função std::make_shared\() para criar um ponteiro.
137 |
138 | ```cpp{0}
139 | #include
140 | #include
141 |
142 | void no_memory_leak()
143 | {
144 | /* Criando um std::shared_ptr do tipo float */
145 | std::shared_ptr a = std::shared();
146 |
147 | *a = 2.71828;
148 |
149 | std::cout << *a << '\n'; // 2.71828;
150 |
151 | /* Smart pointers não precisam ser deletados manualmente */
152 | }
153 |
154 | int main()
155 | {
156 | for(int i = 0; i < 1000; ++i){
157 | no_memory_leak();
158 | }
159 | }
160 | ```
161 |
162 | Usando std::weak_ptr
163 |
164 | Syntax para criar um std::weak_ptr
165 |
166 | Ao invés de usar new TIPO, chamamos a função std::make_weak\() para criar um ponteiro.
167 |
168 | ```cpp{0}
169 | #include
170 | #include
171 |
172 | void no_memory_leak(std::weak_ptr pointer)
173 | {
174 | /* Antes de de-referênciar um std::weak_ptr precisamos transforma-lo em um std::shared_ptr */
175 | std::cout << *std::shared_ptr(pointer) << '\n'; // 2.71828;
176 |
177 | /* Smart pointers não precisam ser deletados manualmente */
178 | }
179 |
180 | int main()
181 | {
182 | std::shared_ptr a = std::make_shared(2.71828);
183 |
184 | for (int i = 0; i < 1000; ++i)
185 | {
186 | no_memory_leak(a);
187 | }
188 | }
189 | ```
190 |
191 | # Diferença entre std::unique_ptr, std::shared_ptr e std::weak_ptr
192 |
193 | std::UNIQUE_ptr como o nome diz, é único.
194 |
195 | Um unique_ptr não pode ser copiado.
196 |
197 | ```cpp{0}
198 | #include
199 |
200 | int main()
201 | {
202 | /* Criando um unique_ptr do tipo int com o valor 10 */
203 | std::unique_ptr a = std::make_unique(10);
204 |
205 | std::unique_ptr b = a; // erro: call to deleted constructor of std::unique_ptr
206 | }
207 | ```
208 |
209 | Devemos usar unique_ptr quando sabemos que uma entidade irá pertencer somente, e somente a uma
210 | outra entidade.
211 |
212 | O unique_ptr é deletado assim que a entidade que o possui sair do escopo.
213 |
214 | std::SHARED_ptr como o nome diz, pode ser compartilhado.
215 |
216 | Ao contrário do unique_ptr, um shared_ptr pode ser copiado.
217 |
218 | ```cpp{0}
219 | #include
220 |
221 | int main()
222 | {
223 | /* Criando um shared_ptr do tipo float com o valor 1.30357 */
224 | std::shared_ptr a = std::make_shared(1.30357);
225 |
226 | std::shared_ptr b = a; // sem erros
227 | }
228 | ```
229 |
230 | Devemos usar shared_ptr quando sabemos que uma entidade irá pertencer a mais
231 | de uma entidade ao mesmo tempo.
232 |
233 | O shared_ptr é deletado assim que todas a entidades que o possuem sairem do escopo.
234 |
235 | std::WEAK_ptr
236 |
237 | Um weak_ptr funciona de forma parecida com o shared_ptr.
238 |
239 | ```cpp{0}
240 | #include
241 |
242 | int main()
243 | {
244 | /* Criando um shared_ptr do tipo int com o valor 10 */
245 | std::shared_ptr a = std::make_shared(10);
246 |
247 | /* Criando um weak_ptr que aponta pra um shared_ptr do tipo int */
248 | std::weak_ptr b = a;
249 |
250 | /* Copiando um weak_ptr */
251 | std::weak_ptr c = b;
252 |
253 | /* Transformando um weak_ptr em shared_ptr para poder de-referência-lo. */
254 | std::cout << *std::shared_ptr(c) << '\n';
255 | }
256 | ```
257 |
258 | Ao contrário do shared_ptr, um weak_ptr não implica que uma entidade possui um ponteiro,
259 | ele serve somente para o uso temporário de um shared_ptr, quando temos um algo que
260 | deve ser acessado somente se existir e não nos importamos se aquela entidade deixar de existir
261 | a qualquer momento.
262 |
--------------------------------------------------------------------------------
/docs/tutorial/secao012.md:
--------------------------------------------------------------------------------
1 | # 12 - Structs
2 |
3 | Uma struct é um tipo que pode conter zero ou mais variáveis que são alocadas de uma forma ordenada.
4 |
5 | O tamanho de uma struct depende do tamanho dos elementos que ela contem.
6 |
7 | Normalmente o tamanho será o tamanho do maior elemento em bytes \* o número de elementos.
8 |
9 | Usamos structs para agrupar valores ou para representar uma entidade.
10 |
11 | O tipo dos elementos que uma struct contem não precisam ser o mesmo.
12 |
13 | `struct NOME_DA_STRUCT { };`
14 |
15 | ```cpp{0}
16 | #include
17 | #include
18 |
19 | struct Pessoa {
20 | std::string nome;
21 | int idade;
22 | };
23 |
24 | int main()
25 | {
26 | /* Variáveis são declaradas da mesma forma que com tipos primitivos */
27 | Pessoa pessoa;
28 |
29 | /* Usamos . para acessar coisas que estão dentro de uma struct */
30 | pessoa.nome = "John doe";
31 | pessoa.idade = 30;
32 |
33 | std::cout << "A idade de " << pessoa.nome << " e " << pessoa.idade;
34 | }
35 | ```
36 |
37 | Structs podem conter funções, além de variáveis.
38 |
39 | ```cpp{0}
40 | #include
41 | #include
42 |
43 | struct Pessoa {
44 | std::string nome;
45 | int idade;
46 |
47 | void apresentar() {
48 | std::cout << "Meu nome e " << nome << " e tenho " << idade << " anos";
49 | }
50 | };
51 |
52 | int main()
53 | {
54 | Pessoa pessoa;
55 | pessoa.nome = "John doe";
56 | pessoa.idade = 30;
57 |
58 | pessoa.apresentar();
59 | }
60 | ```
61 |
62 | Structs possuem uma função especial que é chamada quando uma instância daquela struct é criada. Essa função é chamada de construtor, normalmente usada para dar valores para as variáveis que uma struct possui.
63 |
64 | O construtor é uma função normal, exceto pelo fato de que não tem um tipo de retorno e só deve ser chamada uma vez de maneira automática.
65 |
66 | Quando acessamos uma variável de uma struct, dentro dela mesmo, podemos usar `this` para deixar explicito que a quem tal variável pertence. Isso não é necessário na maioria dos casos, a não ser por preferência ou por um caso onde existe ambiguidade.
67 |
68 | ```cpp{0}
69 | #include
70 | #include
71 |
72 | struct Pessoa {
73 | std::string nome;
74 | int idade;
75 |
76 | /* O construtor não precisa de um tipo de retorno
77 | *
78 | * Usando this para deixar explicito que estamos copiando o valor das variáveis nome e idade
79 | * passadas nos construtor, para as variáveis nome e idade da instância da struct.
80 | **/
81 | Pessoa(std::string nome, int idade) {
82 | this->nome = nome;
83 | this->idade = idade;
84 | }
85 |
86 | void apresentar() {
87 | std::cout << "Meu nome e " << nome << " e tenho " << idade << " anos";
88 | }
89 | };
90 |
91 | int main()
92 | {
93 | Pessoa pessoa("John Doe", 30);
94 |
95 | pessoa.apresentar();
96 | }
97 | ```
98 |
99 | Caso nenhum construtor seja declarado, o compilador irá criar um construtor vazio.
100 |
101 | Por exemplo:
102 |
103 | ```cpp{0}
104 | #include
105 | #include
106 |
107 | struct Pessoa {
108 | std::string nome;
109 | int idade;
110 |
111 | /* Criado pelo compilador */
112 | Pessoa() {}
113 |
114 | void apresentar() {
115 | std::cout << "Meu nome e " << nome << " e tenho " << idade << " anos";
116 | }
117 | };
118 |
119 | int main()
120 | {
121 | Pessoa pessoa;
122 | }
123 | ```
124 |
125 | Podemos ter mais de um construtor, com cada um deles fazendo uma coisa diferente.
126 |
127 | ```cpp{0}
128 | #include
129 | #include
130 |
131 | struct Pessoa {
132 | std::string nome;
133 | int idade;
134 |
135 | /* Primeiro */
136 | Pessoa(std::string nome, int idade) {
137 | this->nome = nome;
138 | this->idade = idade;
139 | }
140 |
141 | /* Segundo */
142 | Pessoa(std::string nome) {
143 | this->nome = nome;
144 | this->idade = -1 // Vamos considerar -1 como desconhecido
145 | }
146 |
147 | /* Terceiro */
148 | Pessoa(int idade) {
149 | this->nome = "desconhecido";
150 | this->idade = idade;
151 | }
152 |
153 | void apresentar() {
154 | std::cout << "Meu nome e " << nome << " e tenho " << idade << " anos";
155 | }
156 | };
157 |
158 | int main()
159 | {
160 | Pessoa pessoa("John Doe", 30); // Chama o primeiro construtor
161 |
162 | Pessoa pessoa("John Doe"); // Chama o segundo construtor
163 |
164 | Pessoa pessoa(30); // Chama o terceiro construtor
165 | }
166 | ```
167 |
--------------------------------------------------------------------------------
/docs/tutorial/secao013.md:
--------------------------------------------------------------------------------
1 | # 13 - Templates
2 |
3 | Nos capítulos anteriores, você aprendeu a escrever funções que ajudam a tornar os programas mais fáceis de escrever, mais seguros e mais fáceis de manter. Embora funções sejam ferramentas poderosas e flexíveis para uma programação eficaz, em certos casos, elas também podem ser um pouco limitantes devido ao requisito do C++ de que você especifique o tipo de todos os parâmetros.
4 |
5 | Por exemplo, digamos que você queira escrever uma função para calcular a multiplicação de dois números. Você pode fazer assim:
6 |
7 | ```cpp{0}
8 | #include
9 |
10 | int multiplicacao(int a, int b)
11 | {
12 | return (a * b);
13 | }
14 |
15 | int main(int, char**)
16 | {
17 | std::cout << multiplicacao(2, 4) << std::endl;
18 | }
19 | ```
20 |
21 | Essa função funcionaria muito bem - para números inteiros. O que acontece depois quando você percebe que sua função max () precisa trabalhar com duplas? Tradicionalmente, a resposta seria sobrecarregar a função multiplicacao() e criar uma nova versão que funcione com duplos:
22 |
23 | ```cpp{0}
24 | double multiplicacao(double a, double b)
25 | {
26 | return (a * b);
27 | }
28 | ```
29 |
30 | Observe que o código para a implementação da versão double de multiplicação() é exatamente o mesmo da versão int de multiplicação().De fato, essa implementação funcionaria para todos os tipos de tipos diferentes: caracteres, entradas, double's, etc.No entanto, como o C++ exige que você faça tipos específicos de suas variáveis, você fica impedido de escrever uma função para cada tipo que deseja usar.
31 |
32 | Ter que especificar diferentes tipos da mesma função em que a única coisa que muda é o tipo dos parâmetros pode se tornar uma dor de cabeça de manutenção e perda de tempo, além de violar as diretrizes gerais de programação de que o código duplicado deve ser minimizado tanto quanto possível. Não seria legal se pudéssemos escrever uma versão do multiplicação () capaz de trabalhar com parâmetros de QUALQUER tipo?
33 |
34 | Bem-vindo ao mundo dos `templates`.
35 |
36 | O que é um template de função?
37 |
38 | Se você procurar a palavra modelo(template) no dicionário, encontrará uma definição semelhante à seguinte: "um modelo é um modelo que serve como padrão para criar objetos semelhantes". Um tipo de modelo muito fácil de entender é o de um estêncil. Um estêncil é um objeto (por exemplo, um pedaço de papelão) com uma forma recortada (por exemplo, a letra J). Ao colocar o estêncil em cima de outro objeto e depois pintar com tinta pelo buraco, você pode produzir rapidamente padrões estampados em muitas cores diferentes! Observe que você só precisa criar um determinado estêncil uma vez - você pode usá-lo quantas vezes quiser, para criar padrões estampados nas cores que desejar. Melhor ainda, você não precisa decidir a cor do padrão estampado que deseja criar até decidir usar o estêncil.
39 |
40 | No C++, modelos de função são funções que servem como padrão para criar outras funções semelhantes. A idéia básica por trás dos modelos de função é criar uma função sem precisar especificar o (s) tipo (s) exato (s) de algumas ou de todas as variáveis. Em vez disso, definimos a função usando tipos de espaço reservado, chamados parâmetros de tipo de modelo. Depois que criamos uma função usando esses tipos de espaços reservados, criamos efetivamente um “estêncil de função”.
41 |
42 | Quando você chama uma função de modelo, o compilador “imprime” uma cópia do modelo, substituindo os tipos de espaços reservados pelos tipos de variáveis reais dos parâmetros em sua chamada de função! Usando essa metodologia, o compilador pode criar vários "sabores" de uma função a partir de um modelo! Vamos dar uma olhada neste processo em mais detalhes na próxima lição.
43 |
44 | Criando modelos de função em C++
45 |
46 | Neste ponto, você provavelmente está se perguntando como criar templates de função em C++. Acontece que não é tão difícil.
47 |
48 | Vamos dar uma olhada na versão int de multiplicacao() novamente:
49 |
50 | ```cpp{0}
51 | int multiplicacao(int a, int b)
52 | {
53 | return (a * b);
54 | }
55 | ```
56 |
57 | Observe que existem três locais onde tipos específicos são usados: os parâmetros x, y e o valor de retorno especificam que eles devem ser números inteiros. Para criar um modelo de função, substituiremos esses tipos específicos por tipos de espaço reservado. Nesse caso, como temos apenas um tipo que precisa ser substituído (int), precisamos apenas de um parâmetro de tipo de modelo.
58 |
59 | Você pode nomear seus tipos de marcadores como quase qualquer coisa que desejar, desde que não seja uma palavra reservada. No entanto, em C++, é habitual nomear seus tipos de modelo com a letra T (abreviação de "Type").
60 |
61 | Aqui está nossa nova função com um tipo de espaço reservado:
62 |
63 | ```cpp{0}
64 | T multiplicacao(T a, T b)
65 | {
66 | return (a * b);
67 | }
68 | ```
69 |
70 | Este é um bom começo - no entanto, não será compilado porque o compilador não sabe o que é "T"!
71 |
72 | Para fazer isso funcionar, precisamos dizer ao compilador duas coisas: primeiro, que essa é uma definição de modelo e, segundo, que T é um tipo de espaço reservado. Podemos fazer as duas coisas em uma linha, usando o que é chamado de declaração de parâmetro de modelo:
73 |
74 |
75 | ```cpp{0}
76 |
77 | template
78 | T multiplicacao(T a, T b)
79 | {
80 | return (a * b);
81 | }
82 | ```
83 |
84 | Acredite ou não, é tudo o que precisamos. Isso irá compilar!
85 |
86 | Agora, vamos dar uma olhada um pouco mais de perto na declaração de parâmetro do modelo. Começamos com o modelo de palavra-chave - isso informa ao compilador que o que se segue será uma lista de parâmetros do modelo. Colocamos todos os nossos parâmetros dentro de colchetes angulares (<>). Para criar um parâmetro de tipo de modelo, use a palavra-chave typename ou classe. Não há diferença entre as duas palavras-chave nesse contexto; portanto, você deve usar as suas. Observe que, se você usar a palavra-chave class, o tipo passado não precisará ser uma classe (pode ser uma variável fundamental, ponteiro ou qualquer outra coisa que corresponda). Então você nomeia seu tipo (geralmente "T").
87 |
88 | Se a função de modelo usar vários parâmetros de tipo de modelo, eles poderão ser separados por vírgulas:
89 |
90 | `template `
91 |
92 | Usando modelos de função
93 |
94 | O uso de um modelo de função é extremamente simples - você pode usá-lo como qualquer outra função. Aqui está um programa completo usando nossa função de modelo:
95 |
96 | ```cpp{0}
97 | #include
98 |
99 | template
100 | T maior(T a,T b) // Retornar o maior valor
101 | {
102 | return (a > b) ? a : b;
103 | }
104 |
105 | int main(int, char**)
106 | {
107 | int a = maior(3, 7); // Retorna 7
108 | std::cout << a << std::endl;
109 |
110 | double b = maior(6.34, 25.001); // returns 25.001
111 | std::cout << b << std::endl;
112 |
113 | char c = maior('a', '6'); // retorna 'a'
114 | std::cout << c << std::endl;
115 |
116 | return 0;
117 | }
118 | ```
119 |
120 | Como você pode ver, as funções de modelo podem economizar muito tempo, porque você só precisa escrever uma função e funcionará com muitos tipos diferentes. Depois de se acostumar a escrever modelos de funções, você descobrirá que eles não demoram mais para escrever do que funções com tipos reais. As funções de modelo reduzem a manutenção do código, porque o código duplicado é reduzido significativamente. E, finalmente, as funções de modelo podem ser mais seguras, porque não há necessidade de copiar funções e alterar tipos manualmente sempre que você precisar que a função funcione com um novo tipo!
121 |
122 | As funções de modelo têm algumas desvantagens, e seríamos negligentes em não mencioná-las. Primeiro, alguns compiladores mais antigos não têm muito bom suporte a modelos. No entanto, essa desvantagem não é mais o problema que costumava ser. Segundo, as funções de modelo geralmente produzem mensagens de erro de aparência maluca que são muito mais difíceis de decifrar do que as das funções regulares (veremos um exemplo disso na próxima lição). Terceiro, as funções de modelo podem aumentar o tempo de compilação e o tamanho do código, pois um único modelo pode ser “realizado” e recompilado em muitos arquivos (existem maneiras de solucionar esse problema).
123 |
124 | No entanto, essas desvantagens são relativamente pequenas em comparação com os modelos de poder e flexibilidade que você traz ao seu kit de ferramentas de programação!
125 |
--------------------------------------------------------------------------------
/docs/tutorial/secao0131.md:
--------------------------------------------------------------------------------
1 | # 13.1 - Instâncias de Modelo de Função
2 |
3 | Vamos dar uma olhada rápida por funções de modelo e como implementá-las em C++.
4 |
5 | Acontece que o C ++ não compila diretamente a função de modelo. Em vez disso, no momento da compilação, quando o compilador encontra uma chamada para uma função de modelo, ele replica a função de modelo e substitui os parâmetros de tipo de modelo por tipos reais. A função com tipos reais é chamada de instância de modelo de função.
6 |
7 | Vamos dar uma olhada em um exemplo desse processo. Primeiro, temos uma função de modelo:
8 |
9 | ```cpp{0}
10 | template // Declaração do template
11 | const T& max(const T& foo, const T& bar) // Argumentos
12 | {
13 | return (foo > bar) ? foo : bar; // ternário retornando o maior valor
14 | }
15 | ```
16 |
17 | Ao compilar seu programa, o compilador encontra uma chamada para a função de modelo:
18 |
19 | ```cpp{1}
20 | int i = max(2, 10); // calls max(int, int)
21 | ```
22 |
23 | O compilador chama max(int, int) e replica o modelo da função e cria a instância do modelo max (int, int):
24 |
25 | ```cpp{0}
26 | const int& max(const int &foo, const int &bar)
27 | {
28 | return (foo > bar) ? foo : bar;
29 | }
30 | ```
31 |
32 | Ele irá identificar o tipo de retorno e dos parâmetros para criar a função
33 |
34 | # Operadores, chamadas de função e modelos de função
35 |
36 | As funções de modelo funcionarão com os tipos internos (por exemplo, char, int, double, etc ...) e classes, com uma ressalva. Quando o compilador compila a instância do modelo, ele a compila exatamente como uma função normal. Em uma função normal, todos os operadores ou chamadas de função que você usa com seus tipos devem ser definidos ou você receberá um erro do compilador. Da mesma forma, quaisquer operadores ou chamadas de função na função de modelo devem ser definidos para quaisquer tipos para os quais o modelo de função é instanciado. Vamos dar uma olhada nisso com mais detalhes.
37 |
38 | Olhe o seguinte exemplo:
39 |
40 | ```cpp{0}
41 | #include
42 | #include
43 | #include
44 |
45 | template // Declaração do template
46 | const T& maior(const T& foo, const T& bar) // Argumentos
47 | {
48 | return (foo > bar) ? foo : bar; // ternário retornando o maior valor
49 | }
50 |
51 | struct Funcionario
52 | {
53 | std::string m_nome;
54 | int m_idade;
55 |
56 | Funcionario(std::string nNome, int nIdade)
57 | {
58 | this->m_nome = nNome;
59 | this->m_idade = nIdade;
60 | }
61 | };
62 |
63 |
64 | int main()
65 | {
66 | Funcionario *funcionario1 = new Funcionario("Joao", 18);
67 | Funcionario *funcionario2 = new Funcionario("Jose", 23);
68 |
69 | Funcionario *maior_idade = maior(funcionario1, funcionario2);
70 |
71 | std::cout << maior_idade->m_idade;
72 |
73 | delete funcionario1;
74 | delete funcionario2;
75 | }
76 | ```
77 |
78 | Esse exemplo funciona, por se tratar de struct's, MAIS CUIDADO! Se for utilizar classes,você irá ter que fazer overload de operador para o template entender a comparação.
79 |
80 | Na seção de Orientação a Objetos, iremos deixar isso bem claro.
81 |
82 |
--------------------------------------------------------------------------------
/docs/tutorial/secao014.md:
--------------------------------------------------------------------------------
1 | # 14 - Stack e Heap
2 |
3 | A memória que um programa usa é normalmente dividida em algumas áreas diferentes, chamadas segmentos:
4 |
5 | - O segmento de código (também chamado de segmento de texto), onde o programa compilado fica na memória. O segmento de código normalmente é somente leitura.
6 | - O segmento bss (também chamado de segmento de dados não inicializado), onde variáveis globais e estáticas inicializadas com zero são armazenadas.
7 | - O segmento de dados (também chamado de segmento de dados inicializado), onde as variáveis globais e estáticas inicializadas são armazenadas.
8 | - O heap, de onde variáveis alocadas dinamicamente são alocadas.
9 | - A stack(pilha) de chamadas, onde são armazenados os parâmetros da função, variáveis locais e outras informações relacionadas à função.
10 | Nesta lição, focaremos principalmente a heap e a stack, pois é aí que a maioria das coisas interessantes ocorre.
11 |
12 | O segmento de heap (também conhecido como "armazenamento gratuito") controla a memória usada para alocação dinâmica de memória. Utilizamos ela na seção passada:
13 |
14 | ```cpp{0}
15 | int *ponteiro = new int; // ptr is assigned 4 bytes in the heap
16 | int *vetor = new int[10]; // array is assigned 40 bytes in the heap
17 |
18 | delete ponteiro;
19 | delete vetor;
20 | ```
21 |
22 | Quando uma variável alocada dinamicamente é excluída, a memória é "retornada" para o heap e pode ser reatribuída à medida que futuras solicitações de alocação forem recebidas. Lembre-se de que excluir um ponteiro não exclui a variável, apenas retorna a memória no endereço associado ao sistema operacional.
23 |
24 | A stack tem vantagens e desvantagens:
25 |
26 | - A alocação de memória no heap é comparativamente lenta.
27 | - A memória alocada permanece alocada até que seja desalocada especificamente (cuidado com vazamentos de memória) ou o aplicativo termina (nesse ponto, o SO deve limpá-la).
28 | - A memória alocada dinamicamente deve ser acessada por meio de um ponteiro. Desreferenciar um ponteiro é mais lento do que acessar diretamente uma variável.
29 | Como o heap é um grande pool de memória, matrizes, estruturas ou classes grandes podem ser alocadas aqui.
30 |
31 | # A stack de chamadas
32 |
33 | A stack de chamadas (geralmente chamada de "a pilha") tem um papel muito mais interessante a desempenhar. A pilha de chamadas controla todas as funções ativas (aquelas que foram chamadas, mas ainda não foram finalizadas) desde o início do programa até o ponto de execução atual e lida com a alocação de todos os parâmetros de função e variáveis locais.
34 |
35 | A pilha de chamadas é implementada como uma estrutura de dados da pilha. Portanto, antes de podermos falar sobre como a pilha de chamadas funciona, precisamos entender o que é uma estrutura de dados da pilha.
36 |
37 | Uma estrutura de dados é um mecanismo de programação para organizar dados, para que possam ser usados com eficiência. Você já viu vários tipos de estruturas de dados, como matrizes e estruturas. Ambas as estruturas de dados fornecem mecanismos para armazenar dados e acessar esses dados de maneira eficiente. Existem muitas estruturas de dados adicionais que são comumente usadas em programação, algumas das quais são implementadas na biblioteca padrão e uma pilha é uma delas.
38 |
39 | # Funcionamento de uma Pilha
40 |
41 | - Olhe para o item superior da pilha(geralmente feito através de uma função chamada top(), mas às vezes chamada de peek())
42 | - Retire o item principal da pilha(feito por meio de uma função chamada pop())
43 | - Coloque um novo item no topo da pilha(feito através de uma função chamada push())
44 |
45 | | Pilha | Saida |
46 | | ----- | ----- |
47 | | Stack | Vazia |
48 | | Push | 1 |
49 | | Stack | 1 |
50 | | Push | 2 |
51 | | Stack | 1 2 |
52 | | Push | 3 |
53 | | Stack | 1 2 3 |
54 | | Pop | |
55 | | Push | 1 2 |
56 | | Pop | |
57 | | Stack | 1 |
58 |
59 | # O segmento da stack de chamadas
60 |
61 | O segmento da pilha de chamadas mantém a memória usada para a pilha de chamadas. Quando a aplicação é iniciada, a função main () é pressionada na pilha de chamadas pelo sistema operacional. Então o programa começa a executar.
62 |
63 | Quando uma chamada de função é encontrada, a função é enviada para a pilha de chamadas. Quando a função atual termina, essa função é retirada da pilha de chamadas. Assim, observando as funções pressionadas na pilha de chamadas, podemos ver todas as funções que foram chamadas para chegar ao ponto de execução atual.
64 |
65 | Nossa analogia da caixa de correio acima é bastante semelhante à maneira como a pilha de chamadas funciona. A própria pilha é um pedaço de tamanho fixo de endereços de memória. As caixas de correio são endereços de memória e os "itens" que estamos empurrando e popping na pilha são chamados de quadros de pilha. Um quadro de pilha controla todos os dados associados a uma chamada de função. Falaremos mais sobre os quadros de pilha em breve. O "marcador" é um registro (um pequeno pedaço de memória na CPU) conhecido como ponteiro da pilha (às vezes abreviado como "SP"). O ponteiro da pilha controla onde está atualmente a parte superior da pilha de chamadas.
66 |
67 | A única diferença entre nossa pilha hipotética de caixa de correio e a pilha de chamadas é que, quando retiramos um item da pilha de chamadas, não precisamos apagar a memória (o equivalente a esvaziar a caixa de correio). Podemos apenas deixá-lo sobrescrito pelo próximo item enviado para esse pedaço de memória. Como o ponteiro da pilha estará abaixo desse local da memória, sabemos que o local da memória não está na pilha.
68 |
69 | # A pilha de chamadas em ação
70 |
71 | Vamos examinar mais detalhadamente como a pilha de chamadas funciona. Aqui está a sequência de etapas que ocorre quando uma função é chamada:
72 |
73 | - O programa encontra uma chamada de função.
74 | - Um quadro de pilha é construído e empurrado na pilha. O quadro da pilha consiste em:
75 | - O endereço da instrução além da chamada da função (chamado endereço de retorno). É assim que a CPU se lembra para onde retornar após a saída da função chamada.
76 | - Todos os argumentos da função.
77 | - Memória para quaisquer variáveis locais.
78 | - Cópias salvas de quaisquer registros modificados pela função que precisam ser restauradas quando a função retornar
79 | - A CPU pula para o ponto inicial da função.
80 | - As instruções dentro da função começam a ser executadas.
81 |
82 | Quando a função termina, ocorrem as seguintes etapas:
83 |
84 | - Os registros são restaurados da pilha de chamadas
85 | - O quadro da pilha é retirado da pilha. Isso libera a memória para todas as variáveis e argumentos locais.
86 | - O valor de retorno é tratado.
87 | - A CPU retoma a execução no endereço de retorno.
88 | - Os valores de retorno podem ser manipulados de várias maneiras diferentes, dependendo da arquitetura do computador. Algumas arquiteturas incluem o valor de retorno como parte do quadro da pilha. Outros usam registradores de CPU.
89 |
90 | Normalmente, não é importante conhecer todos os detalhes sobre como a pilha de chamadas funciona. No entanto, o entendimento de que as funções são efetivamente colocadas na pilha quando são chamadas e ativadas quando retornam fornece os fundamentos necessários para entender a recursão, além de alguns outros conceitos úteis na depuração.
91 |
92 | Uma observação técnica: em algumas arquiteturas, a pilha de chamadas cresce para longe do endereço de memória 0. Em outras, cresce para o endereço de memória 0. Como conseqüência, os novos quadros de pilha enviados podem ter um endereço de memória maior ou menor que os anteriores.
93 |
94 | Exemplo:
95 |
96 | ```cpp{0}
97 | int foo(int x)
98 | {
99 | // b
100 | return x;
101 | } // foo is popped off the call stack here
102 |
103 | int main()
104 | {
105 | // a
106 | foo(5); // a função foo foi chamada no push() para a pilha
107 | // c
108 |
109 | return 0;
110 | }
111 | ```
112 |
113 | Estouro de pilha(Não é piada com o site. juro.)
114 |
115 | A pilha tem um tamanho limitado e, consequentemente, pode conter apenas uma quantidade limitada de informações. No Windows, o tamanho padrão da pilha é de 1 MB. Em algumas máquinas unix, pode ter até 8 MB. Se o programa tentar colocar muitas informações na pilha, resultará um excesso de pilha. O estouro de pilha acontece quando toda a memória da pilha foi alocada - nesse caso, alocações adicionais começam a transbordar para outras seções da memória.
116 |
117 | O estouro de pilha geralmente é o resultado da alocação de muitas variáveis na pilha e / ou de muitas chamadas de funções aninhadas (onde a função A chama a função B chama a função C chama a função D etc ...) Nos sistemas operacionais modernos, o excesso da pilha geralmente faça com que seu sistema operacional emita uma violação de acesso e encerre o programa.
118 |
119 | Aqui está um exemplo de programa que provavelmente causará um estouro de pilha. Você pode executá-lo em seu sistema e assisti-lo travar:
120 |
121 | ```cpp{0}
122 | #include
123 |
124 | int main()
125 | {
126 | int stack[10000000];
127 | std::cout << "He4rt Developers" << std::endl;
128 | return 0;
129 | }
130 | ```
131 |
132 | A classe `std::vector` faz muito bem do uso da pilha, recomendado a se utilizar em vés do vetor normal, assim como a classe `std::array`
--------------------------------------------------------------------------------
/docs/tutorial/secao015.md:
--------------------------------------------------------------------------------
1 | # 15 - Auto Keyword
2 |
3 | A keyword `auto` pode ser usada em variáveis e funções.
4 |
5 | Uma variável declarada com auto possui tipo, e esse tipo é deduzido a partir do valor que é dado à ela.
6 |
7 | Para usar auto durante a declaração de uma variável, essa variável deve ser inicializada para que o tipo possa ser
8 | deduzido.
9 |
10 | ```cpp
11 | auto a = 10; // o tipo de a é int.
12 |
13 | auto b = (int)10; // o mesmo que o de cima, só que de forma explicita.
14 |
15 | auto c; // inválido pois o tipo de c não póde ser deduzido.
16 | ```
17 |
18 | Em funções com retorno do tipo auto, o tipo do retorno é deduzido através do valor retornado.
19 |
20 | ```cpp
21 | auto sum(int a, int b) { return a + b; } // auto é deduzido como int
22 |
23 | auto sum(int a, int b) -> int { return a + b + 3.14; } // forçando auto a ser deduzido como int
24 |
25 | auto sum(int a, int b) { return a + b + 3.14; } // auto é deduzido como double
26 | ```
27 |
28 | Podemos usar parâmetros do tipo `auto` em lambdas.
29 |
30 | ```cpp
31 | #include
32 | #include // std::iota e std::accumulate
33 | #include
34 |
35 | auto main() -> int
36 | {
37 | std::vector array(5);
38 | std::iota(array.begin(), array.end(), 1);
39 |
40 | auto const factorial = std::accumulate(
41 | array.begin(),
42 | array.end(),
43 | 1,
44 | [](auto accum, auto current) -> int { return accum * current; });
45 |
46 | std::cout << factorial; // 120
47 | }
48 | ```
49 |
50 | `auto` em loops
51 |
52 | ```cpp
53 | #include
54 | #include
55 | #include
56 |
57 | auto main() -> int
58 | {
59 | std::vector array(5);
60 | std::generate(array.begin(), array.end(), [i = 1]() mutable -> int { return i++; });
61 |
62 | for (auto element : array)
63 | {
64 | std::cout << element << '\n';
65 | }
66 | }
67 | ```
68 |
--------------------------------------------------------------------------------
/docs/tutorial/secao016.md:
--------------------------------------------------------------------------------
1 | # 16 - Big O Notation
2 |
3 | Big O Notation é uma forma de classificar algoritmos baseado na relação entre o tamanho de um input e o tempo que uma ação baseada nesse input leva para ser executada.
4 |
5 | Big O Notation não é exato, e o tempo que um algoritmo ou programa leva para ser executado, depende de vários fatores. Apesar disso, pode ser útil para entender por que algumas soluções são naturalmente mais lentas que outras, e para aproximar a performance de um algoritmo de forma rápida.
6 |
7 | # Tempo constante O(1)
8 |
9 | Dizemos que uma operação leva tempo constante quando independente do input, ela leva a mesma quantidade de tempo ou a diferença não é grande o suficiente para importar.
10 |
11 | ```cpp
12 | #include
13 | #include
14 | #include
15 |
16 | /* Testa se um número é par */
17 | bool is_even(int number)
18 | {
19 | return number % 2 == 0;
20 | }
21 |
22 | bool is_first_element_even(std::vector const& array)
23 | {
24 | return is_even(array[0]);
25 | }
26 |
27 | int main()
28 | {
29 | std::cout << std::boolalpha << is_even(2) << '\n'; // true
30 | std::cout << std::boolalpha << is_even(9) << '\n'; // false
31 | std::cout << std::boolalpha << is_even(1000000) << '\n'; // true
32 | std::cout << std::boolalpha << is_even(-482717) << '\n'; // false
33 | std::cout << std::boolalpha << is_even(33) << '\n'; // false
34 | // Descobrir se um número é par leva tempo constante
35 |
36 | std::vector array(100);
37 | std::iota(array.begin(), array.end(), 1);
38 | is_first_element_even(array);
39 |
40 | /*
41 | * Descobrir se o primeiro elemento do array é par leva tempo constante
42 | * já que a função não executa nenhuma operação relacionada com o tamanho do array.
43 | */
44 | }
45 | ```
46 |
47 | # Tempo logaritmico O(log n)
48 |
49 | Um exemplo de um algoritmo que leva O(log n) é binary search.
50 |
51 | ```cpp
52 | int binary_search(std::vector const &array, int start, int end, int element)
53 | {
54 | if (end >= start)
55 | {
56 | int mid = start + (end - start) / 2;
57 |
58 | if (array[mid] == element)
59 | return mid; // retorna a index caso o elemento seja encontrado
60 |
61 | if (array[mid] > element)
62 | return binary_search(array, start, mid - 1, element);
63 | /** Chama a função enquanto o elemento não for encontrado e
64 | * a condição parada não for atingida
65 | **/
66 |
67 | return binary_search(array, mid + 1, end, element);
68 | }
69 |
70 | return -1; // -1 caso não encontre o elemento
71 | }
72 | ```
73 |
74 | Esse algoritmo leva O(log n) por que a cada chamada da função binary_search, o campo de busca é cortado pela metade.
75 |
76 | # Tempo linear O(n)
77 |
78 | Em um algoritmo O(n) o tempo de execução aumenta de forma idêntica ao tamanho do input, ou seja, de forma linear.
79 |
80 | ```cpp
81 | #include
82 | #include
83 | #include
84 |
85 | /**
86 | * O tempo necessário para somar todos os elementos do array depende do tamanho do array.
87 | * Sendo assim, conforme o tamanho do array cresce,
88 | * o tempo de execução da função também cresce.
89 | * Por esse motivo, o tempo de execução de sum_elements() pode ser considerado O(n)
90 | */
91 | int sum_elements(std::vector const& array) {
92 | int sum = 0;
93 |
94 | for(int element: array){
95 | sum += element;
96 | }
97 |
98 | return sum;
99 | }
100 |
101 | int main()
102 | {
103 | std::vector array(100);
104 | std::iota(array.begin(), array.end(), 1); // prenche o array com 1, 2, 3...n
105 |
106 | std::cout << sum_elements(array); // soma todos elementos do array
107 | }
108 | ```
109 |
110 | # O(n log n)
111 |
112 | Um exemplo de algoritmo O(n log n) é o famoso quicksort, usado para ordenar vetores.
113 |
114 | ```cpp
115 | #include // pra poder usar std::swap
116 |
117 | void quicksort(std::vector& array, int start, int end)
118 | {
119 | if (start >= end)
120 | return;
121 |
122 | int pivot_index = start;
123 | int const pivot_value = array[end];
124 |
125 | for (int i = start; i < end; ++i)
126 | {
127 | if (array[i] < pivotValue)
128 | {
129 | std::swap(array[i], array[pivot_index]);
130 | ++pivot_index;
131 | }
132 | }
133 |
134 | std::swap(array[pivot_index], array[end]);
135 |
136 | quicksort(array, start, pivot_index - 1, fn);
137 | quicksort(array, pivot_index + 1, end, fn);
138 | }
139 | ```
140 |
141 | O(n log n) é o tempo médio que um quicksort leva, mas isso não é uma regra,
142 | um quicksort pode levar O(n²) no pior dos casos e O(n) no melhor.
143 |
144 | # Tempo quadrático O(n²)
145 |
146 | Em um algoritmo O(n²) o tempo de execução aumenta de forma quadrática.
147 |
148 | ```cpp
149 | #include
150 | #include
151 |
152 | int main()
153 | {
154 | std::array, 5> matrix; // matrix 5x5
155 |
156 | /* Prenchendo a matriz */
157 | for(int i = 0; i < 5; ++i){
158 | for(int j = 0; j < 5; ++j){
159 | matrix[i][j] = i + j;
160 | }
161 | }
162 | }
163 | ```
164 |
165 | Uma matriz de 5 linhas e 5 colunas precisa de dois loops para prenche-la, o loop interior roda 5 vezes para cada vez que o exterior roda, logo, o tempo que leva para prencher uma matriz 5x5 é 5 \* 5 ou 5². Podemos assumir que o tempo que levaria para prencher uma matriz 10x10 seria 10², uma matriz 100x100 100², resumindo, o tempo que leva para preencher uma matriz é O(n²)
166 |
167 | Um algoritmo pode ser O(n³), O(n⁴), O(n⁵), etc.
168 |
169 | Big O Notation não para por aqui, isso foi apenas uma introdução.
170 |
171 | Alguns que não foram mencionados: O(n^c), O(c^n), O(n^n), O(n!)
172 |
--------------------------------------------------------------------------------
/docs/tutorial/secao0161.md:
--------------------------------------------------------------------------------
1 | # 16.1 - Sorting
2 |
--------------------------------------------------------------------------------
/docs/tutorial/secao017.md:
--------------------------------------------------------------------------------
1 | # 17 - Orientação a Objetos (OOP)
2 |
3 | Como vimos até agora, na programação tradicional (o que estamos fazendo antes deste ponto), os programas são basicamente listas de instruções para o computador que definem dados (por meio de objetos) e depois trabalham com esses dados (por meio de instruções e funções). Os dados e as funções que trabalham nesses dados são entidades separadas que são combinadas para produzir o resultado desejado. Devido a essa separação, a programação tradicional geralmente não fornece uma representação muito intuitiva da realidade. Cabe ao programador gerenciar e conectar as propriedades (variáveis) aos comportamentos (funções) de maneira adequada. Isso leva ao código que se parece com isso:
4 |
5 | ```cpp{0}
6 | vaAte(voce, casa);
7 | ```
8 |
9 | Então, o que é programação orientada a objetos? Tal como acontece com muitas coisas, talvez seja entendido mais facilmente através do uso de uma analogia. Dê uma olhada ao seu redor, em todos os lugares que você olha são objetos: livros, prédios, comida e até você. Os objetos têm dois componentes principais:
10 | - Uma lista de propriedades relevantes (por exemplo, peso, cor, tamanho, solidez, forma, etc)
11 | - Algum número de comportamentos que eles podem exibir (por exemplo, serem abertos, fazer outra coisa, quente, etc)
12 | - Essas propriedades e comportamentos são inseparáveis
13 |
14 | A programação orientada a objetos (OOP) fornece a capacidade de criar objetos que unem propriedades e comportamentos em um pacote reutilizável e independente. Isso leva a um código que se parece mais com isso:
15 |
16 | ```cpp{0}
17 | voce.vaAte(casa);
18 | ```
19 |
20 | Isso não apenas lê com mais clareza, como também deixa mais claro quem é o sujeito (você) e qual comportamento está sendo chamado (dirigindo até algum lugar, e pelo parâmetro, sua casa). Em vez de focarmos nas funções de escrita, estamos focados na definição de objetos com um conjunto bem definido de comportamentos. É por isso que o paradigma é chamado de "orientado a objetos".
21 |
22 | Isso permite que os programas sejam escritos de uma maneira mais modular, o que os torna mais fáceis de escrever e entender e também oferece um maior grau de reutilização de código. Esses objetos também fornecem uma maneira mais intuitiva de trabalhar com nossos dados, permitindo-nos definir como interagimos com os objetos e como eles interagem com outros objetos.
23 |
24 | Observe que OOP não substitui os métodos de programação tradicionais. Em vez disso, fornece ferramentas adicionais no seu cinto de ferramentas de programação para gerenciar a complexidade quando necessário.
25 |
26 | A programação orientada a objetos também traz vários outros conceitos úteis para a tabela: herança, encapsulamento, abstração e polimorfismo (os designers de linguagem têm uma filosofia: nunca use uma palavra pequena onde uma palavra grande funcionará). Abordaremos todos esses conceitos nos próximos tutoriais nos próximos capítulos. É um monte de material novo, mas depois de se familiarizar com o OOP e clicar nele, talvez você nunca mais queira voltar à programação tradicional pura.
27 |
28 | Observe que o termo "objeto" está sobrecarregado um pouco, e isso causa uma certa confusão. Na programação tradicional, um objeto é um pedaço de memória para armazenar valores. E é isso. Na programação orientada a objetos, um "objeto" implica que ele é um objeto no sentido tradicional de programação e que combina propriedades e comportamentos. A partir deste momento, quando usarmos o termo "objeto", nos referiremos a "objetos" no sentido orientado a objetos.
--------------------------------------------------------------------------------
/docs/tutorial/secao0171.md:
--------------------------------------------------------------------------------
1 | # 17.1 - Classes
2 |
3 | Embora o C ++ forneça vários tipos de dados fundamentais (por exemplo, char, int, long, float, double, etc ...) que geralmente são suficientes para resolver problemas relativamente simples, pode ser difícil resolver problemas complexos usando apenas esses tipos. Um dos recursos mais úteis do C ++ é a capacidade de definir seus próprios tipos de dados que melhor correspondem ao problema que está sendo resolvido. Você já viu como tipos e estruturas enumerados podem ser usados para criar seus próprios tipos de dados personalizados.
4 |
5 | No mundo da programação orientada a objetos, geralmente queremos que nossos tipos não apenas mantenham dados, mas também forneçam funções que funcionem com os dados. Em C ++, isso geralmente é feito através da palavra-chave da classe. O uso da palavra-chave class define um novo tipo definido pelo usuário chamado class.
6 |
7 | No C ++, classes e estruturas são essencialmente as mesmas. De fato, a seguinte estrutura e classe são efetivamente idênticas:
8 |
9 | ```cpp{0}
10 | struct FuncionarioStruct
11 | {
12 | std::string m_nome;
13 | int m_idade;
14 | };
15 |
16 | class FuncionarioClasse
17 | {
18 | public:
19 | std::string m_nome;
20 | int m_idade;
21 | };
22 | ```
23 |
24 | # Keyword public, protected e private
25 |
26 | Note a utilização do `public`, quer dizer que tanto membros da classe(ou seja, funções que estão dentro da classe) e membros externos podem acessar esta variável.
27 |
28 | Por exemplo:
29 |
30 | ```cpp{0}
31 | struct FuncionarioStruct
32 | {
33 | std::string m_nome;
34 | int m_idade;
35 | };
36 |
37 | int main()
38 | {
39 | FuncionarioStruct f;
40 | f.m_nome = "João";
41 | }
42 | ```
43 |
44 | É possivel modificar diretamente o nome pois struct's não possuem keyword de acesso, e por padrão utilizam `public`
45 |
46 | # Setters e Getters
47 |
48 | Então para acessar uma variável privada, precisamos de funções na classe para alterar ou retornar esses valores,dando o exemplo:
49 |
50 | ```cpp{0}
51 | #include
52 | #include
53 |
54 | // Requer flag de C++17
55 |
56 | namespace FUNCIONARIO // Namespace que irá conter a classe Atendente
57 | {
58 | class Atendente
59 | {
60 | private: // Keyword private
61 | std::string m_nome;
62 |
63 | public: // Keyword public
64 | Atendente(std::string nNome) // Construtor da classe, recebendo um parâmetro nNome
65 | {
66 | this->m_nome = nNome;
67 | }
68 |
69 | ~Atendente() // Destrutor da Classe
70 | {
71 | }
72 |
73 | void setNome(std::string nNome) // Setter do nome
74 | {
75 | this->m_nome = nNome;
76 | }
77 |
78 | const std::string getNome() const // Getter do nome
79 | {
80 | return this->m_nome;
81 | }
82 | };
83 | } // namespace FUNCIONARIO
84 |
85 | auto main() -> int
86 | {
87 | auto ul = std::make_unique("Jose"); // Instanciação da classe Atendente
88 |
89 | std::cout << ul->getNome() << std::endl; // Exibe Jose
90 |
91 | ul->setNome("Claudio"); // Seta o m_nome Claudio
92 |
93 | std::cout << ul->getNome() << std::endl; // Exibe Claudio
94 | }
95 | ```
96 |
97 | Demos um exemplo de utilização de namespace, agrupando outras variantes de funcionarios possíveis.
98 |
99 | Mas, várias classes diferentes de tipos de funcionário terão atributos parecidos e terá uma repetição de código.
100 |
101 | Para isso, podemos `herdar` classes para evitar repetição.
102 |
103 | A keyword `protected` serve para esse caso, pois classes filhas, ou seja, que herdam de uma classe mãe podem acessar seus métodos, mas ainda sim conteúdos de fora não podem acessar seus métodos.
104 |
105 | Exemplo:
106 |
107 | ```cpp{0}
108 | class Funcionario
109 | {
110 | protected: // Keyword private
111 | std::string m_nome;
112 |
113 | public: // Keyword public
114 | Funcionario(std::string nNome) // Construtor da classe, recebendo um parâmetro nNome
115 | {
116 | this->m_nome = nNome;
117 | }
118 |
119 | Funcionario()
120 | {
121 | this->m_nome = "";
122 | }
123 |
124 | ~Funcionario() // Destrutor da Classe
125 | {
126 | }
127 |
128 | void setNome(std::string nNome) // Setter do nome
129 | {
130 | this->m_nome = nNome;
131 | }
132 |
133 | const std::string getNome() const // Getter do nome
134 | {
135 | return this->m_nome;
136 | }
137 | };
138 | class Atendente : public Funcionario // Herdando funcionario
139 | {
140 | private: // Keyword private
141 | std::string m_turno;
142 |
143 | public: // Keyword public
144 | Atendente(std::string nNome, std::string nTurno) // Construtor da classe, recebendo um parâmetro nNome
145 | {
146 | this->m_nome = nNome; // Se m_nome fosse privado, teria que utilizar typedef
147 | this->m_turno = m_turno;
148 | }
149 |
150 | ~Atendente() // Destrutor da Classe
151 | {
152 | }
153 |
154 | void setTurno(std::string nTurno) // Setter do turno
155 | {
156 | this->m_turno = nTurno;
157 | }
158 |
159 | const std::string getTurno() const // Getter do turno
160 | {
161 | return this->m_turno;
162 | }
163 | }; // namespace FUNCIONARIO
164 |
165 | auto main() -> int
166 | {
167 | auto ul = std::make_unique("Jose", "Tarde");
168 |
169 | std::cout << ul->getNome() << std::endl; // Exibe Jose
170 |
171 | ul->setTurno("Noite"); // Seta o turno Noite
172 |
173 | std::cout << ul->getTurno() << std::endl; // Exibe Noite
174 |
175 | return EXIT_SUCCESS;
176 | }
177 | ```
178 |
179 | Getters e Setters possuem padronização, da mesma forma mostrado anteriormente:
180 |
181 | ```cpp{0}
182 | class Date
183 | {
184 | private:
185 | int m_month;
186 | int m_day;
187 | int m_year;
188 |
189 | public:
190 | int getMonth() { return m_month; } // getter do mes
191 | const void setMonth(int month) const { m_month = month; } // setter do mes
192 |
193 | int getDay() { return m_day; } // getter do dia
194 | const void setDay(int day) const { m_day = day; } // setter do dia
195 |
196 | int getYear() { return m_year; } // getter do ano
197 | const void setYear(int year) const { m_year = year; } // setter do ano
198 | };
199 | ```
200 |
201 | Os getters devem fornecer acesso "somente leitura" aos dados. Portanto, a melhor prática é que eles retornem por valor ou referência const (não por referência não const). Um getter que retorna uma referência não-const permitiria ao chamador modificar o objeto real que está sendo referenciado, o que viola a natureza somente leitura do getter (e viola o encapsulamento).
202 |
203 | Prática recomendada: Getters devem retornar por valor ou referência const
--------------------------------------------------------------------------------
/docs/tutorial/secao0172.md:
--------------------------------------------------------------------------------
1 | # 17.2 - Inicialização de Construtores
2 |
3 | Ao escrever uma classe que possui vários construtores (que é a maioria deles), ter que especificar valores padrão para todos os membros em cada construtor resulta em código redundante. Se você atualizar o valor padrão para um membro, precisará tocar em cada construtor.
4 |
5 | A partir do C ++ 11, é possível atribuir diretamente às variáveis normais dos membros da classe (aquelas que não usam a palavra-chave estática) um valor padrão de inicialização:
6 |
7 | ```cpp{0}
8 | class Retangulo
9 | {
10 | private:
11 | double m_altura{ 1.0 };
12 | double m_largura{ 1.0 };
13 |
14 | public:
15 | Retangulo()
16 | {
17 | // O Construtor padrão ira inicializar com os valores colocar acima nas variaveis
18 | }
19 |
20 | void print()
21 | {
22 | std::cout << "altura: " << m_altura << ", largura: " << m_largura << '\n';
23 | }
24 | };
25 |
26 | auto main() -> int
27 | {
28 | Retangulo r{}; // x.m_altura = 1.0, x.m_largura = 1.0
29 | r.print();
30 |
31 | return 0;
32 | }
33 | ```
34 |
35 | A inicialização de membro não estático (também chamada de inicializadores de membro da classe) fornece valores padrão para suas variáveis de membro que seus construtores usarão se os construtores não fornecerem valores de inicialização para os próprios membros (por meio da lista de inicialização de membros).
36 |
37 | No entanto, observe que os construtores ainda determinam que tipo de objetos podem ser criados.
38 |
39 | Então se não tiver construtor padrão, não é possivel fazer isso.
40 |
41 | Se um valor de inicialização padrão for fornecido e o construtor inicializar o membro por meio da lista de inicializadores de membros, a lista de inicializadores de membros terá precedência. O exemplo a seguir mostra isso:
42 |
43 | ```cpp{0}
44 | class Retangulo
45 | {
46 | private:
47 | double m_altura{ 1.0 };
48 | double m_largura{ 1.0 };
49 |
50 | public:
51 |
52 | Retangulo(double altura, double largura)
53 | : m_altura{ altura },
54 | m_largura{ largura }
55 | {
56 | // m_length and m_width are initialized by the constructor (the default values aren't used)
57 | }
58 |
59 | void print()
60 | {
61 | std::cout << "altura: " << m_altura << ", largura: " << m_largura << '\n';
62 | }
63 |
64 | };
65 |
66 | int main()
67 | {
68 | Retangulo r{ 2.0, 3.0 };
69 | r.print();
70 |
71 | return 0;
72 | }
73 | ```
74 |
75 | ```cpp{0}
76 | #include
77 | #include
78 |
79 | class Employee
80 | {
81 | private:
82 | int m_id;
83 | std::string m_name;
84 |
85 | public:
86 | Employee(int id=0, const std::string &name=""):
87 | m_id(id), m_name(name)
88 | {
89 | std::cout << "Employee " << m_name << " criado.\n";
90 | }
91 |
92 | // Use a delegating constructors to minimize redundant code
93 | Employee(const std::string &name) : Employee(0, name) { }
94 | }
95 | ```
96 |
97 | # Construtores com funcionalidade sobreposta
98 |
99 | Quando você instancia um novo objeto, o construtor do objeto é chamado implicitamente pelo compilador C ++. Não é incomum ter uma classe com vários construtores com funcionalidade sobreposta.
100 |
101 | # Delegando construtores em C++11 >
102 |
103 | A partir do C ++ 11, os construtores agora podem chamar outros construtores. Esse processo é chamado de delegação de construtores (ou encadeamento de construtores).
104 |
105 | Para que um construtor chame outro, basta chamar o construtor na lista de inicializadores de membros. Este é um caso em que chamar outro construtor diretamente é aceitável.
106 |
107 | Exemplo:
108 |
109 | ```cpp{0}
110 | #include
111 | #include
112 |
113 | class Empregado
114 | {
115 | private:
116 | int m_id;
117 | std::string m_nome;
118 |
119 | public:
120 | Empregado(int id=0, const std::string &nome=""):
121 | m_id(id), m_nome(nome)
122 | {
123 | std::cout << "Empregado " << m_nome << " criado.\n";
124 | }
125 |
126 | // Delegando construtor
127 | Empregado(const std::string &nome) : Empregado(0, nome) { }
128 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao0173.md:
--------------------------------------------------------------------------------
1 | # 17.3 - Classes no Header
2 |
3 | Todas as classes que escrevemos até agora são simples o suficiente para podermos implementar as funções de membros diretamente dentro da própria definição de classe.
4 |
5 | No entanto, à medida que as classes ficam mais longas e mais complicadas, ter todas as definições de função de membro dentro da classe pode tornar a classe mais difícil de gerenciar e trabalhar. O uso de uma classe já escrita requer apenas a compreensão de sua interface pública (as funções públicas de membro), não como a classe funciona por baixo do capô. Os detalhes de implementação da função membro apenas atrapalham.
6 |
7 | Felizmente, o C ++ fornece uma maneira de separar a parte "declaração" da classe da parte "implementação". Isso é feito definindo as funções de membro da classe fora da definição de classe. Para fazer isso, basta definir as funções de membro da classe como se fossem funções normais, mas prefixe o nome da classe à função usando o operador de resolução de escopo (: :) (o mesmo que para um espaço para nome).
8 |
9 | Exemplo:
10 |
11 | ```cpp{0}
12 | // .hpp
13 | #ifndef _H
14 | #define _H
15 |
16 | class Dia
17 | {
18 | private:
19 | int m_ano;
20 | int m_mes;
21 | int m_dia;
22 |
23 | public:
24 | Dia(int ano, int mes, int dia);
25 |
26 | void SetDia(int ano, int mes, int dia);
27 |
28 | int getAno() { return ano; }
29 | int getMes() { return m_mes; }
30 | int getDia() { return m_dia; }
31 | };
32 |
33 | #endif
34 | ```
35 | ```cpp{0}
36 | // .cpp
37 | #include ".hpp"
38 |
39 | //
40 | Dia::Dia(int ano, int mes, int dia)
41 | {
42 | SetDia(ano, mes, dia);
43 | }
44 |
45 | void Dia::SetDia(int ano, int mes, int dia)
46 | {
47 | m_mes = mes;
48 | m_dia = dia;
49 | m_ano = ano;
50 | }
51 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao1.md:
--------------------------------------------------------------------------------
1 | # 1 - Configurando o Ambiente
2 |
3 | Seção 1 - Opções e Configurando o Ambiente
4 |
5 | Primeiramente, precisamos configurar o ambiente de programação para conseguirmos começar a programar.
6 |
7 | Mas, o que seria um ambiente de programação?
8 |
9 | - Uma IDE (Ambiente de Desenvolvimento Integrado) é um programa que reúne ferramentas para ajudar o desenvolvedor.
10 | Existem várias IDEs para C++ e iremos te dar algumas opções:
11 |
12 | - Falcon C++
13 |
14 | 
15 |
16 | - CodeBlocks
17 |
18 | 
19 |
20 | - CodeBlocks
21 |
22 | 
23 |
24 | - Repl.it
25 |
26 | 
27 |
28 | Sinta-se livre para escolher a IDE se sua preferência
29 |
30 | - Escolha a que deseja utilizar, e siga os passos da seção que corresponde a IDE.
31 |
--------------------------------------------------------------------------------
/docs/tutorial/secao11.md:
--------------------------------------------------------------------------------
1 | # 1.1 - Instalando o Falcon C++
2 |
3 | - Neste curso, vamos ensinar apenas a instalar e utilizar o Falcon CPP
4 |
5 | - Primeiramente, vamos entrar no site do Falcon C++
6 |
7 | - Clique no botão `Download`
8 |
9 | 
10 |
11 | - Após baixar, abra o `.exe`
12 |
13 | - Selecione a linguagem de sua preferência
14 |
15 | 
16 |
17 | - Clique em próxima até chegar nesta tela abaixo, e selecione estas opções:
18 |
19 | 
20 |
21 | - Iremos comentar um pouco sobre compiladores na próxima seção
22 |
23 | - Na próxima tela, escolha o local onde deseja instalar o Falcon C++
24 |
25 | 
26 |
27 | - Avance e pronto, temos a tela inicial do Falcon C++!
28 |
29 | 
30 |
31 | - Agora vamos mostrar um pouco sobre como utilizar a IDE sem muitos problemas
32 |
33 | - Inicialmente, vamos começar pelo menu superior
34 |
35 | 
36 |
37 | - Ao clicar no menu `Arquivo`, temos estas opções:
38 |
39 | 
40 |
41 | - Abrindo o `Novo`, temos estas opções:
42 |
43 | 
44 |
45 | - Para agora, apenas a opção `Arquivo C++` nos interessa, clique nela para criar um novo arquivo C++
46 |
47 | \*Nesta parte abaixo, é onde escrevemos o nosso código
48 |
49 | 
50 |
51 | - As outras opções do menu `Arquivo` são sugestivas, como abrir um arquivo, salvar e fechar
52 |
53 | 
54 |
55 | - Na aba `Executar`, temos estas opções:
56 |
57 | 
58 |
59 | - Para compilar e executar na sequência, utilize o `Compilar e executar`
60 |
61 | - Apenas compilar, utilize o `Compilar`
62 |
63 | - `Executar` quando você ja possui um arquivo `.exe`,ou seja, ja compilou
64 |
65 | * Você também tem todas estas opções em uma barra
66 |
67 | 
68 |
69 | - Pronto! Você tem toda a base para começarmos a programar CPP!
70 |
71 | ::: warning
72 |
73 | - IDE's tem muitos atalhos que pode facilitar a sua vida, recomendamos a dar uma olhada na documentação.
74 |
75 | :::
76 |
--------------------------------------------------------------------------------
/docs/tutorial/secao2.md:
--------------------------------------------------------------------------------
1 | # 2 - Um pouco de teoria
2 |
3 | A CPU de um computador é incapaz de diretamente entender C++. O conjunto limitado de instruções que uma CPU pode entender é chamado de código (ou linguagem) de máquina, e é composto de diversos códigos de operação (_opcodes_).
4 |
5 | Um exemplo de uso de _opcode_ se encontra em `imul eax, eax`, que efetua a multiplicação em arquiteturas X86, e é tradicionalmente representado por 0x0FAF ou 111110101111.
6 |
7 | Durante muitos anos programadores haviam de escrever programas diretamente em linguagem de máquina, o que era algo muito difícil e demorado de se fazer, por diversos motivos.
8 |
9 | Como essas instruções estão organizadas está além do escopo desta introdução, mas é interessante notar duas coisas. Primeiro, cada instrução é composta por uma sequência de 1 e 0. Cada indivíduo 0 ou 1 é chamado de dígito binário ou bit para abreviar. O número de bits que compõem um único comando varia - Por exemplo, algumas CPUs processam instruções que são sempre de 32 bits, enquanto algumas outras CPUs (como a família x86, que você provavelmente está usando) têm instruções que podem ser comprimento variável.
10 |
11 | Cada conjunto de dígitos binários é interpretado pela CPU em um comando para fazer um trabalho muito específico, como comparar esses dois números, ou colocar esse número nesse local de memória. No entanto, como CPUs diferentes têm conjuntos de instruções diferentes, instruções que foram escritas para um tipo de CPU não puderam ser usadas em uma CPU que não compartilhava o mesmo conjunto de instruções. Isso significava que os programas geralmente não eram portáveis (utilizáveis sem grandes retrabalhos) para diferentes tipos de sistema e precisavam ser escritos novamente.
12 |
13 | Para resolver as questões de legibilidade e portabilidade, novas linguagens de programação, como C, C ++, Pascal foram desenvolvidas, com compiladores que permitem executar um mesmo código em diversas arquiteturas diferentes.
14 |
15 | Linguagens são classificadas pelos seus níveis de abstração. Por exemplo, C é uma linguagem de baixo nível, pois é sintáticamente próxima de linguagem de máquina, necessitando do programador controles mais manuais ao _hardware_, como controle de memória, evitar acessos e escritas indevidas de memória, e etc. Linguagems alto nível, como Java, são mais fáceis de se codificar, mas tradicionalmente sofrem em performance, assim como muitas vezes dificultam maior controle ao hardware.
16 |
17 | A grande vantagem do C++ é sua flexibilidade, isto é, a possibilidade de criar programas de baixo nível, assim como abstrações de mais alto nível, mantendo ainda performance similar à do C. Por este motivo, C++ é tradicionalmente usado em engenharia de sistemas, em programas com necessidade de performance, como em computação gráfica, inteligência artificial, etc.
18 |
19 |
20 | ## O que é C++?
21 |
22 | C++ (pronunciado como C plus plus) foi desenvolvido por Bjarne Stroustrup no Bell Labs como uma extensão para C, começando em 1979. C++ adiciona muitos recursos à linguagem C, e pode ser considerado um "superconjunto" do C.
--------------------------------------------------------------------------------
/docs/tutorial/secao3.md:
--------------------------------------------------------------------------------
1 | # 3 - Primeiro Hello World
2 |
3 | Vamos começar com o primeiro Hello World!
4 |
5 | - 1 : Crie um projeto em sua IDE escolhida
6 |
7 | - 2 : Digite o seguinte código:
8 |
9 | ```cpp{0}
10 | #include
11 |
12 | int main ()
13 | {
14 | std::cout << "Hello World" << std::endl;
15 | }
16 | ```
17 |
18 | - 3 : Compile e execute
19 |
20 | - Pronto! Você fez o seu primeiro Hello World!
21 |
22 | - Mas,como?
23 |
24 | - A seguir, iremos explicar todos os conceitos por trás deste `Hello World`:
25 |
26 | ### Sequência
27 |
28 | - O procedimento de código é de cima para baixo e com conteúdos em sequência, separados por `;`
29 |
30 | - Será melhor explicado na seção de variáveis.
31 |
32 | ### Bibliotecas
33 |
34 | ```cpp{0}
35 | #include
36 | ```
37 |
38 | * Uma biblioteca padrão é uma coleção de classes, funções e variáveis escritas na própria linguagem para facilitar o desenvolvimento de aplicações.
39 |
40 | * Utilizando `#include ` é possível chamar bibliotecas.
41 |
42 | * Em termos simples, todo o conteúdo que está na localização da biblioteca é copiado e colado em apenas uma linha de código no seu projeto.
43 |
44 | * Bibliotecas são incluidas sempre no começo do arquivo.
45 |
46 | # Função main
47 |
48 | ```cpp{0}
49 | int main() {}
50 | ```
51 |
52 | - Cada programa C++ tem uma função principal que deve ser nomeada main.
53 |
54 | - Todo o procedimento do seu código inicia-se nesta função.
55 |
56 | - `{}` é o que chamamos de escopo, o que for declarado desde seu início `{` até seu fim `}` irá existir apenas dentro dele.
57 |
58 | - Como `main` é uma função, precisamos colocar `()` após a declaração de seu nome.
59 |
60 | - Os conceitos sobre o que é uma função será explicado na seção de Funções, por enquanto não se preocupe com isso.
61 |
62 | - Vamos aprender a como manipular o nosso conteúdo para que ele continue existindo mesmo fora do escopo futuramente.
63 |
64 | # Saída de Dados e Biblioteca ``
65 |
66 | ```cpp{0}
67 | std::cout << "Hello World" << std::endl;
68 | ```
69 |
70 | - `std::cout` (out de saída) pertence a biblioteca `` significa que queremos exibir algo na tela, ou seja, uma saída de algum dado que passarmos para o `std::cout`.
71 |
72 | - O operador << significa que estamos passando algo para 'a direção', no caso para o std::cout, sendo também um operador da ``.
73 |
74 | - Para passarmos um conjunto de caracteres(chamado de string) precisamos colocar entre "",no caso a string `Hello World`.
75 | Espaços `" "` também contam como caracteres.
76 |
77 | - `std::endl` também pertence a `` que executa a quebra de linha,ou seja, sempre quando chamada irá mandar todo o conteúdo sucessor para uma nova linha.
78 |
79 | - Todo o final de linha de código precisamos colocar `;` para indicarmos pro compilador que pode executar o proximo conteúdo.
80 |
81 | - `std::` é um espaço de nome para as bibliotecas padrões do C++, para acessarmos o seu conteúdo precisamos usar `std::` e entrar neste espaço de nome reservado `std`, com `::` indicando a entrada.
82 |
83 | ```cpp{0}
84 | #include
85 |
86 | int main()
87 | {
88 | std::cout << "A" << std::endl;
89 | std::cout << "B";
90 | }
91 | ```
92 |
93 | Irá ser exibido:
94 |
95 | A
96 |
97 | B
98 |
99 | ```cpp{0}
100 | #include
101 |
102 | int main()
103 | {
104 | std::cout << "A" << "B";
105 | }
106 | ```
107 |
108 | Irá ser exibido:
109 | AB
110 |
111 | - Algumas IDE's faz a quebra de linha automaticamente sem a necessidade do `std::endl`.
112 |
113 | - Todos os conceitos passado será utilizado ao longo do curso, então não se assuste que com a prática estes conceitos serão facilmente fixados.
114 |
--------------------------------------------------------------------------------
/docs/tutorial/secao4.md:
--------------------------------------------------------------------------------
1 | # 4 - Introdução ao compilador e vinculador
2 |
3 | Para compilar um programa em C++, usamos um compilador C++. O compilador percorre cada arquivo de código-fonte (.cpp) em seu programa e executa duas tarefas importantes:
4 |
5 | Primeiro, ele verifica seu código para garantir que ele siga as regras da linguagem C++. Se isso não ocorrer, o compilador fornecerá um erro (e o número da linha correspondente) para ajudar a identificar o que precisa ser corrigido. O processo de compilação também será abortado até que o erro seja corrigido.
6 |
7 | Segundo, ele converte seu código-fonte em um arquivo de linguagem de máquina chamado arquivo de objeto. Os arquivos de objetos são normalmente chamados de name.o ou name.obj, em que name é o mesmo nome do arquivo .cpp do qual foi produzido.
8 |
9 | Por exemplo,se você tem seu `main.cpp`, ele irá gerar um arquivo objeto `main.o`
10 |
11 | 
12 |
13 | # Vinculador
14 |
15 | - Depois que o compilador cria um ou mais arquivos de objeto, outro programa chamado vinculador(linker) entra em ação. O trabalho do linker e dividido em três etapas:
16 |
17 | - Primeiro, pegue todos os arquivos de objetos gerados pelo compilador e combine-os em um único programa executável.
18 |
19 | 
20 |
21 | - Em segundo lugar, além de poder vincular arquivos de objeto, o vinculador também é capaz de vincular arquivos de biblioteca. Um arquivo de biblioteca é uma coleção de código pré-compilado que foi “empacotado” para reutilização em outros programas, como o já usado ``.
22 |
23 | - Em terceiro lugar, o vinculador garante que todas as dependências entre arquivos sejam resolvidas corretamente. Por exemplo, se você definir algo em um arquivo .cpp e usá-lo em outro arquivo .cpp, o vinculador conectará os dois juntos. Se o vinculador não conseguir conectar uma referência a algo com sua definição, você receberá um erro de vinculador e o processo de vinculação será interrompido.
--------------------------------------------------------------------------------
/docs/tutorial/secao5.md:
--------------------------------------------------------------------------------
1 | # 5 - Variáveis
2 |
3 | Um programa pode adquirir dados para trabalhar de várias maneiras: de um arquivo ou banco de dados, através de uma rede, do usuário fornecendo entrada em um teclado ou do programador colocando dados diretamente no código-fonte do próprio programa. Na seção 3, fizemos o programa exibir um `Hello World`, o texto `"Hello World"` Foi inserido diretamente no código-fonte do programa, fornecendo dados para o programa usar. O programa então manipula esses dados enviando-os ao monitor para exibir para o usuário.Os dados em um computador são normalmente armazenados em um formato que é eficiente para armazenamento ou processamento, sendo não-legíveis por humanos.
4 |
5 | Todos os computadores têm memória, chamada RAM (abreviação de memória de acesso aleatório), que está disponível para uso pelos seus programas. Você pode pensar na RAM como uma série de caixas de correio que podem ser usadas para armazenar dados enquanto o programa está em execução. Um único dado, armazenado na memória em algum lugar, é chamado de valor.
6 |
7 | Em C++, o acesso direto à memória não é permitido. Em vez disso, acessamos a memória indiretamente por meio de um objeto. Um objeto é uma região de armazenamento (geralmente memória) que possui um valor e outras propriedades associadas (que serão abordadas em seções futuras). Quando um objeto é definido, o compilador determina automaticamente onde o objeto será colocado na memória. Como resultado, em vez de dizer para obter o valor armazenado em um local específico, podemos dizer para obter o valor armazenado por este objeto e o compilador sabe onde na memória procurar esse valor. Isso significa que podemos nos concentrar no uso de objetos para armazenar e recuperar valores e não ter que nos preocupar com o local da memória em que eles estão sendo colocados.
8 |
9 | Objetos podem ser nomeados ou não nomeados. Um objeto nomeado é chamado de variável e o nome do objeto é chamado de identificador. Em nossos programas, a maioria dos objetos que criamos serão variáveis.
10 |
11 | # Tipos
12 |
13 | - CPP é uma linguagem fortemente tipada:
14 |
15 | | Tipos | Características | Exemplos |
16 | | ------ | :-----------------------------------: | -------------------: |
17 | | void | não é associado a nenhum tipo de dado | Tipo incompleto |
18 | | int | número inteiro | 1, 2, 3, 6, -2 |
19 | | float | número fracionário (range curto) | 2.34f, 23.544f, 3.1f |
20 | | double | número fracionário (range longo) | 2.343223232322321 |
21 | | char | caractere | 'c', 'A', ' ' |
22 | | bool | booleano | true, false |
23 |
24 | Existem mais tipos, mas no momento vamos trabalhar apenas com estes.
25 |
26 | Para criar uma variável, usamos um tipo especial de declaração chamado de definição
27 |
28 | Veja um exemplo de como definir uma variável do tipo `int`chamada `inteiro`:
29 |
30 | ```cpp{0}
31 | int main ()
32 | {
33 | int inteiro;
34 | }
35 | ```
36 |
37 | Também podemos criar a variável já com um valor,no caso o valor `5`
38 |
39 | ```cpp{0}
40 | int main ()
41 | {
42 | int inteiro = 5; // Como vimos na tabela acima, int aceita números inteiros, então 5 poderia ser -212, 40242, etc...
43 | }
44 | ```
45 |
46 | - Nesse caso, estamos atribuindo pelo operador `=` o valor de `5` para a nossa variável chamada `inteiro` do tipo `int`
47 |
48 | Em tempo de compilação, quando o compilador vê esta declaração, ele faz uma nota para si mesmo que estamos definindo uma variável, dando a ela o nome `inteiro`, e que é do tipo `int` (mais em tipos em um momento). Desse ponto em diante (com algumas limitações sobre as quais falaremos em uma lição futura), sempre que o compilador vir o identificador `inteiro`, saberá que estamos fazendo referência a essa variável.
49 |
50 | Quando o programa é executado (chamado runtime), a variável será instanciada. A instanciação é uma palavra sofisticada que significa que o objeto será criado e atribuído a um endereço de memória. As variáveis devem ser instanciadas antes de poderem ser usadas para armazenar valores. Por exemplo, digamos que a variável `inteiro` é instanciada no local da memória 23. Sempre que o programa usar a variável `inteiro`, ele acessará o valor no local da memória 23. Um objeto instanciado às vezes também é chamado de instância. Na seção de ponteiros iremos aprender a manipular diretamente pelo endereço de memória.
51 |
52 | # Comentários
53 |
54 | - Podemos escrever conteúdo no nosso código apenas para visualização utlizando `//` e `/* */`
55 |
56 | ```cpp{0}
57 | int main ()
58 | {
59 | int numero = 3 // variavel numero de tipo inteiro que recebe o valor '3'
60 |
61 | /*
62 | Podemos também comentar trechos de código
63 | que não quisermos utilizar em um
64 | determinado momento
65 | */
66 | }
67 | ```
68 |
69 | - Exemplos de declaração de variáveis e utilizações gerais:
70 |
71 | ```cpp{0}
72 | #include
73 |
74 | int main ()
75 | {
76 | /*|--------------------------------------|
77 | *| |
78 | *| He4rt Developers |
79 | *| |
80 | *|--------------------------------------|
81 | */
82 |
83 | int inteiro = 5;
84 | char caractere = 'a';
85 | float fracionario = 5.2f;
86 | bool booleano = true;
87 |
88 | int inteiro_vazio;
89 |
90 | std::cout << inteiro << caractere << fracionario << std::endl; // Exibição: 5a5.2
91 | std::cout << inteiro << " " << caractere << " " << fracionario << std::endl; // Exibição: 5 a 5.2
92 |
93 | std::cout << inteiro_vazio << std::endl; // Exibição: 0
94 |
95 | std::cout << booleano << std::endl // Exibição: true
96 |
97 | // É possivel quebrar linha também com a string "\n"
98 | std::cout << inteiro << "\n" << caractere << "\n" << fracionario << "\n";
99 | }
100 | ```
101 |
102 | # Curiosidades
103 |
104 | ```cpp{0}
105 | int main ()
106 | {
107 | /*|--------------------------------------|
108 | *| |
109 | *| He4rt Developers |
110 | *| |
111 | *|--------------------------------------|
112 | */
113 |
114 | int a, b; // Correto
115 | int a, int b; // Errado
116 |
117 | int a, double b; // Errado
118 | int a; double b; // Correto
119 |
120 | // Recomendados utilizar este padrão:
121 |
122 | int a;
123 | double b;
124 | }
125 |
126 | ```
127 | # Entrada de Dados com `std::cin`
128 |
129 | Agora iremos falar do `std::cin` da biblioteca ``, ela permite a entrada de dados,sendo sua sintaxe parecida com a do `std::cout`
130 |
131 | ```cpp{0}
132 | std::cin >> ;
133 | ```
134 |
135 | Note que como estamos entrando com dados, temos que indicar pelo operador `>>`, sendo o inverso do operador de saída `std::cout` que utilizamos `<<`.
136 | # Exemplos
137 |
138 | - Entrada e saída de dados de um determinado aluno
139 |
140 | ```cpp{0}
141 | #include
142 |
143 | int main ()
144 | {
145 | int idade; // Declarando a idade do aluno
146 |
147 | // Saida de dados, perguntando para o utilizador do programa a idade do aluno
148 | std::cout << "Digite a idade do aluno: " << std::endl;
149 |
150 | //Entrada de dados com o nome do aluno
151 | std::cin >> idade; // Entrada de dados para a variável idade,ou seja,o que o utilizador digitar irá ir para o inteiro `idade`
152 |
153 | // Saida de dados de uma string e em sequência a idade do aluno
154 | std::cout << "A idade do aluno e: " << idade << std::endl;
155 | }
156 |
157 | ```
158 |
159 | - Lembrando que `std::cout << "Digite a idade do aluno: " << std::endl;` é apenas visual para a interação de programa-usuário.
160 |
161 | - Existem outras formas de inicialização:
162 |
163 | ```cpp{0}
164 | #include
165 |
166 | int main ()
167 | {
168 | /*|--------------------------------------|
169 | *| |
170 | *| He4rt Developers |
171 | *| |
172 | *|--------------------------------------|
173 | */
174 |
175 | //Tipos de inicialização
176 |
177 | int a = 5, A = 6; // Inicialização por cópia
178 | int b( 7 ), B( 8 ); // Inicialização direta
179 | int c{ 9 }, C{ 10 }; // Inicialização uniforme
180 |
181 | std::cout << a << std::endl;
182 | std::cout << A << std::endl;
183 | std::cout << b << std::endl;
184 | std::cout << B << std::endl;
185 | std::cout << c << std::endl;
186 | std::cout << C << std::endl;
187 |
188 | int a, b( 5 );
189 | std::cout << a << " " << b << std::endl; // Saída: 0 5
190 |
191 | }
192 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao51.md:
--------------------------------------------------------------------------------
1 | # 5.1 - Operações Matemáticas
2 |
3 | Primeiramente,vamos falar dos Operadores Aritméticas e são, basicamente, os mesmos encontrados na matemática basica.
4 |
5 | | Operação | Operador | Exemplos |
6 | | ------------- | :------: | -------------------------: |
7 | | Adição | + | int a = 5 + 2 |
8 | | Subtração | - | int b = (4 - 2) - 1 |
9 | | Multiplicação | * | int c = ((2 * 2) * 2) * 2 |
10 | | Divisão | / | int d = (8 / 6) / 2 |
11 | | Módulo | % | int e = 4 % 2 |
12 |
13 | # Exemplos
14 |
15 | ```cpp{0}
16 | #include
17 |
18 | int main ()
19 | {
20 | /*|--------------------------------------|
21 | *| |
22 | *| He4rt Developers |
23 | *| |
24 | *|--------------------------------------|
25 | */
26 |
27 | int A; // Inteiro A
28 | int B; // Inteiro B
29 |
30 | std::cout << "Digite o primeiro numero:" << std::endl;
31 | std::cin >> A;
32 |
33 | std::cout << "Digite o segundo numero:" << std::endl;
34 | std::cin >> B;
35 |
36 | // Estamos atribuindo a uma nova variável C o resultado da soma das variaveis A e B
37 | int C = A + B;
38 |
39 | std::cout << "A soma entre A e B e: " << C << std::endl;
40 |
41 | // Podemos calcular diretamente na saida de dados
42 | std::cout << "A multiplicação entre A e B e: " << A * B << std::endl;
43 | }
44 | ```
45 |
46 | ```cpp{0}
47 | int main ()
48 | {
49 | /*|--------------------------------------|
50 | *| |
51 | *| He4rt Developers |
52 | *| |
53 | *|--------------------------------------|
54 | */
55 |
56 | float A;
57 |
58 | // Até aqui não atribuimos nenhum valor para a variável A
59 |
60 | A = 5.2; // Agora A vale 5.2
61 |
62 | std::cout << A << std::endl;
63 |
64 | A = 8.4; // Agora A vale 8.4
65 |
66 | std::cout << A << std::endl;
67 |
68 | A = A / 2; // Dividimos o atual o valor de A (8.4) por 2 na própria variavel A
69 |
70 | std::cout << A << std::endl;
71 | }
72 | ```
73 |
74 | - O CPP permite simplificar quando fazemos uma operação com a própria variavel.
75 |
76 | ```cpp{0}
77 | int main ()
78 | {
79 | /*|--------------------------------------|
80 | *| |
81 | *| He4rt Developers |
82 | *| |
83 | *|--------------------------------------|
84 | */
85 |
86 | float A = 5.5;
87 |
88 | A += 5; // Equivale A = A + 5
89 | A -= 5; // Equivale A = A - 5
90 | A *= 5; // Equivale A = A * 5
91 | A /= 5; // Equivale A = A / 5
92 |
93 | int a = 2;
94 |
95 | a /= 0; // NÃO EXISTE DIVISÃO POR 0
96 | }
97 | ```
98 |
99 | - CPP é `Case-sensitive`,ou seja, `int a` é DIFERENTE de `int A`.
100 |
101 | # Operações com a biblioteca cmath
102 |
103 | O Cabeçalho `` declara um conjunto de funções para calcular operações e transformações matemáticas comuns:
104 |
105 | ```cpp{0}
106 | #include
107 | #include
108 |
109 | int main ()
110 | {
111 | /*|--------------------------------------|
112 | *| |
113 | *| He4rt Developers |
114 | *| |
115 | *|--------------------------------------|
116 | */
117 |
118 | int x, y;
119 | std::cout << "Digite um numero: \n";
120 | std::cin >> x;
121 |
122 | std::cout << "Digite um outro numero: \n";
123 | std::cin >> y;
124 |
125 | std::cout << std::pow(x, 2); // Eleva algo a potencia, no caso o primeiro valor é elevado ao 2 valor
126 | std::cout << std::sqrt(x); // A raiz de x
127 | std::cout << std::hypot(x, y); // A raiz de (std::pow(x, 2) + std::pow(y,2))
128 | std::cout << std::abs(x + y) // A soma de x com y em módulo => |x + y|
129 |
130 | //cmath também possui outras funcionalidades, recomendamos acessar https://en.cppreference.com/w/cpp/header/cmath
131 |
132 | }
133 |
134 | ```
135 |
136 | Operadores de incremento:
137 |
138 | Incrementar (somar 1 a) e decrementar (subtrair 1 de) uma variável são tão comuns que possuem seus próprios operadores.
139 |
140 | | Operador | Símbolo | Utilização | Operação |
141 | | ------ | :--------: | ----------: | ----------------------------------------:|
142 | | Incremento de prefixo (pré-incremento) | ++ | ++x | Incrementa x e, em seguida, retorna x |
143 | | Decremento do prefixo (pré-decremento) | -- | --x | Decrementa x, em seguida, retorna x |
144 | | Incremento de posfixo (pós-incremento) | ++ | x++ | Copia x, incrementa x e devolve a cópia |
145 | | Decremento do posfixo (pós-decremento) | -- | x-- | Copia x, decrementa x e devolve a cópia |
146 |
147 |
148 | ```cpp{0}
149 | #include
150 |
151 | int main()
152 | {
153 | int a ( 5 );
154 |
155 | int b = ++a; // x é incrementado para 6, x é avaliado para o valor 6 e 6 é atribuído para y
156 |
157 | int c = a++; // a é atribuido para c, valendo 6, e após e avaliado para 7
158 | }
159 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao52.md:
--------------------------------------------------------------------------------
1 | # 5.2 - std::string
2 |
3 | - Explicamos os tipos principais para você utilizar em seu código, mas, por que não string's?
4 |
5 | - Nativamente, para se utilizar string's no C++ precisamos usar `char*`, `char[]` ou `const char*`, mas optamos explicar diretamente por uma classe do C++, chamada std::string.
6 |
7 | - Para utilizar-mos, precisamos incluir tanto o `` como uma nova biblioteca, a ``.
8 |
9 | String's não são nada menos que cadeias de caracteres, por exemplo:
10 |
11 | `"Hello World"`
12 |
13 | Cada caractere representa uma posição
14 |
15 | H - 0
16 |
17 | e - 1
18 |
19 | l - 2
20 |
21 | l - 3
22 |
23 | o - 4
24 |
25 | ' ' - 5
26 |
27 | W - 6
28 |
29 | o - 7
30 |
31 | r - 8
32 |
33 | l - 9
34 |
35 | d - 10
36 |
37 | Para utilizar o std::string é simples:
38 |
39 | ```cpp{0}
40 | /*|--------------------------------------|
41 | *| |
42 | *| He4rt Developers |
43 | *| |
44 | *|--------------------------------------|
45 | */
46 |
47 | #include
48 | #include
49 |
50 | int main ()
51 | {
52 | std::string nome = "Joao";
53 |
54 | std::cout << nome << std::endl;
55 | }
56 | ```
57 |
58 | - Mas temos alguns pontos:
59 |
60 | - Por conta do std::string ser uma classe (falaremos sobre classe futuramente), ela tem formas diferentes de se manipular, não podendo considerar como um tipo comum (int, float, etc...).
61 |
62 | - Para a entrada de dados com `std::string`, não podemos usar apenas o `std::cin`.
63 |
64 | - Vamos utilizar o std::getline
65 |
66 | ```cpp{0}
67 | /*|--------------------------------------|
68 | *| |
69 | *| He4rt Developers |
70 | *| |
71 | *|--------------------------------------|
72 | */
73 |
74 | #include
75 | #include
76 |
77 | int main ()
78 | {
79 | std::string nome;
80 |
81 | std::cout << "Digite seu nome: " << std::endl;
82 | std::getline(std::cin, nome); // Primeiramente passamos o que queremos fazer,no caso std::cin, e segundamente a variável
83 |
84 | std::cout << nome << std::endl;
85 | }
86 | ```
87 |
88 | Mas, essa abordagem tem alguns problemas,por exemplo:
89 |
90 | ```cpp{0}
91 | /*|--------------------------------------|
92 | *| |
93 | *| He4rt Developers |
94 | *| |
95 | *|--------------------------------------|
96 | */
97 |
98 | #include
99 | #include
100 |
101 | int main ()
102 | {
103 | int a, b;
104 |
105 | std::cout << "Digite um numero: " << std::endl;
106 | std::cin >> a;
107 |
108 | std::string nome;
109 |
110 | std::cout << "Digite um nome: " << std::endl;
111 | std::getline(std::cin, nome);
112 |
113 | std::cout << "Digite um outro numero: " << std::endl;
114 | std::cin >> b;
115 |
116 | std::cout << nome << std::endl;
117 | }
118 | ```
119 |
120 | Este exemplo não irá funcionar, precisamos esvaziar o buffer para conseguir-mos utilizar o `std::getline`, então precisamos utilizar o `std::cin.ignore()`
121 |
122 | ```cpp{0}
123 | /*|--------------------------------------|
124 | *| |
125 | *| He4rt Developers |
126 | *| |
127 | *|--------------------------------------|
128 | */
129 |
130 | #include
131 | #include
132 |
133 | int main ()
134 | {
135 | int a, b;
136 |
137 | std::cout << "Digite um numero: " << std::endl;
138 | std::cin >> a;
139 |
140 | std::cin.ignore();
141 |
142 | std::string nome;
143 |
144 | std::cout << "Digite um nome: " << std::endl;
145 | std::getline(std::cin, nome);
146 |
147 | std::cout << "Digite um outro numero: " << std::endl;
148 | std::cin >> b;
149 |
150 | std::cout << a << "\n" << b << std::endl;
151 | std::cout << nome << std::endl;
152 |
153 | }
154 | ```
155 |
156 | Sempre quando for dar entrada de dados em um std::string, certifique-se que o buffer está vazio, ou seja, não ter dado entrada de dados em outro tipo, no caso do exemplo utilizamos o `int a`.
157 |
158 | std::string tem mais conteúdo, mas deixaremos para abordar mais para frente no curso.
159 |
--------------------------------------------------------------------------------
/docs/tutorial/secao6.md:
--------------------------------------------------------------------------------
1 | # 6 - Condições
2 |
3 | Agora iremos falar sobre condições,mas iremos te mostrar a tabela de comparação para se utilizar em conjunto com condições.
4 |
5 | Operadores de comparação:
6 |
7 | | Operadores | Descrição | Exemplos |
8 | | ------------ | --------------------- | -------------------------------------------- |
9 | | `==` | Igual a | 4 == 4 `` 4 == 5 `` |
10 | | `!=` | Diferente de | 4 != 4 `` 4 != 5 `` |
11 | | `>` | Maior que | 4 > 5 `` 4 > 3 `` |
12 | | `<` | Menor que | 4 < 5 `` 4 < 3 `` |
13 | | `>=` | Maior ou igual a | 5 >= 5 `` 6 >= 5 `` |
14 | | `<=` | Menor ou igual a | 6 <= 5 `` 6 <= 6 `` |
15 | | `&&` | E lógico |2 < 5 `` `&&` 2 <= 4 `` = ``|
16 | | `||` | Ou lógico |2 < 5 `` `||` 5 <= 4 `` = ``|
17 |
18 | Condições são comparações que retornam `verdadeiro` ou `falso` para executar ou não um `bloco(escopo)`.
19 |
20 | `if` (se) `else if` (se senão) `else` (senão)
21 |
22 | ```cpp{0}
23 | #include
24 |
25 | int main ()
26 | {
27 | /*|--------------------------------------|
28 | *| |
29 | *| He4rt Developers |
30 | *| |
31 | *|--------------------------------------|
32 | */
33 |
34 | char sexo = 'M'; // Declaramos a variável `sexo` do tipo `char` e inicializamos com o caractere `M`
35 |
36 | // Queremos comparar para saber se `sexo` é masculino(M) ou feminino(F)
37 | if(sexo == 'M') // Verificando se sexo é igual ao caractere M
38 | {
39 | // Se a comparação for `verdadeira`, que é o nosso caso, entrará neste escopo
40 | std::cout << sexo << " e masculino" << std::endl;
41 | }
42 | // if, else if e else são uma sequência, então assim que o escopo de uma condição acabar podemos colocar em sequência
43 | else // Como se tem apenas duas opções `M` e `F`, não precisamos usar o `else if`, em caso de precisar fazer outras comparações em uma mesma cadeia, teríamos que usar `else if` e `else` apenas para a última opção que não necessita de comparação
44 | {
45 | std::cout << sexo << " e feminino" << std::endl;
46 | }
47 | }
48 |
49 |
50 | ```
51 |
52 | ```cpp{0}
53 | #include
54 |
55 | int main ()
56 | {
57 | /*|--------------------------------------|
58 | *| |
59 | *| He4rt Developers |
60 | *| |
61 | *|--------------------------------------|
62 | */
63 |
64 | float nota; // Declaramos a variável `nota` do tipo `float`
65 |
66 | std::cout << "Digite a sua nota: " << std::endl;// Saida de dados
67 | std::cin >> nota;// Entrada de dados
68 |
69 | if(nota >= 6.0f) // Se a nota for maior ou igual a 6, o aluno está aprovado
70 | {
71 | std::cout << "Aprovado!" << std::endl;
72 | } else if(nota >= 5.0f) // Se a nota do aluno for maior ou igual a 5 poderá fazer a prova de recuperação (Não precisamos utilizar nota < 6.0f neste caso pois o programa irá ler essa condição APENAS se a primeira comparação retornar false)
73 | {
74 | std::cout << "Prova de recuperacao!" << std::endl;
75 | } else { // Se a nota do aluno for abaixo de 5, ele esta reprovado
76 | std::cout << "Reprovado!" << std::endl;
77 | }
78 | }
79 | ```
80 |
81 | ```cpp{0}
82 | #include
83 |
84 | int main ()
85 | {
86 | /*|--------------------------------------|
87 | *| |
88 | *| He4rt Developers |
89 | *| |
90 | *|--------------------------------------|
91 | */
92 |
93 | /*
94 | * Poderíamos ter utilizado `else if` na ultima condição, mas não tem
95 | * necessidade por conta que se o aluno não tem nota acima de 5,
96 | * todo outro tipo de resultado é a reprovação.
97 | */
98 | float nota;
99 |
100 | std::cout << "Digite a sua nota: " << std::endl;
101 | std::cin >> nota;
102 |
103 | if(nota >= 6.0f)
104 | {
105 | std::cout << "Aprovado!" << std::endl;
106 | } else if(nota >= 5.0f)
107 | {
108 | std::cout << "Prova de recuperacao!" << std::endl;
109 | } else if(nota < 5.0f) {
110 | std::cout << "Reprovado!" << std::endl;
111 | }
112 | }
113 |
114 | ```
115 |
116 | # Operadores Lógicos
117 |
118 | ```cpp{0}
119 | #include
120 |
121 | int main ()
122 | {
123 | /*|--------------------------------------|
124 | *| |
125 | *| He4rt Developers |
126 | *| |
127 | *|--------------------------------------|
128 | */
129 |
130 | std::string nome;
131 |
132 | std::cout << "Digite seu nome: " << std::endl;
133 | std::getline(std::cin, nome); // Não tem necessidade do std::cin.ignore() pois não tem entrada de dados de outro tipo anteriormente.
134 |
135 | if(nome.size() < 0) // Verificando se a quantidade de caracteres for menor que 0,ou seja, ERRO
136 | std::cout << "ERRO!" << std::endl; // Quando temos apenas uma linha, podemos omitir o escopo
137 | else if(nome.size() >= 0 && nome.size() <= 5) // Quantidade de caracteres maior que 0 E menor que 5
138 | std::cout << "Existe entre 0 e 5 caracteres nesta string" << std::endl;
139 | else if(nome.size() > 5 && nome.size() <= 10)
140 | std::cout << "Existe entre 6 e 10 caracteres nesta string" << std::endl;
141 | else
142 | std::cout << "Existe mais de 10 caracteres nesta string" << std::endl;
143 |
144 | // std::string é uma classe e possui funções próprias para manipular,no caso o size(), na seção de funções você irá entender este conceito.
145 | }
146 | ```
147 |
148 | # Switch
149 |
150 | Para facilitar a utilização de `if/else if/else` temos o `switch`, que executa um certo bloco dependendo da `condição no switch`
151 |
152 | A utlização do `switch` e totalmente opcional e é útil apenas para certos casos
153 | ```cpp{0}
154 | #include
155 |
156 | int main ()
157 | {
158 | /*|--------------------------------------|
159 | *| |
160 | *| He4rt Developers |
161 | *| |
162 | *|--------------------------------------|
163 | */
164 |
165 | int numero1, numero2, resultado;
166 | char opcao;
167 |
168 | std::cout << "Digite um numero: \n";
169 | std::cin >> numero1;
170 |
171 | std::cout << "Digite um segundo numero: \n";
172 | std::cin >> numero2;
173 |
174 | std::cout << "Digite uma opção: (A) Soma / (B) Subtracao / (C) Multiplicacao / (D) Divisao \n";
175 | std::cin >> opcao;
176 |
177 | switch(opcao) // Switch de opcao
178 | {
179 | case 'A': // condição: true = executa o bloco / false = pula para o próximo caso e seu bloco
180 | {
181 | resultado = numero1 + numero2;
182 | break; // Em switch, precisamos utilizar o break para nao carregar as outras condicoes em sequencia,falaremos mais sobre o break na secao de loop
183 | }
184 | case 'B':
185 | {
186 | resultado = numero1 - numero2;
187 | break;
188 | }
189 | case 'C':
190 | {
191 | resultado = numero1 * numero2;
192 | break;
193 | }
194 | case 'D':
195 | {
196 | resultado = numero1 / numero2;
197 | break;
198 | }
199 | }
200 |
201 | std::cout << "O resultado da operacao e: " << resultado << std::endl;
202 | }
203 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao61.md:
--------------------------------------------------------------------------------
1 | # 6.1 - Loops
2 |
3 | Loops em C++ são condições que irão ser repetidas até que uma condição retorne `false`
4 |
5 | Em C++,temos três loop's padrões: `while` (enquanto), `do while` (faz ... enquanto) e for(for é uma versão com recursos extras do `while`,iremos falar sobre o `for` na seção de vetores).
6 |
7 | Exemplo:
8 |
9 | ```cpp{0}
10 | #include
11 |
12 | int main ()
13 | {
14 | /*|--------------------------------------|
15 | *| |
16 | *| He4rt Developers |
17 | *| |
18 | *|--------------------------------------|
19 | */
20 |
21 | int i = 0;
22 |
23 | while(i < 10) // Enquanto i for menor que 10, ele irá repetir este escopo
24 | {
25 | std::cout << i << " "; // Exibição de i com um espaçamento
26 | i++; // A cada repetição, irá iterar 1 em i,ou seja: 0 1 2 3 4 5.. até a condição do while retornar falso
27 | }
28 |
29 | std::cout << std::endl << "O numero final de i e: " << i << std::endl;
30 |
31 | // Exibição: 0 1 2 3 4 5 6 7 8 9
32 | // O numero final de i e: 10
33 |
34 | // Após a exibição de 9, i é iterado e se torna 10, mas 10 < 10 é uma condição falsa, então o loop acaba saindo de seu escopo.
35 | }
36 | ```
37 |
38 | # Do while
39 |
40 | ```cpp{0}
41 | #include
42 |
43 | int main ()
44 | {
45 | /*|--------------------------------------|
46 | *| |
47 | *| He4rt Developers |
48 | *| |
49 | *|--------------------------------------|
50 | */
51 |
52 | int i { 0 } , j = { 0 };
53 | std::string st = "Oi!";
54 |
55 | do // Faz
56 | {
57 | std::cout << "i: "<< i++ << " / j: " << ++j << std::endl; // Interaçoes
58 | }while(i < 10);// Enquanto
59 |
60 | std::cout << std::endl; // Até aqui tem o mesmo efeito do que se utilizando apenas o while
61 |
62 | do
63 | {
64 | std::cout << st << std::endl;
65 | }while(st == "Ola!"); // Neste caso, st ainda sim será mostrado pois está anteriormente a condição, e o loop apenas retorna falso na condição.
66 | }
67 | ```
68 |
69 | Com estes conhecimentos, já podemos fazer algoritmos mais rebuscado,como por exemplo:
70 |
71 | Construir um programa que leia o peso e o sexo masculino e feminino, de um conjunto de várias pessoas. O usuário irá informar a quantidade exata de pessoas. Calcular e escrever o menor peso do grupo de pessoas, maior peso dos homens e média de peso das mulheres
72 |
73 | ```cpp{0}
74 | #include
75 |
76 | int main ()
77 | {
78 | int peso, menor_peso, maior_peso_homens, media_peso_mulheres = 0, quantidade_mulheres = 0;
79 | std::string sexo;
80 |
81 | int pessoas;
82 |
83 | int i = 0;
84 |
85 | std::cout << "Digite o numero de pessoas: \n";
86 | std::cin >> pessoas;
87 |
88 | while(i < pessoas)
89 | {
90 | std::cout << "Digite o peso da pessoa " << (i + 1) << ":\n";
91 | std::cin >> peso;
92 |
93 | std::cout << "Digite o sexo da pessoa " << (i + 1) << ":\n";
94 |
95 | std::cin.ignore();
96 |
97 | std::getline(std::cin, sexo);
98 |
99 | if(menor_peso > peso || i == 0) // (|| i == 0) Para sempre entrar de primeira
100 | {
101 | menor_peso = peso;
102 | }
103 |
104 | if((maior_peso_homens < peso && sexo == "masculino") || i == 0) // Primeiramente ira verificar a condição entre (), e depois o || i == 0
105 | {
106 | maior_peso_homens = peso;
107 | }
108 |
109 | if(sexo == "feminino")
110 | {
111 | media_peso_mulheres += peso; // Somar todos os pesos de mulheres
112 | quantidade_mulheres++; // Quantas mulheres tem
113 | }
114 |
115 | i++; // Iteracao necessaria
116 | }
117 |
118 | media_peso_mulheres /= quantidade_mulheres; // Dividir pela quantidade de mulheres, lembrado que fora do loop pois precisamos de toda a entrada necessária para calcular a media.
119 |
120 | std::cout << "O menor peso e: " << menor_peso << std::endl;
121 | std::cout << "O maior peso entre homens e: " << menor_peso << std::endl;
122 | std::cout << "A media de peso entre mulheres e: " << media_peso_mulheres << std::endl;
123 | }
124 | ```
125 |
126 | Para não precisar usar (|| i == 0) você poderia inicializar o menor_peso com 999999 e maior_peso_homens com 0, por exemplo.
127 |
--------------------------------------------------------------------------------
/docs/tutorial/secao62.md:
--------------------------------------------------------------------------------
1 | # 6.2 - Teste de Mesa
2 |
3 | O Teste de Mesa é um processo manual que é utilizado para validar a lógica de um determinado algoritmo. Ele é utilizado principalmente em algoritmos quando a linguagem utilizada não possui nenhuma ferramenta automatizada de depuração.
4 |
5 | Existe testes bem mais elaborados, mas para começar-mos a entender o fluxo de um programa pode ser útil.
6 |
7 | Não há uma forma padrinizada para a elaboração de um Teste de Mesa, pois dependerá muito do que pretende verificar no algoritmo e do seu nível de entendimento. No geral, você deverá criar no papel uma tabela com todas as variáveis do programa e executar passo a passo seu código, anotando sempre os valores das variáveis. Assim você será capaz de identificar se os valores condizem com o esperado ou localizar a exata linha de código onde o valor da variável passa a ficar errado.
8 |
9 | Em nosso curso, iremos considerar os seguintes passos:
10 |
11 | 1 - Elaborar uma tabela onde cada coluna se refere a cada variável envolvida e o resultado de uma operação em particular (ou observação pertinente).
12 |
13 | 2 - Executar os passos previstos no algoritmo.
14 |
15 | 3 - Verificar se os resultados obtidos são coerentes com os previstos.
16 |
17 | 4 - Encerrar o teste após um número razoável de resultados corretos obtidos.
18 |
19 | Utilizaremos a sequência:
20 |
21 | 1 - Identifique todas as variáveis no seu programa.
22 |
23 | 2 - Crie uma tabela onde a primeira coluna se chama "Passo", a segunda de chama "Linha". A partir disto, crie uma coluna para cada variável do programa.
24 |
25 | 3 - Na primeira linha da tabela, preencha a coluna "Passo" com "Início", pode deixar a coluna "Linha" em branco e preencha cada coluna das variáveis com os respectivos valores iniciais.
26 |
27 | 4 - Percorra seu código linha a linha, preenchendo a tabela. A coluna "Passo" deverá ser incrementada a cada nova linha na tabela; a coluna "Linha" deve indicar o número da linha no código que está sendo analisada e em cada coluna das variáveis deve constar o respectivo valor para cada variável após a linha de código ser executada.
28 |
29 | 5 - Execute o passo 4 até o programa finalizar.
30 |
31 | Vamos utilizar de exemplo o seguinte algoritmo:
32 |
33 | ```cpp{0}
34 | #include
35 |
36 | int main ()
37 | {
38 | int A = 12, B, C = 10; // 1
39 | // 2
40 | D = 2; // 3
41 | // 4
42 | while(A >= C && C > B) // 5
43 | { // 6
44 | if(A > B) // 7
45 | { // 8
46 | A -= B; // 9
47 | }else // 10
48 | { // 11
49 | A += B; // 12
50 | B *= 2; // 13
51 | }
52 | }
53 | }
54 | ```
55 |
56 | Passo 1: Identificar todas as variáveis e as condições do programa
57 |
58 | No nosso caso, temos os inteiros A, B e C
59 |
60 | Temos também a condição do loop na linha 5
61 |
62 | Passo 2: Criar a tabela
63 |
64 | | Linha | A | B | C | Condição |
65 | | :----------:| :---: | :---: | :----:| :-----------:|
66 |
67 | Passo 3: Preencher a primeira linha da tabela
68 |
69 | | Linha | A | B | C | Condição |
70 | | :----------:| :---: | :---: | :----:| :-----------:|
71 | | 1 | 12 | ? | 10 | -- |
72 |
73 | Passo 4: Percorrer cada linha do programa, preenchendo a tabela
74 |
75 | Apenas escreveremos algo na tabela quando tiver alguma mudança, como no caso pulamos a linha 2
76 |
77 | | Linha | A | B | C | Condição |
78 | | :----------:| :---: | :---: | :----:| :-----------:|
79 | | 1 | 12 | ? | 10 | -- |
80 | | 3 | 12 | 2 | 10 | -- |
81 |
82 | Na linha 5, temos uma condição, que no caso retorna true
83 |
84 | A > B => true && C > A => true resulta em: true
85 |
86 | | Linha | A | B | C | Condição |
87 | | :----------:| :---: | :---: | :----:| :-----------:|
88 | | 1 | 12 | ? | 10 | -- |
89 | | 3 | 12 | 2 | 10 | -- |
90 | | 5 | 12 | 2 | 10 | true |
91 |
92 | Temos outra condição na linha 7,no caso A é maior que B,então retorna true
93 |
94 | | Linha | A | B | C | Condição |
95 | | :----------:| :---: | :---: | :----:| :-----------:|
96 | | 1 | 12 | ? | 10 | -- |
97 | | 3 | 12 | 2 | 10 | -- |
98 | | 5 | 12 | 2 | 10 | true |
99 | | 7 | 12 | 2 | 10 | true |
100 |
101 | * Se preferir, separe as condições
102 |
103 | Na linha 8, temos mudanças em A
104 |
105 | | Linha | A | B | C | Condição |
106 | | :----------:| :---: | :---: | :----:| :-----------:|
107 | | 1 | 12 | ? | 10 | -- |
108 | | 3 | 12 | 2 | 10 | -- |
109 | | 5 | 12 | 2 | 10 | true |
110 | | 7 | 12 | 2 | 10 | true |
111 | | 8 | 10 | 2 | 10 | -- |
112 |
113 | Agora, o loop será repetido novamente,e novamente retornara true,e o loop continua
114 |
115 |
116 | | Linha | A | B | C | Condição |
117 | | :----------:| :---: | :---: | :----:| :-----------:|
118 | | 1 | 12 | ? | 10 | -- |
119 | | 3 | 12 | 2 | 10 | -- |
120 | | 5 | 12 | 2 | 10 | true |
121 | | 7 | 12 | 2 | 10 | true |
122 | | 9 | 10 | 2 | 10 | -- |
123 | | 5 | 10 | 2 | 10 | true |
124 | | 7 | 10 | 2 | 10 | true |
125 | | 9 | 8 | 2 | 10 | -- |
126 |
127 | Dessa vez, o loop principal irá retornar false, por conta que A não é maior ou igual a C
128 |
129 | | Linha | A | B | C | Condição |
130 | | :----------:| :---: | :---: | :----:| :-----------:|
131 | | 1 | 12 | ? | 10 | -- |
132 | | 3 | 12 | 2 | 10 | -- |
133 | | 5 | 12 | 2 | 10 | true |
134 | | 7 | 12 | 2 | 10 | true |
135 | | 9 | 10 | 2 | 10 | -- |
136 | | 5 | 10 | 2 | 10 | true |
137 | | 7 | 10 | 2 | 10 | true |
138 | | 9 | 8 | 2 | 10 | -- |
139 | | 4 | 8 | 2 | 10 | false |
140 |
141 | Pronto, finalizamos nosso teste de mesa
142 |
143 | * Em caso de testes com saída de dados, faça uma tabela separada apenas para a saída.
--------------------------------------------------------------------------------
/docs/tutorial/secao7.md:
--------------------------------------------------------------------------------
1 | # 7 - Vetores (C Arrays)
2 |
3 | Conforme a complexidade de um programa cresce, surge a necessidade de agrupar variáveis e entidades.
4 | Um vetor é uma estrutura (não é a única) que serve para este propósito.
5 |
6 | Um vetor (C Array) é um tipo que consiste de uma sequência de elementos que estão lado a lado na memória.
7 | O número de elementos que essa estrutura é capaz de suportar não muda durante a execução do programa.
8 |
9 | O tamanho do vetor precisa ser conhecido durante a compilação.
10 |
11 | Veremos como criar um array que pode mudar de tamanho durante a execução do programa em outra seção.
12 |
13 | # Exemplos
14 |
15 | ```cpp{0}
16 | #include
17 |
18 | int main ()
19 | {
20 | /*|--------------------------------------|
21 | *| |
22 | *| He4rt Developers |
23 | *| |
24 | *|--------------------------------------|
25 | */
26 |
27 | /**
28 | * Um array pode conter (quase) qualquer tipo.
29 | * Por exemplo: int, float, double, std::string
30 | * Acessar um elemento que está no array leva tempo constante,
31 | * falaremos mais sobre isso na seção
32 | */
33 |
34 | /* Declarando um array de 5 posições e que pode conter apenas elementos do tipo int */
35 | int meu_array[5];
36 |
37 | /**
38 | * Podemos acessar um elemento do array usando a posição na qual ele se encontra.
39 | * O primeiro elemento se encontra na posição 0,
40 | * algo que é padrão na maioria das linguagens de programação.
41 | */
42 |
43 | /* meu_array contem o número 10 na posição 0 */
44 | meu_array[0] = 10;
45 |
46 | meu_array[1] = 20;
47 | meu_array[2] = 30;
48 | meu_array[3] = 40;
49 | meu_array[4] = 50;
50 |
51 | /**
52 | * Nosso array possui 5 posições, começando da posição 0, sendo assim,
53 | * para acessar a última posição, usamos o número 4.
54 | */
55 | }
56 | ```
57 |
58 | Vetores são muito eficientes quando queremos trabalhar com a mesma lógica de variável:
59 |
60 | 
61 |
62 | ```cpp{0}
63 | #include
64 |
65 | int main ()
66 | {
67 | /*|--------------------------------------|
68 | *| |
69 | *| He4rt Developers |
70 | *| |
71 | *|--------------------------------------|
72 | */
73 |
74 | /**
75 | * Podemos usar loops para percorrer um array acessando cada elemento
76 | */
77 |
78 | /* Arrays podem ser inicializados com valores */
79 | int meu_array[5] = {1, 2, 3, 4, 5};
80 |
81 | /**
82 | * Percorrendo todas as posições do array e mostrando cada elemento que está na posição
83 | */
84 |
85 | int posicao = 0;
86 | while(posicao < 5)
87 | {
88 | std::cout << meu_array[posicao] << std::endl;
89 | posicao++;
90 | }
91 | }
92 | ```
93 |
94 | Vetores iniciam na posição `0`,`NÃO` em `1`
95 |
96 | Exemplo de uma vetor => `int vetor[5] = { 3, 7, 4, 10, 4}`
97 |
98 | 
99 |
100 | # Exemplo de Aplicação de Loops em vetores
101 |
102 | ```cpp{0}
103 | #include
104 |
105 | int main ()
106 | {
107 | /*|--------------------------------------|
108 | *| |
109 | *| He4rt Developers |
110 | *| |
111 | *|--------------------------------------|
112 | */
113 |
114 | int idade[5];
115 | bool adulto[5];
116 | int i = 0; // i representará a posicao no vetor
117 |
118 | while(i < 5)
119 | {
120 | std::cout << "Digite a " << (i + 1) << " idade: \n";
121 | std::cin >> idade[i];
122 |
123 | adulto[i] = idade[i] >= 18; // Como o operador >= retorna um booleano, o vetor será corretamente preenchido.
124 |
125 | i++; // Sempre que chegar no final do loop, será interado para conseguirmos dar entrada de dados em outra posição do vetor
126 | }
127 |
128 | i = 0; // Zerando i
129 |
130 | while(i < 5)
131 | {
132 | if(adulto[i]) // Condicao se adulto[posicao] for verdadeira
133 | {
134 | std::cout << idade[i] << " e considerado adulto." << std::endl;
135 | }
136 | else
137 | {
138 | std::cout << idade[i] << " nao e considerado adulto." << std::endl;
139 | }
140 | i++;
141 | }
142 | }
143 |
144 | // Para verificar se adulto[posicao] for negativa, poderiamos usar if(!adulto[i])
145 | ```
146 |
147 | # O Loop FOR
148 |
149 | Como vimos, para percorrer um vetor precisamos de um loop, para percorrer des de seu início até o seu final.
150 |
151 | O `FOR` é muito parecido com o `WHILE`, mas com a vantagem de alguns "recursos" incluídos para facilitar a utilização de loop's em determinadas situações.
152 |
153 | De modo geral, um `for` segue a seguinte forma:
154 |
155 | ```cpp{0}
156 | for(; ; ) {}
157 | ```
158 |
159 | Pode-se definir qualquer quantidade de variáveis no bloco de definições, assim como atualizar qualquer variável no bloco de atualização, mas o bloco de critério de parada deve *sempre* se tratar de uma expressão booleana.
160 |
161 | Normalmente, é utilizado da seguinte maneira:
162 |
163 | ```cpp{0}
164 | for(int i = 0; i ; i++) {}
165 | ```
166 |
167 | `int i = 0` é o valor inicializado.
168 |
169 | `i < ` é a condição para o for continuar.
170 |
171 | `i++` é o valor que vai ser iterado ao final do loop, assim como utilizamos nos exemplos anteriores com `i++` no final de cada loop.
172 |
173 | * Lembrando que poderia ser qualquer outro valor no `i++`, utilizamos como padrão para avançar a próxima posição no vetor
174 |
175 | A utilização do `FOR` acaba facilitando percorrer vetores
176 | ```cpp{0}
177 | #include
178 |
179 | int main ()
180 | {
181 | /*|--------------------------------------|
182 | *| |
183 | *| He4rt Developers |
184 | *| |
185 | *|--------------------------------------|
186 | */
187 |
188 | double v[5] = { 1.123, 2.43, 1.23, 5.42, 5.4 };
189 |
190 | for(int i = 0; i < 5; i++)
191 | {
192 | std::cout << v[i] << std::endl;
193 | }
194 | }
195 | ```
196 |
197 | Para ler, e exibir, dez números letras da linha de comando, pode-se utilizar o código abaixo:
198 |
199 | ```cpp{0}
200 | #include
201 |
202 | int main ()
203 | {
204 | /*|--------------------------------------|
205 | *| |
206 | *| He4rt Developers |
207 | *| |
208 | *|--------------------------------------|
209 | */
210 | char v[10];
211 |
212 | for(int i = 0; i < 10; i++)
213 | {
214 | std::cin >> v[i];
215 | }
216 |
217 | for(int i = 0; i < 10; i++)
218 | {
219 | std::cout << v[i] << " ";
220 | }
221 | }
222 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao71.md:
--------------------------------------------------------------------------------
1 | # 7.1 - std::array e std::vector
2 |
3 | C arrays não são muito flexíveis, algo que dificulta o desenvolvimento de um programa.
4 |
5 | Felizmente, no C++ temos outras opções (que você deve usar): O std::array e std::vector
6 |
7 | # Exemplos
8 |
9 | ```cpp{0}
10 | #include
11 | #include
12 |
13 | int main ()
14 | {
15 | /*|--------------------------------------|
16 | *| |
17 | *| He4rt Developers |
18 | *| |
19 | *|--------------------------------------|
20 | */
21 |
22 | /**
23 | * std::array é o primeiro container que iremos ver.
24 | * A STL(Standard Template Library) oferece uma série de containers.
25 | * Um container é uma estrutura que pode conter uma coleção de objetos.
26 |
27 | * O std::array é uma Struct que possui um C array dentro dela.
28 | * Possui uma implementação simples e várias funções que facilitam o manejo de arrays.
29 | * O tamanho do std::array precisa ser conhecimento durante a compilação.
30 |
31 | * Recomenda-se que você use esse tipo de array ao invés de C arrays.
32 | */
33 |
34 | /* Criando um std::array com 3 posições que podem conter elementos do tipo std::string */
35 | std::array meu_array = {"Hello ", "world", "!"};
36 |
37 | /* Mostrando os elementos do array, funciona igual o C array */
38 | for(int i = 0; i < meu_array.size(); ++i) {
39 | std::cout << meu_array[i];
40 | }
41 |
42 | /* Também podemos usar um ranged loop para percorrer o array */
43 | for(std::string elemento : meu_array) {
44 | std::cout << element;
45 | }
46 | }
47 | ```
48 |
49 | ```cpp{0}
50 | #include
51 | #include
52 |
53 | int main ()
54 | {
55 | /*|--------------------------------------|
56 | *| |
57 | *| He4rt Developers |
58 | *| |
59 | *|--------------------------------------|
60 | */
61 |
62 | /*
63 | * std::vector é um array que pode mudar de tamanho durante a execução do programa
64 | * Isso é possível através do uso de ponteiros
65 | * Ao contrário do C array e std::array, o tamanho do std::vector não precisa
66 | * ser conhecido durante a compilação
67 | */
68 |
69 | /* Criando um std::vector de floats */
70 | std::vector meu_vector;
71 |
72 | /*
73 | * Foi criado um std::vector vazio, sendo assim, o tamanho dele é 0
74 | * Podemos adicionar elementos no std::vector usando as funções push_back() e emplace_back()
75 | * O std::vector aumenta e diminui de tamanho conforme você insere e remove elementos
76 | */
77 | meu_vector.push_back(3.14159);
78 |
79 | /*
80 | * Agora o meu_vector tem o tamanho 1
81 | * Podemos verificar o tamanho do vector do mesmo jeito que
82 | * vericamos o tamanho do std::array. Usando a função size()
83 | */
84 | std::cout << meu_vector.size() // 1
85 |
86 | /*
87 | * Podemos percorrer o std::vector do mesmo jeito que percorremos o std::array
88 | */
89 |
90 | meu_vector.push_back(2.71828)
91 | meu_vector.push_back(1.30357)
92 |
93 | for(double valor : meu_vector) {
94 | std::cout << valor;
95 | }
96 | }
97 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao72.md:
--------------------------------------------------------------------------------
1 | # 7.2 - Matrizes
2 |
3 | Matrizes são vetores acoplados que formam linhas e colunas.
4 |
5 | Por exemplo,temos 5 alunos, e cada aluno possui 5 anos.
6 |
7 | Para facilitar,podemos utilizar matrizes:
8 |
9 | ```cpp{0}
10 | #include
11 | #include
12 | #include
13 |
14 | int main ()
15 | {
16 | /*|--------------------------------------|
17 | *| |
18 | *| He4rt Developers |
19 | *| |
20 | *|--------------------------------------|
21 | */
22 |
23 | int matriz[5][5];
24 |
25 | for(int i = 0;i < 5;i++)
26 | for(int j = 0;j < 5;j++)
27 | std::cin >> matriz[i][j];
28 |
29 | for(int i = 0;i < 5;i++)
30 | for(int j = 0;j < 5;j++)
31 | std::cout << matriz[i][j] << std::endl;
32 | }
33 | ```
34 |
35 | Podemos também utilizar `std::array`:
36 |
37 | ```cpp{0}
38 | #include
39 | #include
40 | #include
41 |
42 | int main ()
43 | {
44 |
45 | /*|--------------------------------------|
46 | *| |
47 | *| He4rt Developers |
48 | *| |
49 | *|--------------------------------------|
50 | */
51 |
52 | //Temos um vetor de vetor, com as linha representando cada aluno, e as colunas cada nota
53 |
54 | std::array , 5> alunos_nota = {{ {{4.5, 6.3, 5.5, 6.1, 7.2}}, // Aluno 0
55 | {{1.2, 4.2, 8.1, 8.3, 8.2}}, // Aluno 1
56 | {{5.2, 4.2, 6.4, 5.6, 7.2}}, // Aluno 2
57 | {{4.2, 5.4, 6.2, 5.2, 7.5}}, // Aluno 3
58 | {{2.2, 4.4, 2.3, 5.5, 3.2}} }}; // Aluno 4
59 |
60 | std::cout << "Notas dos alunos: \n\n";
61 |
62 | for (float i : alunos_nota){ // Percorre cada linha
63 | for (float j : i){ // Percorre cada coluna, assim que chegar ao final da coluna, vai para a próxima linha
64 | std::cout << j << ' ';
65 | }
66 |
67 | std::cout<< std::endl; // A cada linha lida
68 | }
69 | }
70 | ```
71 |
72 | ::: danger
73 |
74 | O std::array é um wrapper por volta de um C array, por possuir uma implementação super simples, a diferença de performance e recursos
75 | utilizados entre o C array padrão e o std::array podem ser considerados nulos.
76 |
77 | :::
78 |
--------------------------------------------------------------------------------
/docs/tutorial/secao8.md:
--------------------------------------------------------------------------------
1 | # 8 - Funções
2 |
3 | Você já sabe que todo programa deve ter uma função chamada main (que é onde o programa inicia a execução quando é executado). No entanto, a medida que os programas começam a ficar cada vez mais longos, a colocação de todo o código dentro da função principal torna-se cada vez mais difícil de trabalhar. As funções fornecem uma maneira de dividir nossos programas em pequenos blocos modulares que são mais fáceis de organizar, testar, usar e reusar. A maioria dos programas usam muitas funções. A biblioteca padrão C++ vem com muitas funções já escritas para você usar, mas é comum escrever funções próprias.
4 |
5 | Considere um caso que pode ocorrer na vida real: você está lendo um livro quando lembra que precisa fazer uma ligação telefônica. Você coloca um marcador em seu livro, faz a ligação e, quando termina a ligação, volta ao local marcado e continua seu livro exatamente onde parou.
6 |
7 | Programas C++ podem funcionar da mesma maneira. Um programa estará executando instruções sequencialmente dentro de uma função quando encontrar uma chamada de função. Uma chamada de função é uma expressão que informa a CPU para interromper a função atual e executar outra função. A CPU “coloca um marcador” no ponto atual de execução e, em seguida, chama (executa) a função nomeada na chamada de função. Quando a função chamada termina, a CPU retorna ao ponto marcado e retoma a execução.
8 |
9 | Primeiro, vamos começar com a sintaxe mais básica para definir uma função. Para esta lição, todas as funções definidas pelo usuário (exceto main) terão o seguinte formato:
10 |
11 | ```cpp{0}
12 | void nome_função ()
13 | {
14 | // código aqui
15 | }
16 | ```
17 |
18 | `void` são funções que não retornam valor algum, também conhecidas como *procedimento*.
19 |
20 | Exemplos:
21 |
22 | ```cpp{0}
23 | #include
24 |
25 | void MostrarMensagem()
26 | {
27 | std::cout << "Hello World" << std::endl;
28 | }
29 |
30 | int main ()
31 | {
32 | /*|--------------------------------------|
33 | *| |
34 | *| He4rt Developers |
35 | *| |
36 | *|--------------------------------------|
37 | */
38 | MostrarMensagem(); // Chamando a função
39 | }
40 | ```
41 |
42 | ```cpp{0}
43 | #include
44 |
45 | void CalcularSoma()
46 | {
47 | int a, b;
48 |
49 | std::cout << "Digite dois numeros em sequencia" << std::endl;
50 | std::cin >> a >> b;
51 |
52 | std::cout << "A soma e: "<< (a + b) << std::endl;
53 | }
54 |
55 | int main ()
56 | {
57 | /*|--------------------------------------|
58 | *| |
59 | *| He4rt Developers |
60 | *| |
61 | *|--------------------------------------|
62 | */
63 | CalcularSoma(); // Chamando a função
64 | }
65 | ```
66 |
67 | Considerado o exemplo anterior, podemos passar variáveis para funções por meio de `parâmetros` direto do `main`
68 |
69 | ```cpp{0}
70 | #include
71 |
72 | void CalcularSoma(int a, int b) // Parâmetros a e b, recebidos em sequência no main
73 | {
74 | std::cout << "A soma e: "<< (a + b) << std::endl;
75 | }
76 |
77 | int main ()
78 | {
79 | int a, b;
80 |
81 | std::cout << "Digite dois numeros em sequencia" << std::endl;
82 | std::cin >> a >> b;
83 |
84 | CalcularSoma(a, b); // Chamando a função
85 | }
86 | ```
87 |
88 | Como já discutimos em seções anteriores, quando declaramos `tipo a` ou `tipo a = valor` ele existe apenas no escopo onde foi criado, e que chamamos de declaração na memória `stack` (teremos uma seção especificamente para memória `stack` e `heap`)
89 |
90 | Então os parâmetros existem `APENAS` nas funções, no caso a função `CalcularSoma()` não reconhece os inteiros declarados no `main()`
91 |
92 | Por conta disso, parâmetros podem ter nomes diferentes em relação ao o que passamos para ela, já que não possuem relação nenhuma
93 |
94 | Exemplo:
95 |
96 | ```cpp{0}
97 | #include
98 |
99 | void CalcularSoma(int a, int b)
100 | {
101 | a += b;
102 | std::cout << "A soma e: "<< a << std::endl;
103 | }
104 |
105 | void CalcularSubtracao(int a, int b)
106 | {
107 | a -= b;
108 | std::cout << "A subtracao e: "<< a << std::endl;
109 | }
110 |
111 | void CalcularMultiplicacao(int a, int b)
112 | {
113 | a *= b;
114 | std::cout << "A multiplicacao e: "<< a << std::endl;
115 | }
116 |
117 | void CalcularDivisao(int a, int b)
118 | {
119 | a /= b;
120 | std::cout << "A divisao e: "<< a << std::endl;
121 | }
122 |
123 | int main ()
124 | {
125 | /*|--------------------------------------|
126 | *| |
127 | *| He4rt Developers |
128 | *| |
129 | *|--------------------------------------|
130 | */
131 |
132 | int n1, n2;
133 | char opcao;
134 |
135 | std::cout << "Digite dois numeros em sequencia: \n";
136 | std::cin >> n1 >> n2;
137 |
138 | do
139 | {
140 | std::cout << "Digite a opcao: (A) Soma / (B) Subtracao / (C) Multiplicacao / (D) Divisao \n";
141 | std::cin >> opcao;
142 |
143 | switch(opcao)
144 | {
145 | case 'A':
146 | {
147 | CalcularSoma(n1, n2);
148 | break;
149 | }
150 | case 'B':
151 | {
152 | CalcularSubtracao(n1, n2);
153 | break;
154 | }
155 | case 'C':
156 | {
157 | CalcularMultiplicacao(n1, n2);
158 | break;
159 | }
160 | case 'D':
161 | {
162 | CalcularDivisao(n1, n2);
163 | break;
164 | }
165 | default:
166 | {
167 | break;
168 | }
169 | }
170 |
171 | }while(opcao != 'A' && opcao != 'B' && opcao != 'C' && opcao != 'D'); // Evita de ter um input errado no std::cin >> opcao;
172 | }
173 | ```
174 |
175 | Mas, temos um porém:
176 |
177 | `n1` continua com o mesmo valor, pois `a` só existe dentro da função
178 |
179 | Da mesma forma que funções voids retornam nada, temos também funções int,float,char... que retornam o seu tipo
180 |
181 | ```cpp{0}
182 | #include
183 |
184 | int CalcularSoma(int a, int b)
185 | {
186 | a += b;
187 | return a; // Precisamos usar o return no que queremos retornar
188 | }
189 |
190 | int CalcularSubtracao(int a, int b)
191 | {
192 | a -= b;
193 | return a;
194 | }
195 |
196 | int CalcularMultiplicacao(int a, int b)
197 | {
198 | a *= b;
199 | return a;
200 | }
201 |
202 | int CalcularDivisao(int a, int b)
203 | {
204 | a /= b;
205 | return a;
206 | }
207 |
208 | int main ()
209 | {
210 | /*|--------------------------------------|
211 | *| |
212 | *| He4rt Developers |
213 | *| |
214 | *|--------------------------------------|
215 | */
216 |
217 | int n1, n2, resultado;
218 | char opcao;
219 |
220 | std::cout << "Digite dois numeros em sequencia: \n";
221 | std::cin >> n1 >> n2;
222 |
223 | do
224 | {
225 | std::cout << "Digite a opcao: (A) Soma / (B) Subtracao / (C) Multiplicacao / (D) Divisao \n";
226 | std::cin >> opcao;
227 |
228 | switch(opcao)
229 | {
230 | case 'A':
231 | {
232 | resultado = CalcularSoma(n1, n2); // resultado recebe o retorno da função
233 | break;
234 | }
235 | case 'B':
236 | {
237 | resultado = CalcularSubtracao(n1, n2);
238 | break;
239 | }
240 | case 'C':
241 | {
242 | resultado = CalcularMultiplicacao(n1, n2);
243 | break;
244 | }
245 | case 'D':
246 | {
247 | resultado = CalcularDivisao(n1, n2);
248 | break;
249 | }
250 | default:
251 | {
252 | break;
253 | }
254 | }
255 |
256 | }while(opcao != 'A' && opcao != 'B' && opcao != 'C' && opcao != 'D'); // Evita de ter um input errado no std::cin >> opcao;
257 |
258 | std::cout << "O resultado e: " << resultado << std::endl;
259 | }
260 | ```
261 |
262 | Como você já deve ter notado, a função main retorna um inteiro e podemos explicitar isso
263 |
264 | ```cpp{0}
265 | #include
266 |
267 | int main ()
268 | {
269 | /*|--------------------------------------|
270 | *| |
271 | *| He4rt Developers |
272 | *| |
273 | *|--------------------------------------|
274 | */
275 |
276 | std::cout << "Hello World" << std::endl;
277 |
278 | return 0;
279 | }
280 | ```
281 |
282 | Podemos retornar a função main para indicar que tudo ocorreu bem por conseguir chegar no final do escopo da função principal.
283 |
284 | Caso nada seja retornado pela função main, 0 é assumido.
285 |
286 | Temos a biblioteca `` que possui `EXIT_SUCCESS`, considerado uma convensão para programas em C++.
287 |
288 | ```cpp{0}
289 | #include
290 | #include
291 |
292 | int main ()
293 | {
294 | /*|--------------------------------------|
295 | *| |
296 | *| He4rt Developers |
297 | *| |
298 | *|--------------------------------------|
299 | */
300 |
301 | std::cout << "Hello World" << std::endl;
302 |
303 | return EXIT_SUCCESS;
304 | }
305 | ```
306 |
307 | ::: warning
308 |
309 | Como já falamos, recomendamos fortemente que leia a documentação das bibliotecas que vamos apresentar durante o curso, assim conseguindo extrair ao máximo o que a linguagem C++ fornece ao desenvolvedor.
310 |
311 | :::
312 |
--------------------------------------------------------------------------------
/docs/tutorial/secao81.md:
--------------------------------------------------------------------------------
1 | # 8.1 - Protótipo de Função
2 |
3 | Nos exemplos, criamos nossas funções acima da nossa função main.
4 |
5 | Se criarmos abaixo, por conta da ordem de compilação o C++ acaba não reconhecendo a função que está sendo chamada,pois ela ainda não existe
6 |
7 | Mas temos uma forma de manipular isso:
8 |
9 | ```cpp{0}
10 | #include
11 |
12 | void ExibirNome(std::string nome);
13 |
14 | int main()
15 | {
16 | /*|--------------------------------------|
17 | *| |
18 | *| He4rt Developers |
19 | *| |
20 | *|--------------------------------------|
21 | */
22 |
23 | std::string a = "Joao";
24 | ExibirNome(a);
25 | }
26 |
27 | void ExibirNome(std::string nome)
28 | {
29 | std::cout <<"O nome e: "<< nome << std::endl;
30 | }
31 | ```
32 |
33 | O que fizemos foi:
34 |
35 | Indicar que existe uma função `ExibirNome`, sendo um `protótipo`, e apos a função main executar sua lógica.
36 |
37 | # `#define`
38 |
39 | Podemos por meio do `#define` indicar algo a ser substituido antes de ser executado
40 |
41 | Antes do início da compilação, todos os nossos `#define`'s são substituidos pelos seus respectivos valores.
42 |
43 | ```cpp{0}
44 | #include
45 | #include
46 | #include
47 |
48 | #define QNT_ALUNOS 3
49 |
50 | void exibir_nome(std::array arr);
51 |
52 | int main()
53 | {
54 | /*|--------------------------------------|
55 | *| |
56 | *| He4rt Developers |
57 | *| |
58 | *|--------------------------------------|
59 | */
60 |
61 | std::array nomes; // Um array de string de 3 posições
62 |
63 | for(std::string &element : nomes) // & significa que estamos passando a referência de uma posição em nomes, teremos uma seção explicanto o que é uma referência.
64 | std::cin >> element;
65 |
66 | exibir_nome(nomes);
67 | }
68 |
69 | void exibir_nome(std::array arr)
70 | {
71 | for(std::string &element : arr)
72 | std::cout << element << " ";
73 | }
74 | ```
75 |
--------------------------------------------------------------------------------
/docs/tutorial/secao82.md:
--------------------------------------------------------------------------------
1 | # 8.2 - Argumentos da função main
2 |
3 | Também podemos passar argumentos para a função main, como vimos ela é uma função como qualquer outra
4 |
5 | Temos várias formas de receber argumentos, mas o tipo mais utilizado é ``
6 |
7 | ```cpp{0}
8 | #include
9 |
10 | int main(int argc,char *argv[])
11 | {
12 | /*|--------------------------------------|
13 | *| |
14 | *| He4rt Developers |
15 | *| |
16 | *|--------------------------------------|
17 | */
18 |
19 | // Argc é a quantidade de argumentos recebidos, argc já inicia com um argumento, o proprio nome do .exe
20 |
21 | // Argv são os nomes dos argumentos em si, em um vetor de string's
22 |
23 | std::cout << argc << std::endl; // 1 como padrão
24 |
25 | std::cout << argv[0] << std::endl; // argv[0] sempre tera o nome do .exe
26 | }
27 |
28 | ```
29 |
30 | Para passar argumentos para ela, precisa abrir o .exe pelo cmd, e na sua frente os argumentos, separados por espaço
31 |
32 | `nome_do_programa.exe argumento1 argumento2 ...`
33 |
34 | Assim podemos modificar a forma de execução do nosso código
35 |
36 | ```cpp{0}
37 | #include
38 | #include
39 |
40 | int main(int argc, char **argv)
41 | {
42 | /*|--------------------------------------|
43 | *| |
44 | *| He4rt Developers |
45 | *| |
46 | *|--------------------------------------|
47 | */
48 |
49 | int a = 5, b = 2;
50 |
51 | if(argc > 1) // Recebeu argumentos além da inicial
52 | {
53 | std::cout << (a + b) << std::endl;
54 | }
55 | else
56 | {
57 | std::cout << a << " " << b << std::endl;
58 | }
59 |
60 | return EXIT_SUCCESS;
61 | }
62 | ```
63 |
64 | ::: danger
65 |
66 | Dependendo de sua IDE você pode ter problemas na hora de comparar argumentos da função main, recomendamos a utilização do cli.cpp
67 |
68 | :::
69 |
--------------------------------------------------------------------------------
/docs/tutorial/secao83.md:
--------------------------------------------------------------------------------
1 | # 8.3 - Recursão
2 |
3 | Recursão é um conceito não exclusivo do C++, onde uma função chama a si mesma até que uma condição seja alcançada.
4 |
5 | Tudo que pode ser resolvido por loops, pode ser resolvido por recursão.
6 | Tudo que pode ser resolvido por recursão, pode ser resolvido por loops.
7 |
8 | Por que usar recursão? Legibilidade.
9 |
10 | Algumas soluções são mais fáceis de serem expressadas por recursão.
11 | Assim como outras são mais fáceis através de loops.
12 |
13 | # Exemplos
14 |
15 | ```cpp{0}
16 | #include
17 |
18 | int factorial(int number)
19 | {
20 | /**
21 | * Toda função recursiva precisa de uma condição de parada,
22 | * caso contrário entrará em um loop infinito
23 | * Nesse caso, a função retorna quando encontrar
24 | * essa condição de parada
25 | * No caso da função fatorial, existem duas condições de parada:
26 | * quando number == 0 ou quanto number == 1, pois:
27 | * 0! = 1
28 | * 1! = 1
29 | */
30 | if (number <= 1)
31 | {
32 | return 1;
33 | }
34 |
35 | /**
36 | * Se o número não for <= 1, chamamos a função factorial novamente,
37 | * passando o número - 1 como parâmetro
38 | * Repetimos esse processo até que a condição de parada seja alcançada
39 | */
40 | return number * factorial(number - 1);
41 | }
42 |
43 | /**
44 | * Usando operador ternário
45 | */
46 | int factorial(int number)
47 | {
48 | return number <= 1 ? 1 : number * factorial(number - 1);
49 | }
50 |
51 | int fibonacci(int number)
52 | {
53 | /**
54 | * Condição de parada
55 | */
56 | if (number <= 2)
57 | {
58 | return number;
59 | }
60 |
61 | return fibonacci(number - 2) + fibonacci(number - 1);
62 | }
63 |
64 | /**
65 | * Usando operador ternário
66 | */
67 | int fibonacci(int number)
68 | {
69 | return number <= 2 ? number : fibonacci(number - 2) + fibonacci(number - 1);
70 | }
71 |
72 | int main ()
73 | {
74 | /*|--------------------------------------|
75 | *| |
76 | *| He4rt Developers |
77 | *| |
78 | *|--------------------------------------|
79 | */
80 |
81 | /**
82 | * Calcular fatorial de um número é um exemplo clássico de recursão
83 | */
84 | std::cout << factorial(5); // 120
85 |
86 | /**
87 | * Calcular o nth termo da sequência de fibonacci é outro exemplo clássico
88 | */
89 |
90 | std::cout << fibonacci(10); // 55 começando do 0
91 |
92 | /**
93 | * Visualização de como uma função recursiva funciona.
94 | * int result = factorial(5)
95 | * 5 * factorial(4)
96 | * 4 * factorial(3)
97 | * 3 * factorial(2)
98 | * 2 * factorial(1)
99 | * 2
100 | * 6
101 | * 24
102 | * 120
103 |
104 | * std::cout << result; // 120
105 | */
106 | }
107 | ```
108 |
--------------------------------------------------------------------------------
/docs/tutorial/secao84.md:
--------------------------------------------------------------------------------
1 | # 8.4 - Funções Lambda
2 |
3 | Funções lambda foram implementadas no C++11 e versões posteriores, onde podemos declarar objetos de funções em forma anônima, normalmente utilizadas quando precisamos de uma função que não precisará existir após ser utilizada.
4 |
5 | Sintaxe:
6 | `[]() -> T {}`
7 |
8 | CAPTURAS `[]`
9 | PARÂMETROS `()`
10 | TIPO DO RETORNO `-> T`
11 | CORPO DA FUNÇÃO `{}`
12 |
13 | Chamamos uma função lambda da mesma forma que chamamos uma função normal: `nome_variavel()`
14 |
15 | Exemplo:
16 |
17 | ```cpp{0}
18 | #include
19 | #include
20 |
21 | int main(int argc, const char **argv)
22 | {
23 | /*|--------------------------------------|
24 | *| |
25 | *| He4rt Developers |
26 | *| |
27 | *|--------------------------------------|
28 | */
29 |
30 | int a(3), b(5);
31 |
32 | /* Quando criamos uma lambda, precisamos usar 'auto', pois o tipo de cada função é único. */
33 |
34 | auto soma = [](int n1, int n2) {
35 | return n1 + n2;
36 | };
37 |
38 | std::cout << soma(a, b);
39 |
40 | return EXIT_SUCCESS;
41 | }
42 | ```
43 |
44 | Podemos retornar uma função lambda por outra função:
45 |
46 | ```cpp{0}
47 | auto func()
48 | {
49 | return [](int var) { return var; }
50 | }
51 | ```
52 |
53 | Também podemos criar lambdas que são executadas imediatamente. Esse tipo de função é conhecido como IILE(Immediately Invoked Lambda Expression) ou IIFE(Immediately Invoked Function Expression)
54 |
55 | Exemplos:
56 |
57 | ```cpp{0}
58 | #include
59 | #include
60 |
61 | int main(int argc,const char **argv)
62 | {
63 | /*|--------------------------------------|
64 | *| |
65 | *| He4rt Developers |
66 | *| |
67 | *|--------------------------------------|
68 | */
69 |
70 | []{ std::cout << "He4rt Developers"; }();
71 |
72 | return EXIT_SUCCESS;
73 | }
74 | ```
75 |
76 | ```cpp{0}
77 | #include
78 | #include
79 |
80 | int main()
81 | {
82 | /*|--------------------------------------|
83 | *| |
84 | *| He4rt Developers |
85 | *| |
86 | *|--------------------------------------|
87 | */
88 |
89 | std::string he4rt = "He4rt";
90 | std::string developers = "Developers";
91 |
92 | [](std::string h, std::string d){ std::cout << h + " " + d ;}( he4rt, developers);
93 |
94 | // Saida: He4rt Developers
95 |
96 | return EXIT_SUCCESS;
97 | }
98 | ```
99 |
--------------------------------------------------------------------------------
/docs/tutorial/secao85.md:
--------------------------------------------------------------------------------
1 | # 8.5 - Keyword Static
2 |
3 | A keyword `static` possui comportamentos diferentes dependendo da situação, mas iremos falar dela exclusivamente dentro de funções que não pertencem à classes.
4 |
5 | Se é uma variável em uma função, ela não pode ser acessada de fora da função, como qualquer outra variável local.
6 |
7 | Antes que qualquer função em uma unidade de tradução seja executada (possivelmente após a execução inicial iniciada), as variáveis com duração de armazenamento estático (escopo de namespace) nessa unidade de tradução serão "constante inicializadas".
8 |
9 | O efeito disso se resume que uma variavel estática em uma função continua "existindo" na função.
10 |
11 | Exemplo:
12 |
13 | ```cpp{0}
14 | #include
15 |
16 | void stc()
17 | {
18 | static int i = 0;
19 | i++;
20 |
21 | std::cout << i << std::endl;
22 | }
23 |
24 | int main()
25 | {
26 | int a = 0;
27 |
28 | while(true)
29 | {
30 | if(a >= 10) { break; };
31 | stc();
32 | a++;
33 | }
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/tutorial/secao9.md:
--------------------------------------------------------------------------------
1 | # 9 - Header
2 |
3 | A medida que os programas aumentam (e fazem uso de mais arquivos), torna-se cada vez mais entediante declarar todas as funções que você deseja usar definidas em um arquivo diferente. Não seria legal se você pudesse colocar todas as suas declarações encaminhadas em um único local e importá-las quando precisar?
4 |
5 | Arquivos de código C++ (.cpp) não são os únicos arquivos comumente vistos em programas C++. O outro tipo de arquivo é chamado de arquivo de cabeçalho. Os arquivos de cabeçalho geralmente têm uma extensão .h, mas você os verá ocasionalmente com uma extensão .hpp ou nenhuma extensão. O objetivo principal de um arquivo de cabeçalho é propagar declarações para arquivos de código.
6 |
7 | Considere a inclusão do cabeçalho `` em um programa utilizando `std::cout`. No entanto, esse programa nunca forneceu uma definição ou declaração para `std::cout`, então como o compilador sabe o que é `std::cout`?
8 |
9 | A resposta é que `std::cout` foi declarado a seguir no arquivo de cabeçalho `iostream`. Quando #incluímos ``, solicitamos que o pré-processador copie todo o conteúdo (incluindo declarações de encaminhamento para `std::cout`) do arquivo chamado `iostream` para o arquivo que faz o `#include`.
10 |
11 | Considere o que aconteceria se o cabeçalho iostream não existisse. Onde quer que você use `std::cout`, você deverá digitar ou copiar manualmente todas as declarações relacionadas a std :: cout na parte superior de cada arquivo que usou `std::cout`! Isso exigiria muito conhecimento sobre como o `std::cout` foi implementado e seria uma tonelada de trabalho. Pior ainda, se um protótipo de função for alterado, teremos que atualizar manualmente todas as declarações de encaminhamento. É muito mais fácil #incluir o iostream!
12 |
13 | Quando se trata de funções vale lembrar que os arquivos de cabeçalho geralmente contêm apenas declarações de função e objeto, não definições de função e objeto (caso contrário, pode resultar em uma violação da regra de uma definição). `std::cout` é declarado para a frente no cabeçalho do `iostream`, mas definido como parte da biblioteca padrão C++, que é automaticamente vinculada ao seu programa durante a fase do vinculador.
14 |
15 | Agora vamos trabalhar com mais arquivos, execute o exemplo a seguir:
16 |
17 | `media.cpp`
18 | ```cpp{0}
19 | int media(int a, int b, int c)
20 | {
21 | return (a + b + c)/3;
22 | }
23 | ```
24 |
25 | `main.cpp`
26 | ```cpp{0}
27 | #include
28 |
29 | int media(int a, int b, int c) ; // declaração direta usando protótipo de função
30 |
31 | int main()
32 | {
33 | std::cout << "A media e: " << media(1, 4, 3) << std::endl;
34 | return 0;
35 | }
36 | ```
37 |
38 | (Não se esqueça de adicionar o arquivo media.cpp ao seu projeto para que ele seja compilado).
39 |
40 | ::: warning
41 | No `Falcon C++` você pode criar um projeto, e isso irá facilitar na hora de trabalhar com múltiplos arquivos.
42 | :::
43 |
44 | Neste exemplo, usamos uma declaração de encaminhamento para que o compilador saiba qual é o identificador adicionado ao compilar main.cpp. Como mencionado anteriormente, a adição manual de declarações avançadas para todas as funções que você deseja usar que residem em outro arquivo pode ser entediante rapidamente.
45 |
46 | Vamos escrever um arquivo de cabeçalho para nos livrar desse fardo. Escrever um arquivo de cabeçalho é surpreendentemente fácil, pois os arquivos de cabeçalho consistem apenas em duas partes:
47 |
48 | O conteúdo real do arquivo de cabeçalho, que deve ser a declaração de encaminhamento de todos os identificadores que queremos que outros arquivos possam ver.
49 |
50 | Adicionar um arquivo de cabeçalho a um projeto funciona de forma análoga à adição de um arquivo de origem. Se estiver usando um IDE, siga as mesmas etapas e escolha “Cabeçalho” em vez de “Origem” quando solicitado. Se estiver usando a linha de comando, basta criar um novo arquivo no seu editor favorito.
51 |
52 | `media.hpp`
53 | ```cpp{0}
54 | int media(int a, int b, int c); // protótipo de função para add.h
55 | ```
56 |
57 | `media.cpp`
58 | ```cpp{0}
59 | #include "media.h"
60 |
61 | int media(int a, int b, int c)
62 | {
63 | return (a + b + c) /3;
64 | }
65 | ```
66 |
67 | `main.cpp`
68 | ```cpp{0}
69 | #include
70 |
71 | int media(int a, int b, int c) ; // declaração direta usando protótipo de função
72 |
73 | int main()
74 | {
75 | std::cout << "A media e: " << media(1, 4, 3) << std::endl;
76 | return 0;
77 | }
78 | ```
79 |
80 | Quando o pré-processador processa a linha #include `media.hpp`, ele copia o conteúdo de media.h no arquivo atual naquele momento. Como nosso `media.hpp` contém uma declaração direta para a função `media`, essa declaração direta será copiada para main.cpp. O resultado final é um programa funcionalmente igual ao em que adicionamos manualmente a declaração de encaminhamento no topo do arquivo main.cpp.
81 |
82 | Consequentemente, nosso programa será compilado e vinculado corretamente.
83 |
84 | Se você receber um erro do compilador indicando que media.h não foi encontrado, verifique se o arquivo está realmente com o nome add.h. Dependendo de como você o criou e o nomeou, é possível que o arquivo tenha sido nomeado como add (sem extensão) ou media.h.txt ou media.hpp. Verifique também se ele está no mesmo diretório que o restante dos seus arquivos de código.
85 |
86 | Se você receber um erro do vinculador sobre a adição de função não ser definida, inclua media.cpp em seu projeto para que a definição de adição de função possa ser vinculada ao programa.
87 |
88 | ## Aviso
89 |
90 | O pré-processador *não* checa se o arquivo a ser incluindo está sendo incluindo mais de uma vez. Isto pode se tornar um problema
91 | em projetos maiores, com diversos `.cpp`, visto que uma inclusão dupla de _header_ causará um problema de compilação.
92 |
93 | Para contornar este problema, podemos usar uma estratégia chamada de _header guard_, que consiste em criar uma macro que registra se aquele arquivo já foi incluido previamente.
94 |
95 | Exemplo:
96 |
97 | Em `media.hpp`
98 | ```cpp{0}
99 |
100 | #ifndef __MEDIA // Caso __MEDIA não for definido ..
101 | #define __MEDIA // .. definiremos __MEDIA e incluiremos o header
102 | int media(int a, int b, int c);
103 |
104 | // ...
105 |
106 | #endif // Finalizando o ifndef
107 | ```
108 |
109 | Ou seja, quando o arquivo for incluído uma vez, `__MEDIA` será definido. Quando o arquivo for incluído novamente, o pré-processador verá que `__MEDIA` já foi definido e não incluirá o _header_.
110 |
111 | Uma outra alternativa menos portátil é usar um *pragma*.
112 | ```cpp{0}
113 |
114 | #pragma once // Garante que o arquivo seja incluido apenas uma vez.
115 | int media(int a, int b, int c);
116 | ```
--------------------------------------------------------------------------------
/docs/tutorial/secao91.md:
--------------------------------------------------------------------------------
1 | # 9.1 - Protetores de Cabeçalho
2 |
3 | Em seções anteriores observamos que um identificador de variável ou função pode ter apenas uma definição (a regra de uma definição). Assim, um programa que define um identificador de função mais de uma vez causará um erro de compilação:
4 |
5 | ```cpp{0}
6 | #include
7 |
8 | int num() // Definição da função num
9 | {
10 | return 5;
11 | }
12 |
13 | int num() // Erro de compilação / Funções duplicadas
14 | {
15 | return 5;
16 | }
17 |
18 | int main()
19 | {
20 | std::cout << num();
21 | }
22 | ```
23 |
24 | Embora esses programas sejam fáceis de corrigir (remova a definição duplicada), com arquivos de cabeçalho, é muito fácil acabar em uma situação em que uma definição em um arquivo de cabeçalho é incluída mais de uma vez. Isso pode acontecer quando um arquivo de cabeçalho `#include` outro arquivo de cabeçalho (o que é comum).
25 |
26 | Considere o seguinte exemplo acadêmico:
27 |
28 | `a.hpp`
29 | ```cpp{0}
30 | float teste()
31 | {
32 | return 1.2f;
33 | }
34 | ```
35 |
36 | `b.hpp`
37 | ```cpp{0}
38 | #include "a.hpp"
39 | ```
40 |
41 | `main.cpp`
42 | ```cpp{0}
43 | #include "a.hpp"
44 | #include "b.hpp"
45 |
46 | int main()
47 | {
48 | return 0;
49 | }
50 | ```
51 |
52 | Este programa aparentemente inocente não será compilado! Aqui está o que está acontecendo. Primeiro, main.cpp inclui a.hpp, que copia a definição da função `teste()` para main.cpp. Então main.cpp inclui b.hpp, que inclui a.hpp em si. Isso copia o conteúdo de a.h (incluindo a definição da função teste()) para b.hpp, que é copiada para main.cpp.
53 |
54 | Assim, depois de resolver todos os `#include`, o main.cpp acaba assim:
55 |
56 | ```cpp{0}
57 | float teste()
58 | {
59 | return 1.2f;
60 | }
61 |
62 | float teste()
63 | {
64 | return 1.2f;
65 | }
66 |
67 | int main()
68 | {
69 | return 0;
70 | }
71 | ```
72 |
73 | Definições duplicadas e um erro de compilação. Cada arquivo, individualmente, está bem. No entanto, como o main.cpp acaba incluindo o conteúdo de a.h duas vezes, encontramos problemas. Se b.hpp precisar de teste() e main.cpp precisar de b.hpp e a.hpp, como você resolveria esse problema?
74 |
75 | # Protetores de Cabeçalho
76 |
77 | ```cpp{0}
78 | #ifndef NOME_UNICO
79 | #define NOME_UNICO
80 |
81 | // Declarações
82 |
83 | #endif
84 | ```
85 |
86 | Quando esse cabeçalho é incluido, o pré-processador verifica se NOME_UNICO foi definido anteriormente. Se for a primeira vez que incluímos o cabeçalho, NOME_UNICO não será definido. Consequentemente, `#define NOME_UNICO` e inclui o conteúdo do arquivo. Se o cabeçalho for incluído novamente no mesmo arquivo, NOME_UNICO já terá sido definido desde a primeira vez em que o conteúdo do cabeçalho foi incluído e o conteúdo do cabeçalho será ignorado (graças ao #ifndef).
87 |
88 | Todos os seus arquivos de cabeçalho devem ter proteções de cabeçalho neles. NOME_UNICO pode ser o nome que você quiser, mas por convenção é definido como o nome completo do arquivo de cabeçalho, digitado em maiúsculas, usando sublinhados para espaços ou pontuação. Por exemplo, a.hpp teria o protetor de cabeçalho:
89 |
90 | ```cpp{0}
91 | #ifndef A_H
92 | #define A_H
93 |
94 | float teste()
95 | {
96 | return 1.2f;
97 | }
98 |
99 | #endif
100 | ```
101 |
102 | Vamos voltar ao exemplo a.hpp, usando o a.hpp com protetores de cabeçalho. Para uma boa forma, também adicionaremos protetores de cabeçalho em b.hpp
103 |
104 | `a.hpp`
105 | ```cpp{0}
106 | #ifndef A_H
107 | #define A_H
108 |
109 | float teste()
110 | {
111 | return 1.2f;
112 | }
113 |
114 | #endif
115 | ```
116 |
117 | `b.hpp`
118 | ```cpp{0}
119 | #ifndef B_H
120 | #define B_H
121 |
122 | #include "a.hpp"
123 |
124 | #endif
125 | ```
126 |
127 | `main.cpp`
128 |
129 | ```cpp{0}
130 | #include "a.hpp"
131 | #include "b.hpp"
132 |
133 | int main()
134 | {
135 | return 0;
136 | }
137 | ```
138 |
139 | Depois que o pré-processador resolve todas as inclusões, este programa fica assim:
140 |
141 | ```cpp{0}
142 | #ifndef A_H // a.hpp incluido de main.cpp,
143 | #define A_H // A_H foi definido aqui
144 |
145 | // Todo esse conteudo foi colocado aqui
146 | float teste()
147 | {
148 | return 1.2f;
149 | }
150 |
151 |
152 | #endif // A_H
153 |
154 | #ifndef B_H // b.hpp incluido de main.cpp
155 | #define B_H
156 | #ifndef B_H // a.hpp incluido de b.hpp, A_H foi incluido
157 | #define A_H // Resto do conteudo foi incluido
158 |
159 | float teste()
160 | {
161 | return 1.2f;
162 | }
163 |
164 | #endif // A_H
165 | #endif // B_H
166 |
167 | int main()
168 | {
169 | return 0;
170 | }
171 | ```
172 |
173 | Geralmente, pedimos que você não inclua definições de função em seus cabeçalhos. Então, você deve estar se perguntando por que deve incluir protetores de cabeçalho se eles o protegem de algo que você não deve fazer.
174 |
175 | Existem alguns casos em que mostraremos no futuro onde é necessário colocar definições de não função em um arquivo de cabeçalho. Por exemplo, o C++ permitirá que você crie seus próprios tipos. Esses tipos definidos pelo usuário geralmente são definidos nos arquivos de cabeçalho, portanto, a definição pode ser propagada para os arquivos de código que precisam usá-los. Sem uma proteção de cabeçalho, seus arquivos de código podem acabar com várias cópias idênticas dessas definições, o que causará um erro de compilação de definição duplicada.
176 |
177 | Portanto, mesmo que não seja estritamente necessário ter proteções de cabeçalho neste ponto da série de tutoriais, estamos estabelecendo bons hábitos agora, para que você não precise desaprender os maus hábitos mais tarde.
178 |
179 | #pragma once
180 |
181 | Muitos compiladores suportam uma forma mais simples e alternativa de proteção de cabeçalho usando a diretiva #pragma:
182 |
183 | `exemplo.hpp`
184 | ```cpp{0}
185 | #pragma once
186 |
187 | // codico
188 | ```
189 |
190 | O #pragma já serviu ao mesmo objetivo que os protetores de cabeçalho e tem o benefício adicional de ser mais curto e menos propenso a erros.
191 |
192 | No entanto, o #pragma não é uma parte oficial da linguagem C ++ e nem todos os compiladores o suportam (embora a maioria dos compiladores modernos o faça).
193 |
194 | Para fins de compatibilidade, recomendamos a aderência aos protetores de cabeçalho tradicionais. Eles não são muito mais trabalhosos e têm garantia de suporte em todos os compiladores compatíveis.
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "He4rt-CPP-Tutorial",
3 | "version": "1.0.0",
4 | "description": "Tutorial de C++ da He4rt Developers",
5 | "scripts": {
6 | "dev": "vuepress dev docs",
7 | "build": "vuepress build docs"
8 | },
9 | "repository": "https://github.com/Novout/He4rt-CPP-Tutorial.git",
10 | "author": "He4rt Developers",
11 | "license": "MIT",
12 | "private": false,
13 | "devDependencies": {
14 | "vuepress": "^1.5.0"
15 | },
16 | "dependencies": {
17 | "vuepress-theme-yuu": "^2.3.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------