Jump to content
Dexter's Lab

Questão pertinente de malloc e ficheiros

Recommended Posts

Dexter's Lab

Boas

Estou com uma dúvida que aparenta ser simples. Refere-se ao malloc.

No seguinte código:

void get()
{
FILE *file = fopen("ex7exp1.txt", "r");

if(!file)
{
	printf("Não foi possível abrir o ficheiro");
	return;
}

int round, c, len;
fscanf(file, "%i", &len);

char *name = malloc(sizeof(char) * (len +1));

	fscanf(file, "%s", name);

	printf("%s\n", name);

fclose(file);
}

Eu vou a um documento de texto onde primeiro está um valor (que é o numero de letras que possui o nome à sua frente) e logo a seguir o nome.

No ficheiro tenho:

"5joana"

Portanto, ele vai ler o 5, alocar 5*char e colocar lá o Joana.

Contudo, se eu meter "2joana" ele não vai apenas buscar "jo", mas continua a ir buscar TUDO.

Ora, isto vai contra o conceito que aprendi sobre alocação dinâmica de memória. Gostava de saber a explicação para isto e se há algo que não apanhei e que já deveria saber.

Obrigado pela atenção.

PS: É também possível que esteja a aplicar mal o malloc() mas nesse caso gostaria que me elucidassem e explicassem como o posso usar neste contexto.

Edited by Dexter's Lab

Share this post


Link to post
Share on other sites
pmg

O teu problema 'e no scanf().

Estas a usar o scanf() de uma forma insegura. Para limitares o scanf() a ler N caracteres tens de especificar esse N dentro da string de conversao.

scanf("%2s", name); // o '\0' nao e contado no scanf

A maneira usual de ler input do utilizador limitado por um tamanho especificado 'e com fgets()

fgets(file, 3, name); // o 3 ja inclui espaco para '\0'


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Ah, estou a entender! Isto porque o scanf independentemente do numero de bytes que é "ordenado" a ler, ele simplesmente lê até lhe aparecer um \0, certo?

São estas particularidades que criam em mim um fascínio pelo C. Isto é incrível.

PS: Então e se eu quiser que, nesse scanf, esteja um número variável a definir o tamanho? por exemplo [scanf("%'len's", string);] sendo que 'len' corresponde a uma variável de 2 valores? Nesse caso só posso usar o fgets, correto?

Edited by Dexter's Lab

Share this post


Link to post
Share on other sites
pmg

PS: Então e se eu quiser que, nesse scanf, esteja um número variável a definir o tamanho? por exemplo [scanf("%'len's", string);] sendo que 'len' corresponde a uma variável de 2 valores? Nesse caso só posso usar o fgets, correto?

Nao é possivel fazer isso directamente.

Podes construir uma string com os tamanho 'embebido' e usar essa string no scanf ...

int len = 2;
char format[100];
name = malloc(len + 1);
sprinf(format, "%%%ds", len); // "%2s"
scanf(format, name);


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Muito obrigado pelo conhecimento.

Queria já agora aproveitar para perguntar o seguinte:


   int len;
   char *name;

   fscanf(file, "%i", &len);

   fgets(name, len, file);
   printf("%s\n", name);

   fclose(file);

Porque é que se defino a string desta forma me dá um erro "segmentation fault", e declarando-a "char string" já me dá corretamente, e no entanto na documentação que encontro está tudo definido da forma que eu não consigo?

Share this post


Link to post
Share on other sites
pmg

Em C, uma string tem como base um array (eu quase que diria que uma string é um array). Se precisas de alterar a string, precisas de ter um array a sério.

Ao definires um apontador, deves indicar para onde ele aponta. A tua instrução char *name; faz um apontador que aponta para um lugar aleatório que pode ser inválido. A instrução char *name = "default.txt"; faz um apontador que aponta para um array que não é alterável (neste caso podia-se fazer const char *name = "default.txt"; para ajudar o compilador a detectar tentativas de alterar o array só de leitura). A instrução char name[] = "default.txt"; faz um array de 12 caracteres que é inicializado com os caracteres 'd', 'e', ..., 'x', 't', e '\o'.

Se te desenrascas com o ingles, aconselho-te uma leitura da secção 6 do FAQ do comp.lang.c.

Basicamente: ao contrário do que muita gente pensa um ponteiro não é um array (uma string), nem um array (uma string) é um ponteiro.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.