# 5. Formatacao de Strings e Cores

## Introdução

Em C e C++, a formatação de strings e a saída de dados são fundamentais para depuração, logs e interação com o usuário. C utiliza funções da biblioteca padrão como `printf` e `sprintf`, enquanto C++ oferece `iostream` com operadores `<<` e `>>`. Diferente do PHP, que tem tipagem dinâmica e formatação flexível, C/C++ exige especificadores de formato rigorosos e gerenciamento cuidadoso de buffers para evitar vulnerabilidades.

***

## Output em C (`stdio.h`)

### Funções Básicas

| Função       | Descrição                            |
| ------------ | ------------------------------------ |
| `printf()`   | Saída formatada para stdout          |
| `fprintf()`  | Saída formatada para arquivo         |
| `sprintf()`  | Saída formatada para string (buffer) |
| `snprintf()` | Versão segura com limite de tamanho  |
| `puts()`     | String simples com quebra de linha   |
| `putchar()`  | Caractere único                      |

### `printf` - Formatação Básica

```c
#include <stdio.h>

int main() {
    int idade = 25;
    float altura = 1.75;
    char nome[] = "Alice";
    
    printf("Nome: %s\n", nome);
    printf("Idade: %d anos\n", idade);
    printf("Altura: %.2f metros\n", altura);
    printf("Hex: %x, Octal: %o\n", 255, 255);
    
    return 0;
}
```

### Especificadores de Formato `printf`

| Especificador | Tipo                              | Exemplo                               |
| ------------- | --------------------------------- | ------------------------------------- |
| `%d` / `%i`   | Inteiro decimal                   | `printf("%d", 42);`                   |
| `%u`          | Inteiro sem sinal                 | `printf("%u", 42u);`                  |
| `%x` / `%X`   | Hexadecimal (minúsculo/maiúsculo) | `printf("%x", 255);` // ff            |
| `%o`          | Octal                             | `printf("%o", 8);` // 10              |
| `%f`          | Float / Double                    | `printf("%f", 3.14);`                 |
| `%e` / `%E`   | Notação científica                | `printf("%e", 3.14);` // 3.140000e+00 |
| `%c`          | Caractere                         | `printf("%c", 'A');`                  |
| `%s`          | String                            | `printf("%s", "texto");`              |
| `%p`          | Ponteiro                          | `printf("%p", &var);`                 |
| `%%`          | Porcentagem literal               | `printf("%%");`                       |

### Modificadores de Formato

```c
// Largura mínima
printf("%10d\n", 42);     // "        42"
printf("%-10d\n", 42);    // "42        " (esquerda)

// Precisão (decimais)
printf("%.2f\n", 3.14159); // "3.14"
printf("%.5s\n", "abcdef"); // "abcde"

// Zero padding
printf("%05d\n", 42);     // "00042"

// Comprimento (long, long long)
printf("%ld\n", 1000000L);
printf("%lld\n", 10000000000LL);
```

### `fprintf` - Saída para Arquivo

```c
#include <stdio.h>

FILE* arquivo = fopen("log.txt", "w");
if (arquivo != NULL) {
    fprintf(arquivo, "Erro: %s na linha %d\n", "conexão falhou", 42);
    fclose(arquivo);
}
```

### `sprintf` e `snprintf` - Saída para String

```c
// sprintf (inseguro - pode estourar buffer)
char buffer[50];
sprintf(buffer, "Valor: %d", 42);  // OK se buffer suficiente

// snprintf (seguro - limita tamanho)
char buffer[20];
int escrito = snprintf(buffer, sizeof(buffer), "Valor: %d", 123456789);
if (escrito >= sizeof(buffer)) {
    printf("Truncado! Precisaria de %d bytes\n", escrito + 1);
}
```

{% hint style="warning" %}
Nunca use `sprintf()` sem controle de tamanho. Use `snprintf()` para evitar buffer overflow.
{% endhint %}

***

## Input em C (`scanf`)

### `scanf` - Leitura Formatada

```c
int idade;
char nome[50];
float altura;

printf("Digite nome, idade e altura: ");
scanf("%s %d %f", nome, &idade, &altura);
```

**Especificadores `scanf`:**

| Especificador | Descrição                   |
| ------------- | --------------------------- |
| `%s`          | String (sem espaços)        |
| `%d`          | Inteiro decimal             |
| `%f`          | Float                       |
| `%c`          | Caractere                   |
| `%[^\n]`      | Linha inteira (até newline) |

