Conceitos Fundamentais em C e C++

Introdução às Linguagens C e C++

Embora C e C++ compartilhem uma herança comum, elas possuem distinções importantes. Em C, a declaração de variáveis geralmente precisa preceder seu uso dentro de um bloco de código. C não inclui a biblioteca <iostream> e, consequentemente, não utiliza cin ou cout para operações de entrada/saída, nem requer using namespace std;.

C++, por outro lado, é uma linguagem orientada a objetos que oferece maior flexibilidade na declaração de variáveis e um conjunto rico de bibliotecas padrão, como <iostream> para I/O e <algorithm> para operações comuns em coleções de dados.

Tamanhos de Tipos de Dados Básicos

A representação de dados na memória é fundamental. Um byte consiste em 8 bits. Os tamanhos de tipos de dados comuns podem variar ligeiramente entre sistemas, mas tipicamente:

  • Um int ocupa 4 bytes.
  • Um double ocupa 8 bytes.

Representação Binária de Números

Números inteiros são frequentemente representados usando o complemento de dois. Por exemplo, em um sistema de 16 bits:

  • O valor 32767 é representado como 0111 1111 1111 1111.
  • O valor -32768 é representado como 1000 0000 0000 0000.

O bit mais significativo (o primeiro bit à esquerda) atua como um indicador de sinal: 0 para positivo e 1 para negativo.

Fundamentos da Sintaxe

Comentários no Código

Comentários são essenciais para documentar o código. Em C e C++, existem duas formas principais:

  • Comentário de linha única: Começa com // e se estende até o final da linha.
  • Comentário de múltiplas linhas: Delimitado por /* no início e */ no final.

Operações de Entrada e Saída

As linguagens C e C++ oferecem diferentes mecanismos para lidar com a entrada e saída de dados:

  • C++ (<iostream>): Usa std::cin para entrada e std::cout para saída, com operadores >> e <<, respectivamente.
  • C (<cstdio>): Utiliza scanf para entrada formatada e printf para saída formatada. Estes são geralmente mais rápidos para I/O em massa.

Para caracteres individuais, as funções getchar() e putchar() (da biblioteca <cstdio>) são usadas. Por exemplo, putchar(66); exibirá o caractere 'B' (ASCII 66).

Especificadores de Formato (printf / scanf)

Ao usar scanf e printf, especificadores de formato são cruciais:

  • %s: Para strings de caracteres (scanf para strings para ao encontrar espaço ou Enter).
  • gets(): Lê uma linha inteira, incluindo espaços, até encontrar um Enter (Nota: gets() é perigoso e desaconselhado devido a vulnerabilidades de estouro de buffer; prefira fgets() ou std::getline em C++).
  • %c: Para caracteres (char). Caracteres literais são definidos com aspas simples, e.g., 'A'.
  • %f: Para números de ponto flutuante (float).
  • %lf: Para números de ponto flutuante de precisão dupla (double).
  • %lld: Para inteiros longos (long long).

Formatação de saída:

  • %Nd: Alinha um inteiro à direita em um campo de N caracteres. Ex: %5d para 15 resulta em   15.
  • %-Nd: Alinha um inteiro à esquerda em um campo de N caracteres. Ex: %-5d para 15 resulta em 15  .

float valorDecimal = 45.6789f;
printf("Valor formatado: %12.3f\n", valorDecimal);
// Saída: Valor formatado:        45.679
// O número é impresso com 3 casas decimais e ocupa um campo total de 12 caracteres.

O caractere de tabulação \t avança a saída para a próxima parada de tabulação, alinhando o texto em colunas.

Precedência de Operadores

A ordem em que as operações são avaliadas é definida pela precedência dos operadores. Alguns grupos de operadores comuns incluem:

  • Aritméticos: +, -, *, /, %, ++, --.
  • Lógicos: && (E), || (OU), ! (NÃO).
  • Atribuição: =, +=, -=, *=, etc.

Macros com #define

Diretivas de pré-processador como #define realizam substituição de texto antes da compilação. Elas podem ser usadas para definir constantes ou "macros com parâmetros".


#define SOMA_VALORES(a, b) ((a) + (b))
#define DOBRO(val) ((val) * 2)

Embora úteis, macros podem introduzir problemas de depuração e segurança de tipo. Em C++, funções inline ou const são geralmente preferíveis. Uma macro pode ser desdefinida com #undef para limitar seu escopo.

