Programar em C++/Manipulando strings: diferenças entre revisões

[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Absosutamente fora de escopo... transferindo...
Linha 44:
No estilo C++, como era de se esperar, as strings são objetos, eles podem ser criados facilmente através da biblioteca padrão referenciada pelo arquivo de cabeçalho <string>. As strings são objetos com recursos que permitem manipular os seus caracteres com as funcionalidades das funções da linguagem C e mais algumas características próprias possibilitadas pela orientação a objetos.
 
== Lendo um caractere ==
 
Ler um caractere até é simples, basta utilizar o objeto cin e será guardado o valor digitado na variável.
 
<source lang=cpp>
char nivel;
cout << "Entre um nível: ";
cin >> nivel;
</source>
 
Porém teremos de pressionar a tecla ENTER depois de digitar o caractere. Isto leva a várias questões.
 
 
O problema “pressione uma tecla para continuar...”
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
 
int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair, qualquer outra tecla para continuar: ";
cin >> ch;
if (ch != 'S' && ch != 's')
cout << "Desaja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
 
#ifdef _MSC_VER
system ("pause");
#endif
 
return 0;
}
</source>
 
*O programa funciona bem se pressionarmos S ou s para sairmos;
*O programa funciona bem se pressionarmos qualquer outra tecla com caractere imprimivel;
*Mas se pressionarmos a tecla ENTER, nada acontece, o cin continua à espera de entrada. a razão é o operador de extracção “>>” ignora os espaços em branco e os caracteres "nova linha" resultantes do pressionamento da tecla enter.
 
== A função cin.get() ==
 
Já tivemos oportunidade para discutir a função getline (função membro) do objecto cin.
 
<source lang=cpp>
cin.getline(name,80);
</source>
 
Aqui vamos utilizar uma outra função, a cin.get().
 
Esta função pode ser chamada, tal como a getline(), através de 3 argumentos, onde o primeiro é o array de caracteres, mas também o pode ser sem argumentos ou ainda apenas um argumento.
 
No caso de não conter argumentos apenas irá ler um caracter, em vez de uma cadeia de caracteres.
 
No caso de ter um argumento, ela aceita qualquer tecla incluindo o enter. (o que não se passa com o cin e o operador de extracção). Aqui um exemplo
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair, \nqualquer outra tecla para continuar: ";
cin.get(ch);
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
 
#ifdef _MSC_VER
system ("pause");
#endif
 
 
return 0;
}
</source>
 
Porém se pressionarmos uma tecla de caractere imprimível, não conseguiremos inserir o próximo prompt, parece que houve um salto. Estranho!
 
Para explicar a razão deste novo problema necessitamos de explicar o conceito de buffer.
 
O "input buffer" é uma área de memória que guarda os caracteres de entrada, por exemplo do telado, até que essa entrada seja atribuída pelo cin e o operador de extracção >>, ou por funções como get() ou getline() do objecto cin.
 
Quando o loop começa, o "input buffer" está vazio.
 
*Se digitarmos apenas o enter, sendo este o primeiro e único caractere no "imput buffer", ele é removido do input buffer e atribuído á variavel ch, então o "input buffer" está vazio na próxima iteração do loop;
*Se digitarmos x e enter. Temos 2 caracteres. A função get() retira o primeiro c1aráctere do "input buffer" e atribui á variavel ch, mas nisto o caractere nova linha permanece no "input buffer". Isto faz com que na próxima iteração do loop, não haja a oportunidade para entrar com dados.
 
Ou seja, na segunda iteração, é retirado o caractere nova linha – que ficou da 1ª iteração - e é colocado na varaiel ch. Agora o "input buffer" está vazio.
 
== cin.ignore() ==
 
Uma solução é limpar o caractere nova linha do "input buffer" antes da chamada da função getline(). E fazemos isso usando a função ignore() do objecto cin.
 
Esta função membro tal com a get() e a getline() são sobrecarregadas, podem ser chamadas sem argumentos, com um ou dois argumentos.
 
Utilizar a função ignore() sem argumentos, permite que o próximo caractere no "input buffer" seja lido e depois descartado,- e isto é exactamente aquilo que queríamos.
 
