Processar carateres

Ler e escrever

Podemos usar scanf() e printf() para ler e escrever carateres.

  scanf("%c", &ch); // ler um carater
  printf("%c", ch); // escrever um carater

Mas é mais comum usar as funções mais básicas:

  ch = getchar(); // ler um carater
  putchar(ch);    // escrever um carater

Reservamos scanf() e printf() para leitura e escrita formatada (e.g. números).

Ler carateres

   int getchar(void);

Exemplo

Contar o número de linhas na entrada padrão.

#include <stdio.h>

int main(void) {
    int ch;    // código de um carater
    int lines = 0;  // número de linhas
    do {
        ch = getchar();  // ler um carater
        if(ch == '\n')   // nova linha?
            lines ++;
    } while(ch != EOF);
    printf("%d linhas\n", lines);
}

Exemplo (2)

Versão mais "idiomática": leitura do próximo carater na condição do ciclo.

#include <stdio.h>

int main(void) {
    int ch;    // código de um carater
    int lines = 0;  // número de linhas
    while ((ch=getchar()) != EOF) {
      if(ch == '\n')  // nova linha?
         lines++;
    }
    printf("%d linhas\n", lines);
}

Exemplo maior: ROT13



https://en.wikipedia.org/wiki/ROT13

Programa

#include <stdio.h>

/* Rodar 13 posições as letras A-Z */
int rot13(int ch) {
  if(ch >= 'A' && ch <= 'Z') 
     ch = ((ch - 'A' + 13) % 26) + 'A';
  return ch;
}

int main(void) {
    int ch;
    while ((ch=getchar()) != EOF) 
       putchar(rot13(ch));
}

Execução

$ cat texto.txt
"TO BE OR NOT TO BE; THAT IS THE QUESTION"
    -- W. SHAKESPEARE

$ gcc -o rot13 rot13.c
$ ./rot13 < texto.txt > rodado.txt

$ cat rodado.txt
"GB OR BE ABG GB OR; GUNG VF GUR DHRFGVBA"
    -- J. FUNXRFCRNER

$ ./rot13 < rodado.txt
"TO BE OR NOT TO BE; THAT IS THE QUESTION"
    -- W. SHAKESPEARE

Funções de biblioteca

Algumas funções

#include <ctype.h>
  
int islower(int ch);  // letra minúscula a..z
int isupper(int ch);  // letra maiúscula A..Z
int isalpha(int ch);  // a..z ou A..Z
int isdigit(int ch);  // algarimo decimal 0..9

int tolower(int ch); // converter em minúscula
int toupper(int ch); // converter em maiúscula

Atenção: apenas funcionam para ASCII simples — e.g. letras sem acentos.

Algumas funções

Exemplo: contar letras e algarismos

#include <stdio.h>
#include <ctype.h>

int main(void) {
  int ch;
  int letras = 0, algarismos = 0;

  while((ch=getchar()) != EOF) {
    if (isalpha(ch))
       letras++;
    else if(isdigit(ch))
       algarismos++;
  }
  printf("%d, %d\n", letras, algarismos);
}

Instrução switch

Instrução switch

Podemos usar uma sequência de if/else para escolher entre múltiplos casos:

if(nota == 4)
  printf("Excelente");
else if(nota == 3)
  printf("Bom");
else if(nota == 2)
  printf("Razoável");
else if(nota == 1)
  printf("Fraco");
else
  printf("Nota inválida");

Instrução switch

Em alternativa, podemos usar uma instrução switch:

switch(nota) {
  case 4:  printf("Excelente");
           break;
  case 3:  printf("Bom");
           break;
  case 2:  printf("Razoável");
           break;
  case 1:  printf("Fraco");
           break;
  default: printf("Nota inválida");
           break;
}

Instrução switch

  switch ( expressão ) {
    case constante1: instruções
    ...
    case constanteN: instruções 

    default: instruções 
  }

Instrução switch

   case 33:  ...
   case 'A': ...
   case (100-1)/2: ...

Instrução switch

Instrução switch

Podemos agrupar multiplos case com uma só sequência de instruções:

switch(nota) {
  case 4:
  case 3:
  case 2: printf("Aprovado");
          break;
  case 1: printf("Reprovado");
          break;
  default: printf("Nota inválida");
           break;
}

Instrução switch

Podemos escrever de forma mais sucinta juntando vários case.

switch(nota) {
  case 4: case 3: case 2: 
          printf("Aprovado");
          break;
  case 1: printf("Reprovado");
          break;
  default: printf("Nota inválida");
           break;
}

Efeito do break

Efeito do break

switch(nota) {
  case 4:  printf("Excelente");
  case 3:  printf("Bom");
  case 2:  printf("Razoável");
  case 1:  printf("Fraco");
  default: printf("Nota inválida");
}

Se a nota for 3, imprime

BomRazoávelFracoNota inválida

Exemplo: contar vogais e consoantes


#include <stdio.h>
#include <ctype.h>

int main(void) {
  int ch, vogais = 0, consoantes = 0;
  while ((ch=getchar()) != EOF) {
    ch = toupper(ch);
    switch (ch) {
    case 'A': case 'E': 
    case 'I': case 'O': case 'U':
        vogais ++;
        break;
    default:
        if(isalpha(ch)) consoantes ++;
    }
  }
  printf("%d, %d\n", vogais, consoantes);
}

Execução

$ cat texto2.txt
"To be or not to be; that is the question."
    -- W. SHAKESPEARE

$ gcc -o letras letras.c
$ ./letras < texto2.txt
18 vogais, 24 consoantes