Subsecções

26 Strings como array de caracteres

Strings são essencialmente arrays de caracteres (arrays com elementos do tipo char) que DEVEM terminar com '\0'. Normalmente é conveniente definir a constante NULO em seu programa para representar este terminador: #define NULO '\0'.

No exemplo acima, embora não tenhamos escrito explicitamente o caracter NULO, o compilador automaticamente o colocou como o último elemento do array arr2[]. Portanto, o tamanho de arr2[] é 6: 5 para os caracteres que indicamos (ci208) e 1 para o caractere NULO que o compilador introduziu automaticamente. As definições abaixo são equivalentes.

      char arr2[] =  {'c','i',' ', '2','0','8','\0'};

      char arr2[] =  {'c','i',' ', '2','0','8', NULO};

O caractere NULO marca o final de um string.

Outros exemplos:

    // a maneira tediosa 
    char name1[] = { 'j','o','s','e',' ','s','i','l','v','a','\0' };

    // e a maneira facil 
    char name2[] = "jose silva";

Embora o primeiro exemplo seja um string, o segundo exemplo mostra como strings são geralmente escritos (como constantes). Note que se você usar aspas quando escreve uma constante, você não precisa colocar '\0', porque o compilador faz isso para você.

Quando você for criar um array de caracteres de um tamanho específico, lembre-se de adicionar 1 para o tamanho máximo de caracteres esperado para armazenar o caractere NULO. Por exemplo, para armazenar o string “programar eh divertido”, você precisa de um array de tamanho 22 (21 caracteres + 1 para o NULO).

26.1 Imprimindo strings com cout

Strings podem ser impressos usando cout . Por exemplo:

   int main()
   {
       char mensagem[] = "tchau";

       cout << "ola" << endl << mensagem << endl;
   }

A saída deste programa é:

    ola
    tchau

26.2 Lendo strings do teclado com cin.getline() e cin

A função cin.getline() lê uma linha de texto digitado no teclado e a armazena em um vetor indicado como primeiro argumento. O segundo argumento da função indica o número máximo de caracteres que será lido. Veja o exemplo abaixo:

#include <iostream>
using namespace std;

int main()
{
  char nome[100];
  
  cout << "Entre seu nome: ";
  cin.getline (nome, 100);
  cout << "Oi, " << nome << "." << endl ;
}

Exemplo de execução

   Entre seu nome: Jose Silva
   Oi, Jose Silva.

Passando um nome de array para a função cin.getline(), como ilustrado no programa acima, coloca a linha inteira digitada pelo usuário no array nome (tudo ou máximo de 99 caracteres até que seja teclado enter). Note que se o usuário digitar caracteres demais (neste caso, mais de 99 caracteres), apenas os primeiros 99 caracteres digitados serão copiados para o array indicado no primeiro argumento da função.

A função cin pode ser usada de maneira similar. A única diferença é que cin lê somente a primeira palavra (tudo até que se digite um separador - um espaço em branco, tabulação, ou enter).

#include <iostream>
using namespace std;

int main()
{
  char nome[100];
  
  cout << "Entre seu nome: ";
  cin >> nome;
  cout << "Oi, " << nome << "." << endl;
}

Exemplo de execução

   Entre seu nome: Jose Silva
   Oi, Jose.

Note que somente o primeiro nome é lido pelo cin porque a função pára no primeiro espaço em branco que encontra (enquanto cin.getline() pára quando encontra um enter).

26.3 Array de Strings

Em notas de aula anteriores, vimos alguns exemplos de arrays de arrays (matrizes ou tabelas). Como strings são também arrays, podemos definir arrays de strings. O programa abaixo inicializa um array de strings com nomes e os imprime.

#include <iostream>
using namespace std;

#define NUM_NOMES 5        // define a quantidade de nomes no array 
#define TAM       20       // define o tamanho maximo do nome

int main()
{
  char nomes[NUM_NOMES][TAM] = {"Jose Silva", 
				"Maria Silva",
				"Antonio dos Santos",
				"Pedro dos Santos",
				"Joao da Silva"};
  int i;
  
  for(i = 0; i < 5; i++)
    cout << nomes[i] << endl;
}

A saída deste programa é:

   Jose Silva 
   Maria Silva
   Antonio dos Santos
   Pedro dos Santos
   Joao da Silva

26.4 Funções de String

Há funções para manipulação de string já definidas na biblioteca padrão C++ chamada cstring. Todas as funções que apresentaremos nesta seção são parte desta biblioteca. Portanto, se seu programa utilizar uma destas funções você deve incluir a linha #include <cstring> no início do seu programa.

O objetivo desta seção é mostrar como estas funções poderiam ser implementadas como exemplos de programas de manipulação de strings.

26.4.1 A função strlen()

A função strlen() tem como argumento um string. Ela retorna um inteiro que é o comprimento do string (o número de caracteres do string, não contando o caractere NULL). Por exemplo, o comprimento do string “alo” é 3.

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
  char nome[100];
  int comprimento;
  
  cout << "Entre seu nome: ";
  cin.getline(nome, 100);
  comprimento = strlen(nome);
  
  cout << "Seu nome tem  " << comprimento << " caracteres." << endl;
}

