Ir para o conteúdo

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 putsput 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]);
}