### `fgets` - Leitura Segura de Strings

```c
char linha[100];
printf("Digite algo: ");
fgets(linha, sizeof(linha), stdin);  // Limita tamanho
linha[strcspn(linha, "\n")] = 0;     // Remove newline
```

{% hint style="warning" %}
Evite `gets()`. Foi removido do padrão C11 por ser inseguro, pois não limita a entrada.
{% endhint %}

***

## Output em C++ (`iostream`)

### `cout` - Saída Básica

```cpp
#include <iostream>
#include <string>

int main() {
    int idade = 25;
    double altura = 1.75;
    std::string nome = "Alice";
    
    std::cout << "Nome: " << nome << std::endl;
    std::cout << "Idade: " << idade << " anos" << std::endl;
    std::cout << "Altura: " << altura << " m" << std::endl;
    
    return 0;
}
```

### Manipuladores de Formatação

```cpp
#include <iostream>
#include <iomanip>

int main() {
    // Base numérica
    std::cout << std::hex << 255 << std::endl;   // ff
    std::cout << std::oct << 255 << std::endl;   // 377
    std::cout << std::dec << 255 << std::endl;   // 255
    
    // Largura e preenchimento
    std::cout << std::setw(10) << 42 << std::endl;      // "        42"
    std::cout << std::left << std::setw(10) << 42 << std::endl; // "42        "
    std::cout << std::setfill('0') << std::setw(5) << 42 << std::endl; // "00042"
    
    // Precisão decimal
    std::cout << std::fixed << std::setprecision(2) << 3.14159 << std::endl; // "3.14"
    std::cout << std::scientific << 3.14159 << std::endl; // "3.141590e+00"
    
    // Booleanos
    std::cout << std::boolalpha << true << std::endl;  // "true"
    
    return 0;
}
```

### `cin` - Input em C++

```cpp
#include <iostream>
#include <string>

int main() {
    int idade;
    std::string nome;
    
    std::cout << "Digite nome e idade: ";
    std::cin >> nome >> idade;  // Lê até espaço
    
    // Ler linha inteira
    std::string linha;
    std::cin.ignore();  // Limpa buffer
    std::getline(std::cin, linha);
    
    return 0;
}
```

***

## Formatação Avançada em C

### `string.h` - Manipulação de Strings

```c
#include <string.h>

char str1[50] = "Hello";
char str2[] = " World";

// Concatenação
strcat(str1, str2);  // "Hello World"

// Cópia
strcpy(str1, "Novo texto");

// Tamanho
size_t len = strlen(str1);

// Comparação
if (strcmp(str1, "Novo texto") == 0) {
    printf("Iguais\n");
}
```

### Funções Seguras (C11 - opcional)

```c
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>

char buffer[10];
strcpy_s(buffer, sizeof(buffer), "seguro");  // Verifica limites
```

### Conversão de Strings para Números

```c
#include <stdlib.h>

// String para inteiro
int val = atoi("123");        // Simples, sem verificação de erro
long val2 = strtol("123", NULL, 10);  // Com verificação

// String para float
double val3 = strtod("3.14", NULL);
```

***

## Formatação Avançada em C++

### `std::stringstream`

Permite formatação em string usando manipulação de streams.

```cpp
#include <sstream>
#include <iomanip>

std::stringstream ss;
ss << "Valor: " << std::setw(10) << std::hex << 255;
std::string resultado = ss.str();  // "Valor:        ff"
```

### `std::format` (C++20)

Formatação moderna similar a Python/JavaScript.

```cpp
#include <format>

int idade = 25;
std::string nome = "Alice";

// C++20
std::string msg = std::format("Nome: {}, Idade: {}", nome, idade);
std::cout << msg << std::endl;

// Especificadores
std::string hex = std::format("{:#x}", 255);   // "0xff"
std::string pad = std::format("{:10}", 42);    // "        42"
std::string pi = std::format("{:.2f}", 3.14159); // "3.14"
```

### `std::to_string` (C++11)

Conversão simples para string.

```cpp
std::string s1 = std::to_string(42);      // "42"
std::string s2 = std::to_string(3.14159); // "3.141590"
```

***

## Códigos ANSI para Cores (CLI)

Em terminais compatíveis, é possível usar cores com códigos ANSI.

### Cores Básicas

