Quando eu comecei a programar em C, eu sempre tive a curiosidade de por que eu não poderia fazer isso:
char buff[];
scanf(”%s”,&buff);
para pegar uma string de qualquer tamanho do teclado. Obviamente isso não funciona em C, já que em C você precisa manipular a memória na forma mais básica possível, depois que aprendi a utilizar malloc() e realloc(), isso ficou simples.
A idéia é bem simples:
1)Inicializar uma pequena string vazia
2)entrar em um loop que vai fazer (até encontrar ‘\n’):
1.pegar um caractere por vez e armazenar em uma variável temporária
2.contar o tamanho (atualizado) da string digitada
3.se o tamanho for maior que o incial:
1.reallocar a memória com 2 a mais(um para o caractere, um para o final)
4.Colocar o caractere recebido, no final da string
Claro que tudo isso tem que ser feito com muito cuidado para não estourar a memória e tudo isso que já sabemos.
Vamos ao código então, ele é bem simples, e adaptar em uma função para o seu programa em C fica praticamente patético (apenas coloque um return *buff; no final ;)).
/* Esse programa serve para ler uma linha com qualquer tamanho */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define STARTSIZE 2
int main(void){
char *buff = NULL;
char ch = ‘\0′;
int qtd = -1;
/* Primeiramente vamos alocar memoria para uma pequena linha, STARTSIZE caracteres */
if((buff=(char*)malloc(sizeof(char)*STARTSIZE))==NULL){
perror(”malloc”);
return errno;
}
memset(buff,’\0′,sizeof(char)*STARTSIZE);
fprintf(stdout,”Digite uma linha, finalize com ENTER:”);
do{
ch=(char)fgetc(stdin);
qtd++;
if(qtd>STARTSIZE){
if((buff=(char*)realloc(buff,sizeof(char)*qtd+1))==NULL){
perror(”realloc”);
return errno;
}
buff[qtd]=’\0′;
buff[qtd+1]=’\0′;
}
buff[qtd]=ch;
}while(ch!=’\n’);
fprintf(stdout,”Recebi a linha:\n%s”,buff);
free(buff);
return 0;
}
Existe uma outra forma de se resolver isso, bem mais rápida e com menos bugs (essa versão, por ser antiga, possui alguns bugs que eu não havia reparado), a idéia permanece a mesma. Aqui está uma versão mais estável.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main(void){
char *buff = NULL;
char tmp = ‘\0′;
int size = 0;
fprintf(stdout,”Digite uma linha, termine com ENTER:”);
fflush(stdout);
while(tmp!=’\n’){
read(fileno(stdin),&tmp,1);
size++;
if((buff=(char*)realloc(buff,size))==NULL){
perror(”realloc”);
return EXIT_FAILURE;
}
buff[size]=’\0′;
buff[size-1]=tmp;
}
fprintf(stdout,”Recebi a linha:\n%s\n”,buff);
if(buff)
free(buff);
return 0;
}
June 3rd, 2008 at 2:59 am
Caro amigo,
Estava procurando algo parecido e achei seu artigo interessante, no entanto apos compilar sem erros, so consigo inserir uu caracter - resposta : recebi a linha c; com dois caracteres - resposta: recebi a linha: cc abortado e com mais de 2 a resposta e : abortado.
Uso o fedora 9:
[aimar@localhost Curso C]$ uname -r
2.6.25.3-18.fc9.i686
E o gcc:
[aimar@localhost Curso C]$ gcc –version
gcc (GCC) 4.3.0 20080428 (Red Hat 4.3.0-8)
Caso possa me ajuda ficarei muito agradecido.
Obs.: Estou engatinhando no C
June 3rd, 2008 at 9:09 am
aimar, você está completamente correto, essa versão é velha e possui vários bugs, sendo que um deles é exatamente esse.
Existem várias formas de se resolver esse problema, sendo que todas são um tanto quanto parecidas, estou colocando na postagem mesmo uma outra versão correta, tanto em 64 bits quanto em 32 bits.
Muito obrigado por me avisar deste erro.