Um exemplo de execução:

   Entre seu nome: Dostoevsky
   Seu nome tem 10 caracteres.

Abaixo, mostramos como a função strlen() poderia ser implementada.

   int strlen( char str[] )
   {
      int comprimento = 0;
      
      
      while ( str[comprimento] != NULL )
          ++comprimento;
      return comprimento;
    }

26.4.2 A função strcmp()

A função strcmp() é usada para comparar dois strings. Lembre que não podemos usar ==, como em str1 == str2, para comparar dois strings, uma vez que strings são arrays. Strings devem ser comparados caractere por caractere. A função strcmp() tem como argumento dois strings e retorna um inteiro.

Strings são ordenados de forma similar a maneira como palavras são ordenadas em um dicionário. Ordenamos palavras em um dicionário alfabeticamente, e ordenamos strings respeitando a ordem dos caracteres no conjunto de caracteres da máquina. A ordenação abaixo é válida em qualquer computador:

'0' < '1' < ... < '8' < '9'
'A' < 'B' < ... < 'Y' < 'Z'
'a' < 'b' < ... < 'y' < 'z'
A ordem relativa do três conjuntos (dígitos, letras maiúsculas e letras minúsculas) depende do computador utilizado.

Se s1 e s2 são strings, o resultado da chamada de função strcmp(s1, s2) é:

$\bullet$ se s1 $=_{s}$ s2, strcmp() retorna 0

$\bullet$ se s1 $<_{s}$ s2, strcmp() retorna um número negativo (< 0)

$\bullet$ se s1 $>_{s}$ s2, strcmp() retorna um inteiro positivo (> 0)

(onde $=_{s}$, $<_{s}$ e $>_{s}$ são $=$, $<$ e $>$ para strings)

$s1 <_{s} s2$ significa “$s1$ vem antes de $s2$ no dicionário”. Exemplos: “tudo” é menor que “xadrez”, “calor” é menor que “calorao”, “frio” é menor que “quente”, e é claro o string vazio , NULL, é menor que qualquer string.

Considere o exemplo abaixo que usa strcmp():

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
  char palavra1[100], palavra2[100];
  int resultado;
  
  cout << "entre com uma palavra: ";
  cin >> palavra1;
  cout << "entre outra palavra: ";
  cin >> palavra2;
  
  resultado = strcmp(palavra1, palavra2);
  
  if (resultado == 0)
    cout << "igual" << endl;
  else if (resultado > 0)
    cout << "o primeiro e' maior" << endl;
  else
    cout << "o segundo e' maior" << endl;
}

Aqui está um exemplo de como a função strcmp() poderia ser implementada.

int strcmp( char s1[], char s2[] )
{
   int i = 0;

   while (1)
   {
     if (s1[i] == NULL && s2[i] == NULL)
        return 0;
     else if (s1[i] == NULL)
        return -1;
     else if (s2[i] == NULL)
        return 1;
     else if (s1[i] < s2[i])
        return -1;
     else if (s1[i] > s2[i])
        return 1;
     else 
        ++i;
   }
}

Na biblioteca padrão, a função strcmp() faz distinção entre letras maiúsculas e minúsculas. Se você não quer que a função faça esta distinção, você pode modificar o seu string para ter apenas letras minúsculas (ou maiúsculas) antes de passá-lo como argumento para a função strcmp(). Para fazer isso, você pode usar a função da biblioteca padrão tolower(), que tem como argumento um caractere. Se o caractere passado é uma letra maiúscula, ele retorna esta letra minúscula; caso contrário, retorna o mesmo caractere. Por exemplo: tolower('A') é 'a', tolower('1') é '1', tolower('a') é 'a'.

26.4.3 A função strcpy()

A função strcpy() é usada para copiar o conteúdo de um string para outro. Ela tem dois argumentos: strcpy(s1, s2) copia o conteúdo do string s2 para o string s1. A função strcpy() que apresentamos abaixo não retorna um valor. Seu protótipo é

void strcmp(char [], char []);

O exemplo abaixo mostra a utilização do strcpy().

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
  char pal[100], palCopia[100];
  
  cout << "entre com uma palavra: ";
  cin >> pal;
  strcpy(palCopia, pal);
  
  cout << "entre outra palavra: ";
  cin >> pal;
  
  cout << "voce entrou primeiro: " << palCopia << endl;
}

Embora este programa pudesse ter sido escrito sem usar strcpy(), o objetivo é mostrar que se pode usar strcpy() para fazer “atribuição” de strings.

A função strcpy() poderia ter sido implementada da seguinte forma:

   void strcpy( char s1[], char s2[] )
   {
      int i = 0;

      while ( s2[i] != NULL )
      {
          s1[i] = s2[i];
          ++i;
      }
      s1[i] = s2[i];      
   }


Créditos: Documento produzido pelo Prof. Armando L.N. Delgado (DINF/ET/UFPR), baseado em revisão sobre material de Prof. Carmem Hara e Prof. Wagner Zola (DINF/ET/UFPR).

Esta obra está licenciada com uma Licença Creative Commons Atribuição-NãoComercial-CompartilhaIgual 4.0 Internacional.  Licença Creative Commons

Armando Luiz Nicolini Delgado
2020-10-20