paulo1205 
		 
		(usa Ubuntu)
		 
		Enviado em 05/06/2013 - 17:19h 
		A forma mais simples e segura de ler strings em C é usar 
fgets ().
gets () é uma função obsoleta, e foi inclusive removida da última revisão do padrão do C (em 2011).  O problema com ela era justamente não limitar a quantidade de caracteres lidos, o que dava margem a exceder o tamanho da string que deveria guaradar os dados.  
gets () deve ser evitada a todo custo. 
Dá para ler strings com espaços através de 
scanf (), usando a conversão do tipo "
%[...] " em lugar de "
%s " (
scanf () é muito poderosa, mas um bocado complexa; é importante gastar um tempo razoável lendo sua documentação).  Eu prefiro usar 
fgets (), mas uma forma de fazer com 
scanf (), usando somente '\n' como terminador da string, é mais ou menos como a seguinte.
    char str[80]; 
int n, a, b; 
 
/* ... */ 
 
/* Lê string, verificando se a leitura foi bem sucedida. */ 
a=b=0; 
n=scanf("%79[^\n]%n%*1[\n]%b", str, &a, &b); 
str[79]=0;  /* Garante o byte nulo terminador da string. */ 
 
if(n==EOF){ 
  /* 
    Leitura falhou. 
    Provavelmente você vai colocar algum código de tratamento de erro, 
    talvez querendo testar os valores de feof() e ferror(). 
  */ 
} 
else if(n>0){ 
  /* Conseguiu ler uma string não-vazia. */ 
  /* 
    Verifica se ocorreu truncamento da string antes da marca de fim 
    de linha (i.e., a linha digitada tem mais do que 79 caracteres). 
  */ 
  if(b>a){ 
    /* 
      Não, a linha não foi truncada.  Todos os caracteres digitados foram 
      consumidos pelo scanf(), incluindo a marca de fim de linha. 
    */ 
  } 
  else{ 
    /* 
      A linha foi truncada.  Isso significa que os caracteres excedentes 
      -- incluindo a marca de fim de linha -- ainda estão no buffer, es- 
      perando ser lidos por alguma outra função. 
    */ 
  } 
} 
else{ 
  /* 
    n==0.  Isso provavelmente significa que o usuário digitou ENTER sem 
    ter digitado antes qualquer outro caráter.  Nesse caso a marca de fim 
    linha vai permanecer no buffer de entrada, devendo ser consumida de 
    algum modo, para não impactar leituras futuras. 
  */ 
}  
Parece complicado?  Pois é mesmo, especialmente se você quiser programar de modo seguro.  Uma vantagem desse método é que o valor de 
a  já dá, de cara, o tamanho da string lida, permitindo que se evite uma chamada a 
strlen () para medir o tamanho da string.
Com 
fgets (), o sistema lê a linha -- incluindo a quebra de linha --, e a armazena no buffer.  O motivo de armazenar a quebra de linha é dar a aplicação uma forma de determinar se houve truncamento da linha.  A forma de fazer seria mais ou menos a seguinte.
    #define BUFFER_LEN 80 
 
char buf[BUFFER_LEN]; 
int len; 
 
if(fgets(buf, BUFFER_LEN, stdin)!=NULL){ 
  /* Leitura bem sucedida. */ 
  buf[BUFFER_LEN-1]=0; /* Garante o byte nulo no final do buffer. */ 
  len=strlen(buf); /* Mede o comprimento efetivo da string lida. */ 
 
  if(len>0){ 
    if(buf[len-1]=='\n'){ 
      /* Linha lida completamente e sem truncamento. */ 
 
      /* 
        Se a quebra de linha não interessar, pode-se trocá-la pelo byte 
        nulo que marca o fim da string, fazendo ``buf[len-1]=0;''.  Pode 
        ser, porém, que, se len==1, o resultado de remover o fim de linha 
        é que o buffer fique com tamanho zero. 
      */ 
    } 
    else{ 
      /* 
        A linha foi truncada.  Como proceder nesse caso depende da aplicação. 
        No entanto, os caracteres não lidos (incluindo, como sempre, a quebra 
        de linha) vão permanecer no buffer. 
      */ 
    } 
  } 
  else{ 
    /* 
      Acho que este caso (len==0) não deve ocorrer nunca, a não ser 
      que BUFFER_LEN valha 1 (o que provavelmente seria uma tremenda 
      bobagem). 
    */ 
  } 
} 
else{ 
  /* A leitura falhou completamente.  Dá o devido tratamento. */ 
}