```c
#include <stdio.h>

#define RESET   "\033[0m"
#define VERMELHO "\033[31m"
#define VERDE   "\033[32m"
#define AMARELO "\033[33m"
#define AZUL    "\033[34m"
#define MAGENTA "\033[35m"
#define CIANO   "\033[36m"
#define BRANCO  "\033[37m"

// Negrito
#define NEGRITO "\033[1m"

int main() {
    printf(VERMELHO "Erro crítico!" RESET "\n");
    printf(VERDE "Sucesso!" RESET "\n");
    printf(AMARELO "Aviso!" RESET "\n");
    printf(AZUL "Informação" RESET "\n");
    
    // Combinado
    printf(NEGRITO VERMELHO "ERRO FATAL" RESET "\n");
    
    return 0;
}
```

### Função de Cores em C

```c
#include <stdio.h>

typedef enum {
    COR_PRETO = 30,
    COR_VERMELHO = 31,
    COR_VERDE = 32,
    COR_AMARELO = 33,
    COR_AZUL = 34,
    COR_MAGENTA = 35,
    COR_CIANO = 36,
    COR_BRANCO = 37
} CorTexto;

void print_color(CorTexto cor, const char* texto) {
    printf("\033[%dm%s\033[0m", cor, texto);
}

int main() {
    print_color(COR_VERMELHO, "Erro!");
    printf("\n");
    print_color(COR_VERDE, "Sucesso!");
    printf("\n");
    return 0;
}
```

### C++ com Cores

```cpp
#include <iostream>

class Color {
public:
    static constexpr const char* RED = "\033[31m";
    static constexpr const char* GREEN = "\033[32m";
    static constexpr const char* YELLOW = "\033[33m";
    static constexpr const char* BLUE = "\033[34m";
    static constexpr const char* RESET = "\033[0m";
};

int main() {
    std::cout << Color::RED << "Erro!" << Color::RESET << std::endl;
    std::cout << Color::GREEN << "Sucesso!" << Color::RESET << std::endl;
    return 0;
}
```

***

## Formatação para Logs

### Log Estruturado em C

```c
#include <stdio.h>
#include <time.h>

typedef enum {
    LOG_DEBUG,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR
} NivelLog;

void log_msg(NivelLog nivel, const char* arquivo, int linha, const char* fmt, ...) {
    const char* niveis[] = {"DEBUG", "INFO", "WARN", "ERROR"};
    const char* cores[] = {"\033[36m", "\033[32m", "\033[33m", "\033[31m"};
    
    time_t agora;
    time(&agora);
    struct tm* tm_info = localtime(&agora);
    
    char timestamp[20];
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm_info);
    
    printf("%s[%s] %s [%s:%d] ", cores[nivel], niveis[nivel], timestamp, arquivo, linha);
    
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
    
    printf("\033[0m\n");
}

#define LOG_DEBUG(...) log_msg(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INFO(...)  log_msg(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define LOG_WARN(...)  log_msg(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define LOG_ERROR(...) log_msg(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)

int main() {
    LOG_INFO("Programa iniciado");
    LOG_DEBUG("Valor de x: %d", 42);
    LOG_WARN("Operação lenta");
    LOG_ERROR("Falha na conexão: %s", "timeout");
    return 0;
}
```

### Log em C++

```cpp
#include <iostream>
#include <chrono>
#include <format>

enum class LogLevel { DEBUG, INFO, WARN, ERROR };

class Logger {
private:
    LogLevel nivelMinimo;
    
    static constexpr const char* levelToString(LogLevel level) {
        switch (level) {
            case LogLevel::DEBUG: return "DEBUG";
            case LogLevel::INFO:  return "INFO";
            case LogLevel::WARN:  return "WARN";
            case LogLevel::ERROR: return "ERROR";
        }
        return "UNKNOWN";
    }
    
    static constexpr const char* levelColor(LogLevel level) {
        switch (level) {
            case LogLevel::DEBUG: return "\033[36m";
            case LogLevel::INFO:  return "\033[32m";
            case LogLevel::WARN:  return "\033[33m";
            case LogLevel::ERROR: return "\033[31m";
        }
        return "\033[0m";
    }
    
public:
    Logger(LogLevel nivel = LogLevel::INFO) : nivelMinimo(nivel) {}
    
    template<typename... Args>
    void log(LogLevel nivel, std::string_view fmt, Args&&... args) {
        if (nivel < nivelMinimo) return;
        
        auto now = std::chrono::system_clock::now();
        auto time_t = std::chrono::system_clock::to_time_t(now);
        
        std::cout << levelColor(nivel)
                  << "[" << levelToString(nivel) << "] "
                  << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S")
                  << " " << std::vformat(fmt, std::make_format_args(args...))
                  << "\033[0m" << std::endl;
    }
};

int main() {
    Logger logger(LogLevel::DEBUG);
    logger.log(LogLevel::INFO, "Programa iniciado");
    logger.log(LogLevel::DEBUG, "Valor de x: {}", 42);
    logger.log(LogLevel::ERROR, "Falha na conexão: {}", "timeout");
    return 0;
}
```

