├── .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 | Logo 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/images/0)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/0)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/1)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/1)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/2)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/2)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/3)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/3)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/4)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/4)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/5)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/5)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/6)](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/links/6)[![](https://sourcerer.io/fame/Novout/Novout/He4rt-CPP-Tutorial/images/7)](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 | 4 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 22 | 23 | 24 | 26 | 27 | 28 | 34 | 42 | 50 | 58 | 67 | 68 | 69 | 70 | 71 | 72 | 78 | 80 | 84 | 88 | 93 | 101 | 105 | 111 | 118 | 126 | 129 | 130 | 131 | 132 | 136 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 149 | 151 | 162 | 175 | 177 | 182 | 183 | 184 | 189 | 191 | 196 | 197 | 202 | 204 | 209 | 211 | 213 | 224 | 237 | 239 | 244 | 245 | 246 | 251 | 253 | 258 | 259 | 260 | 261 | 263 | 264 | 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 | ![Falcon](../.vuepress/assets/falcon.jpg) 15 | 16 | - CodeBlocks 17 | 18 | ![Code::Blocks](../.vuepress/assets/codeblocks.png) 19 | 20 | - CodeBlocks 21 | 22 | ![Qt Creator](../.vuepress/assets/qt.png) 23 | 24 | - Repl.it 25 | 26 | ![Repl.it](../.vuepress/assets/replit.png) 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 | ![Falcon pt_1](../.vuepress/assets/falcon_pt1.png) 10 | 11 | - Após baixar, abra o `.exe` 12 | 13 | - Selecione a linguagem de sua preferência 14 | 15 | ![Falcon pt_2](../.vuepress/assets/falcon_pt2.png) 16 | 17 | - Clique em próxima até chegar nesta tela abaixo, e selecione estas opções: 18 | 19 | ![Falcon pt_3](../.vuepress/assets/falcon_pt3.png) 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 | ![Falcon pt_4](../.vuepress/assets/falcon_pt4.png) 26 | 27 | - Avance e pronto, temos a tela inicial do Falcon C++! 28 | 29 | ![Falcon pt_5](../.vuepress/assets/falcon_pt5.png) 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 | ![Falcon pt_6](../.vuepress/assets/falcon_pt6.png) 36 | 37 | - Ao clicar no menu `Arquivo`, temos estas opções: 38 | 39 | ![Falcon pt_7](../.vuepress/assets/falcon_pt7.png) 40 | 41 | - Abrindo o `Novo`, temos estas opções: 42 | 43 | ![Falcon pt_8](../.vuepress/assets/falcon_pt8.png) 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 | ![Falcon pt_9](../.vuepress/assets/falcon_pt9.png) 50 | 51 | - As outras opções do menu `Arquivo` são sugestivas, como abrir um arquivo, salvar e fechar 52 | 53 | ![Falcon pt_10](../.vuepress/assets/falcon_pt10.png) 54 | 55 | - Na aba `Executar`, temos estas opções: 56 | 57 | ![Falcon pt_11](../.vuepress/assets/falcon_pt11.png) 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 | ![Falcon pt_12](../.vuepress/assets/falcon_pt12.png) 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 | ![Compilador_pt1](../.vuepress/assets/compilador_pt1.png) 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 | ![Compilador_pt2](../.vuepress/assets/compilador_pt2.png) 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 | ![vetor_pt1](../.vuepress/assets/vetor_pt1.png) 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 | ![vetor_pt2](../.vuepress/assets/vetor_pt2.png) 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 | --------------------------------------------------------------------------------