A função com 1 ou 2 argumentos é usada para cadeias de caracteres.
* Com um argumento, o argumento é o número máximo de caracteres a ser removido do "input buffer". Exemplo:
 
<source lang=cpp>
cin.ignore(80); // Remove até 80caracteres do input buffer
</source>
 
* Com dois argumentos, o segundo argumento é o delimitador, um caractere que se encontrado, antes do número de caracteres especificado no primeiro paramento, faz com que a remoção pare. Exemplo:
 
<source lang=cpp>
cin.ignore (80, '\n'); // Remove 80 caracteres se até lá não encontrar o nova linha.
</source>
 
Reescrevendo o código anterior utilizando o cin.ignore()
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
 
int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair,\n qualquer outra tecla para continuar: ";
cin.get(ch);
cin.ignore();
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
 
#ifdef _MSC_VER
system ("pause");
#endif
 
 
return 0;
}
</source>
 
Ora este programa funciona muito bem, MAS…
 
Se pressionarmos a tecla Enter para continuar, teremos de fazer isso duas vezes, pois a primeira vez é ignorada. A razão: é que não existe nada no "input buffer" quando a função ignore é chamada, por isso é que a tecla enter necessita de ser pressionada 2 vezes, colocando um caractere nova linha a mais no "buffer" para a função ignore() remover.
 
Se tentarmos modificar isto através do '''if'''?
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
 
int main(void)
{
char ch;
do {
cout << "Pressionar S ou s para sair,\n qualquer outra tecla para continuar: ";
cin.get(ch);
if (ch != '\n')
cin.ignore();
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
 
#ifdef _MSC_VER
system ("pause");
#endif
 
return 0;
}
</source>
 
Agora sim temos todos os problemas resolvidos e isto agora funciona!!
 
== cin, cin.get(), cin.getline() ==
 
O problema anterior do caractere nova linha permanece quando usamos o cin, o get() e o getline() juntos num programa, uma vez que o enter é usado para terminar a entrada.
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
 
int main(void)
{ char name[80];
int courseNum;
cout << "Informe o número do curso: ";
cin >> courseNum;
cout << "Informe seu nome: ";
cin.getline(name, 80);
cout << "O número do curso é: " << courseNum << endl;
cout << "Seu nome é: " << name << endl;
 
#ifdef _MSC_VER
system ("pause");
#endif
 
return 0;
}
</source>
 
Aqui, neste exemplo, nós não tivemos a oportunidade de colocar o nome. Quando digitamos o número e depois pressionamos a tecla enter, o cin coloca o número no courseNUm mas permanenece o caractere nova linha no "input buffer", que fica para o enter name, pois o getline lê espaços em branco.
 
A solução pode ser:
 
<source lang=cpp>
#include <iostream>
 
using namespace std;
 
int main(void)
{
char name[80];
int courseNum;
cout << "Informe o número do curso: ";
cin >> courseNum;
cin.ignore();
cout << "Informe seu nome: ";
cin.getline(name, 80);
cout << "O número do curso é: " << courseNum << endl;
cout << "Seu nome é: " << name << endl;
 
#ifdef _MSC_VER
system ("pause");
#endif
 
return 0;
}
</source>
 
A partir destes exemplos podemos criar umas regras:
 
#Colocar sempre a função ignore() depois do cin e do >>;
#*Razão: O "cin>>" deixa sempre o nova linha no "input buffer". Assim devemos eliminá-lo com a função ignore().
#Não colocar a função ignore(), no caso de ser sem parâmetros, depois do getline();
#*Razão:O getline() remove o caractere nova linha que termina a entrada do "input buffer", portanto não é necessário o ignore().
#Verificar se temos o caractere nova linha no "input buffer" depois de utilizar o get(), se tivermos deveremos utilizar o ignore().
#*Razão: A função get() '''com um argumento''' deixa o caractere nova linha no "input buffer" se pressionarmos um caractere e o enter. mas não deixará, se apenas pressionarmos o enter. portanto é necessário confirmar.
 
== Funções de caracteres úteis. ==