***

## Saída para Arquivos

### C - `fprintf`

```c
FILE* log = fopen("app.log", "a");  // Append
if (log) {
    fprintf(log, "[%ld] Operação realizada\n", time(NULL));
    fclose(log);
}
```

### C++ - `fstream`

```cpp
#include <fstream>

std::ofstream arquivo("app.log", std::ios::app);
if (arquivo.is_open()) {
    arquivo << "Operação realizada" << std::endl;
    arquivo.close();
}
```

***

## Boas Práticas

{% stepper %}
{% step %}

### Use `snprintf` em vez de `sprintf`

```c
// Ruim
char buf[100];
sprintf(buf, "%s", entrada_usuario);  // Buffer overflow!

// Bom
char buf[100];
snprintf(buf, sizeof(buf), "%s", entrada_usuario);
```

{% endstep %}

{% step %}

### Valide retornos de funções

```c
if (fprintf(arquivo, "dado\n") < 0) {
    perror("Erro ao escrever");
}
```

{% endstep %}

{% step %}

### Use `fgets` em vez de `scanf` para strings

```c
// Ruim
char nome[50];
scanf("%s", nome);  // Sem limite

// Bom
char nome[50];
fgets(nome, sizeof(nome), stdin);
nome[strcspn(nome, "\n")] = 0;  // Remove newline
```

{% endstep %}

{% step %}

### Prefira C++ streams para código moderno

* Type-safe (não há especificadores incorretos)
* Extensível (sobrecarga de operadores)
* Gerenciamento automático de recursos
  {% endstep %}

{% step %}

### Detecte ambiente para cores

```c
#include <unistd.h>

int tem_cor() {
    return isatty(STDOUT_FILENO);
}

if (tem_cor()) {
    printf("\033[31mErro!\033[0m\n");
} else {
    printf("Erro!\n");
}
```

{% endstep %}
{% endstepper %}

***

## Vulnerabilidades Comuns

| Vulnerabilidade         | Descrição                 | Mitigação                          |
| ----------------------- | ------------------------- | ---------------------------------- |
| Format String           | `printf(usuario_input)`   | Usar `printf("%s", usuario_input)` |
| Buffer Overflow         | `sprintf` sem limite      | Usar `snprintf`                    |
| Integer Overflow        | `printf("%d", grande)`    | Verificar limites antes            |
| Uninitialized read      | Variável não inicializada | Sempre inicializar                 |
| Missing null terminator | String sem `\0`           | Garantir espaço para terminator    |

### Format String Attack (Exemplo Perigoso)

```c
// Vulnerável!
printf(usuario_input);  // Se usuário digitar "%x%x%x", lê stack

// Correto
printf("%s", usuario_input);
```

***

## Resumo para Segurança

| Prática           | Risco                | Mitigação                        |
| ----------------- | -------------------- | -------------------------------- |
| `printf(entrada)` | Format String Attack | Usar `printf("%s", entrada)`     |
| `sprintf()`       | Buffer overflow      | Usar `snprintf()`                |
| `gets()`          | Buffer overflow      | Usar `fgets()`                   |
| `scanf("%s")`     | Buffer overflow      | Usar `fgets()` ou `%Ns`          |
| `strcpy()`        | Buffer overflow      | Usar `strncpy()` ou `strcpy_s()` |

***

## Recursos Adicionais

* Manual: `man printf`, `man scanf`, `man snprintf`
* Documentação C++: [cppreference.com - iostream](https://en.cppreference.com/w/cpp/io)
* OWASP: [Format String Attack](https://owasp.org/www-community/attacks/Format_string_attack)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/programacao-e-linguagens/c-and-c++/5.-formatacao-de-strings-e-cores.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