Tipos de Dados Fundamentais

C e C++ oferecem uma variedade de tipos de dados para armazenar diferentes tipos de informações:

void

O tipo void indica a ausência de tipo. É usado em funções que não retornam valor ou para ponteiros genéricos (void*).

bool

Representa valores lógicos: true ou false. Geralmente ocupa 1 byte.

char

Armazena um único caractere. Caracteres literais são delimitados por aspas simples, como 'X'. As sequências de escape são caracteres especiais:

  • \n: Nova linha.
  • \\: Barra invertida literal.
  • \': Apóstrofo literal.
  • \0: Caractere nulo (frequentemente usado como terminador de string em C).

A aritmética com caracteres é possível devido à sua representação ASCII (ou equivalente). Por exemplo, para converter uma letra maiúscula para minúscula, pode-se adicionar 32 ao seu valor ASCII.

float e double

Usados para números de ponto flutuante (com casas decimais):

  • float: Precisão simples, geralmente 6-7 dígitos significativos. Literais float podem ser sufixados com f, e.g., 1.27f.
  • double: Precisão dupla, geralmente 15-16 dígitos significativos. É o tipo padrão para literais de ponto flutuante sem sufixo.

Números podem ser expressos em notação científica, como 1.23E3 (equivalente a 1.23 * 10^3 ou 1230).

Tipos Inteiros com e sem Sinal

Tipos inteiros podem ser signed (com sinal, permitindo números positivos e negativos) ou unsigned (sem sinal, apenas não negativos).

  • short: Geralmente de -32768 a 32767.
  • unsigned short: Geralmente de 0 a 65535.
  • int: Geralmente de -2.147.483.648 a 2.147.483.647.

Operador Condicional (Ternário)

Uma forma concisa de expressar uma condição:

condição ? expressão_se_verdadeira : expressão_se_falsa;

Se a condição for verdadeira, o resultado é expressão_se_verdadeira; caso contrário, é expressão_se_falsa.


int a = 10, b = 20;
int maior = (a > b) ? a : b; // 'maior' será 20

Estruturas de Controle

Estruturas de Repetição (Loops)

Utilizadas para executar blocos de código repetidamente. Podem ser combinadas com break (para sair do loop) e continue (para pular para a próxima iteração).

  • for: Ideal para um número fixo de iterações.
  • while: Repete enquanto uma condição é verdadeira (pode não executar se a condição for falsa desde o início).
  • do...while: Garante que o bloco de código seja executado pelo menos uma vez, e depois repete enquanto a condição for verdadeira.

Estrutura Condicional switch

Usada para selecionar um de muitos blocos de código a serem executados, com base no valor de uma expressão inteira.


int opcao = 2; // Exemplo de variável de controle
switch (opcao) {
    case 1:
        // Bloco de código para a opção 1
        printf("Opcao selecionada: Um\n");
        break; // Importante para evitar "fall-through"
    case 2:
        // Bloco de código para a opção 2
        printf("Opcao selecionada: Dois\n");
        break;
    default:
        // Bloco padrão, executado se nenhum dos casos anteriores corresponder
        printf("Opcao desconhecida\n");
}

É crucial incluir break; após cada case para evitar que a execução "caia" para os case seguintes.

Arrays (Vetores)

Arrays são coleções de elementos do mesmo tipo, armazenados em posições contíguas de memória. A indexação em C e C++ é baseada em zero (o primeiro elemento tem índice 0). É importante estar atento aos limites do array para evitar erros de acesso à memória.

Estruturas (struct)

Estruturas permitem agrupar diferentes tipos de dados sob um único nome, criando um tipo de dado composto.


struct Estudante {
    int matricula;
    float media;
    char nome[50]; // Um array de char para o nome
};

// Criação de uma variável do tipo Estudante
Estudante alunoPrincipal;
alunoPrincipal.matricula = 1001;
alunoPrincipal.media = 8.5f;
strcpy(alunoPrincipal.nome, "Carlos"); // Usando strcpy para atribuir uma string

// Criação de um vetor de estruturas
Estudante turma[30];
turma[0].matricula = 2001;
turma[0].media = 7.8f;
strcpy(turma[0].nome, "Ana");

Conversão de Tipos

A conversão de tipos pode ocorrer implicitamente (coerção) ou explicitamente (casting). Ao converter um número de ponto flutuante para um inteiro, a parte fracionária é truncada (descartada). Em expressões com tipos mistos, um tipo de "menor" precisão pode ser promovido ao tipo de "maior" precisão para evitar perda de dados.

