Strings
Introdução
Uma string é um conjunto de caracteres armazenados num vector. As strings são representadas utilizando aspas enquanto os caracteres entre plicas. Poderemos pensar que C é fraco no tratamento de strings visto que strings não é tipo básico da linguagem e única forma de representar um conjunto de caracteres é recorrendo a um vector.
Por exemplo, não podemos fazer:
- uma atribuição s1="OLA";
- compará-las s1=="OLA";
- concatenar.
Uma excepção é no momento da declaração em que pode ser atribuída uma string, exemplo:
char nome[]="OLA"; // Equivalente a char nome[3+1]="OLA";
Para atribuir temos que primeiro declarar uma string de tamanho conhecido:
char str[65]; /* OU */ char *str = malloc(65); /* Embora aqui a memória seja alocada dinamicamente no heap */
C possui uma poderosa biblioteca de funções que permite realizar estas tarefas e muito mais, e se por acaso não encontrarmos nenhuma função que faça o que queremos podemos sempre fazer manipulação carácter a carácter e resolver o problema (algumas linguagens que tratam strings como um todo e não um conjunto de caracteres não o permitem).
A declaração de strings obedece à sintaxe de declaração de vectores, sendo a primeira posição 0 e termina com o carácter \0
.
Nota: Na declaração de uma string não se esqueça de 'guardar' espaço para o \0
.
Exemplo:
char linha[101]; // Declaração de um vector que conterá uma string com 100 caracteres e um para o '\0'
Nota: As funções que serão descritas aqui estão disponíveis com #include <string.h>
Leitura e escrita se strings
Algumas funções de leitura e escrita:
puts
#include <stdio.h>
int main (void) {
char palavra[]="OLA";
printf ("%s\n",palavra);
puts(palavra);
return (0);
}
A função puts
após escrever uma string muda de linha, enquanto a função printf
não (a função puts
— put string — só permite a escrita de strings tal como o nome indica).
scanf
#include <stdio.h>
int main (void) {
char s[20];
scanf ("%s",s);
printf ("%s",s);
return 0;
}
Nota: As variáveis não são precedidas de um &
ao contrário de outro tipo de variáveis na função scanf
.
A função scanf
lê todos os caracteres até encontrar um espaço ou enter, em seguida coloca o \0
(ou seja, só permite ler uma palavra). Cuidado ao usarem por causa de seg faults.
$ ./a.out
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault (core dumped)
Isto porque o input ultrapassou os 20 caracteres. Isto acontece quando um programa tenta aceder a memória que não lhe é destinada.
gets e fgets
A função gets
(get string) permite colocar numa variável todos os caracteres introduzidos pelo utilizador (desde que dentro do limite), ou seja, não está limitada a leitura de uma única palavra como a função scanf
.
Sintaxe:
gets(nome_da_var); // Tal como o scanf também tem o problema dos seg fault's
É recomendado o uso da função fgets
:
char* fgets(char* s, int n, FILE* stream);
Caso aconteça um erro é retornado o valor NULL
.
Como C associa as operações de I/O com ficheiro(stdin
/stout
), para conseguirmos ler o input vindo do teclado com fgets
fazemos:
char s[10];
fgets(s, 10, stdin) /* Assim estamos livres de buffer overflow, pois a função só vai ler até onde o programador quiser, neste caso ate 10 */
Manipulação de Strings
Algumas funções para manipulação de strings do string.h
.
strlen
int strlen (char* s)
Devolve o número de caracteres existentes numa string, sem contar com o \0
.
#include <stdio.h>
#include <string.h>
int main (void) {
char str[]="Olá Mundo";
printf ("%in",strlen(str));
return (0);
}
O código desta função seria algo deste género:
#include <stdio.h>
int strlen (char* s) {
int i;
for (i=0;s[i]!='\0';++i);
return i;
}
int main (void) {
char str[]="Olá Mundo";
printf ("%in",strlen(str));
return (0);
}
strcpy
char* strcpy (char* dest, const char* src);
Esta função copia a string src
para dest
e retorna dest
.
#include <stdio.h>
#include <string.h>
int main (void) {
char str[20];
printf ("%sn",strcpy(str,"Olá Mundo"));
return (0);
}
O código da função strcpy
poderá ser algo deste género:
char *strcpy (char *dest, char *src) {
int i=0; // Variável inicializada a 0 para apontar para a primeira posição
while (dest[i]=src[i]) /* dest[i]=src[i] não é um teste de igualdade mas sim uma atribuição, como se trata de uma atribuição o carácter atribuido é devolvido, se for o carácter terminador sai do while */
++i;
return dest;
}
strcat
char* strcat (char* dest, const char* src);
Coloca a string src
imediatamente a seguir ao final da string dest
e retorna dest
.
#include <stdio.h>
#include <string.h>
int main (void) {
char str[20]="Olá ";
printf ("%s\n",strcat(str,"Mundo"));
return (0);
}
O código da função strcat
poderá ser algo deste género:
char* strcat (char* dest, char* src) {
int i=0, len=strlen(dest);
while (dest[len++]=src[i++]);
return dest;
}
strdup
char* strdup(const char* str)
Esta função copia uma string, mas ao contrário da strcpy
, não é necessário alocar espaço previamente.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[]="exemplo";
char* str2;
str2=strdup(str1);
puts(str2);
free(str2); /* Como ja nao precisamos da string podemos libertar a sua memoria */
return 0;
}
strcmp
Compara strings. Repare que quando estamos a falar em comparação, estamos a falar em comparação alfabética.
int strcmp(const char* s1, const char* s2)
Retorno | Explicaçao |
---|---|
<0 | s1 é menor que s2 |
0 | s1 e s2 são iguais |
>0 | s1 é maior que s2 |
#include<stdio.h>
#include<string.h>
int main(void)
{
char s1[]="Ola";
if(strcmp(s1,"Ola")==0)
printf("Sao iguais");
else
printf("Sao diferentes");
return 0;
}
Podemos traduzir a função para:
int strcmp(char* s1, char* s2)
{
int i=0;
while(s1[i]==s2[i] && s1[i]!='\0')
i++;
return (s1[i]-s2[i]);
}