Strings Estilo C

Strings em C são arrays de caracteres terminados por um caractere nulo ('\0').

  • scanf("%s", nomeArray);: Lê uma string para um array de caracteres.
  • gets(nomeArray);: Lê uma linha inteira (desaconselhado).
  • puts("Mensagem");: Escreve uma string seguida de uma nova linha.

Funções

Funções de Manipulação de Strings (C-style)

A biblioteca <string.h> (C) ou <cstring> (C++) oferece funções para manipular strings de caracteres:

  • strlen(s): Retorna o comprimento da string s (sem contar o '\0').
  • strcat(destino, fonte): Concatena a string fonte ao final de destino.
  • strcpy(destino, fonte): Copia a string fonte para destino.
  • strcmp(s1, s2): Compara lexicograficamente s1 e s2. Retorna um valor negativo se s1 < s2, zero se s1 == s2, e positivo se s1 > s2.

Passagem de Parâmetros por Referência

Por padrão, parâmetros são passados por valor para funções, significando que uma cópia do valor é usada e o argumento original não é modificado. Para modificar o argumento original, pode-se usar passagem por referência (em C++ com &) ou ponteiros (em C e C++).


void trocarValores(int &val1, int &val2) {
    int temp = val1;
    val1 = val2;
    val2 = temp;
}

Quando um array é passado para uma função, o que é realmente passado é o endereço de seu primeiro elemento. Isso significa que modificações dentro da função afetam o array original.

Recursão e Iteração

  • Iteração (Abordagem Bottom-Up): Resolve um problema construindo a solução a partir de casos base conhecidos, geralmente com loops.
  • Recursão (Abordagem Top-Down): Resolve um problema dividindo-o em subproblemas menores da mesma natureza. É crucial ter um caso base para parar a recursão. Técnicas como "memoização" (caching de resultados de subproblemas) podem otimizar funções recursivas.

Standard Template Library (STL)

A STL em C++ é uma coleção de classes e funções de template que fornecem estruturas de dados e algoritmos comuns.

std::vector

Um vector é um array dinâmico que pode redimensionar-se automaticamente. Ele armazena elementos de um tipo específico (T) e oferece acesso aleatório.

  • std::vector<T> meuVetor;: Declara um vetor. T pode ser int, std::string, ou até mesmo outro std::vector para arrays multidimensionais.
  • meuVetor.empty(): Retorna true se o vetor estiver vazio.
  • meuVetor.size(): Retorna o número de elementos no vetor.
  • meuVetor.push_back(elemento): Adiciona um elemento ao final.
  • meuVetor.pop_back(): Remove o último elemento.
  • meuVetor[n]: Acesso direto ao elemento na posição n.
  • meuVetor.begin() e meuVetor.end(): Retornam iteradores para o início e logo após o final do vetor, respectivamente.
  • Algoritmos como std::sort(meuVetor.begin(), meuVetor.end()) podem ser usados para ordenar o vetor.
  • std::unique(meuVetor.begin(), meuVetor.end()): Remove elementos adjacentes duplicados (o vetor deve estar ordenado para que funcione corretamente).

Outros Componentes da STL

A STL inclui uma vasta gama de contêineres e algoritmos:

  • Contêineres Sequenciais: std::deque (fila de duas extremidades), std::list (lista duplamente encadeada), std::stack (pilha), std::queue (fila), std::priority_queue (fila de prioridade).
  • Contêineres Associativos: std::set (conjunto ordenado de valores únicos), std::multiset (conjunto ordenado com valores duplicados), std::map (mapa/dicionário chave-valor único), std::multimap (mapa chave-valor com chaves duplicadas).
  • Utilitários: std::string (para strings modernas em C++), std::pair (para agrupar dois valores), std::bitset (para manipular sequências de bits).

Muitos contêineres compartilham funções comuns como begin(), end(), size(), empty(), clear() (para remover todos os elementos), e swap() (para trocar o conteúdo com outro contêiner do mesmo tipo).

Além disso, o cabeçalho <algorithm> oferece funções genéricas como std::find, std::reverse, std::lower_bound (retorna um iterador para o primeiro elemento não menor que um valor) e std::upper_bound (retorna um iterador para o primeiro elemento maior que um valor).

Tags: C C++ STL tipos de dados Estruturas de Controle

Publicado em 7-17 06:06