• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

magician

Retornar arrays Strings com apontadores.

27 mensagens neste tópico

Ando aqui de volta do C para um trabalho e isto ta complicado ao fazer um apontador do tipo char consigo guardar uma string mas como crio uma array de strings com apontadores ? e como o retorna por uma função?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Um array de string s com apontadores... fiquei baralhado.

Não será um array de apontadores para char? Tipo:

char** pointer;

Este tipo de dados funciona como todos os outros.

retornar:

return pointer;

Alguma coisa me está a escapar aqui, não?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

o que kero fazer é guardar em um apontador varias strings ou seja apontadores de char.

e como faço para percorrer e colocar valores dessa forma :S

Ai meu rico Java :confused: lol

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

char** pointer;

//alocar espaço dinamicamente para os teus ponteiros

pointer = (char**) malloc(N*sizeof(char*));

//para cada char*, vas ter de alocar dinamicamente também.

Aceder

pointer[0][1]; //string 0 caracter 1

Isto é uma forma de fazer, porque podes alocar tudo de uma vez e usar tipo: pointer[(resultado de calculo que dependo dos tamanhos alocados)]

Agora. Ponteiros retornados numa função só são válidos se o objecto alocado for dinámico, ou se este já vem dos proprios parametros da função.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Heiien Java Java :confused:

Será que me podias fazer ai dois pequenos exemplos para eu ver se entendo isto é que 1 apontador já tava a ir agora duplos :S

Preciso de ter um array de Strings ou seja como disseste um apontador de apontadores de char.

Depois preciso de colocar strings la dentro com um ciclo e retornar esse array.

e depois preciso de imprimir string a string :S

Se me poderes explicar :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então.

Forma mais simples. Estático.

char* str[] = {"safado\0","xxx\0"}; 

Desvantagem. Completamente estático, não alteravel. Não pode ser retornado como resultado de função.

int n = 2;
char** pointer;
pointer = (char**) malloc(n*sizeof(char*));

pointer[0] = (char*)malloc(7*sizeof(char));
pointer[1] = (char*)malloc(4*sizeof(char));

pointer[0] = "safado\0";
pointer[1] = "xxx\0";

Precisa de maior gestão de memória. Mas é mais flexivel.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

char** pointer;
pointer = (char**) malloc(n*sizeof(char*));

pointer[0] = "safado\0";
pointer[1] = "xxx\0";

Não posso fazer logo assim ?

Já agora como posso juntar um int a uma string eu tentei fazer assim mas nhaa

strcat(dir->d_name,(char *)sb.st_size);

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes fazer assim, mas...

Alias já te estou a enganar. Bem me parecia que existia algo de errado aqui. Mostra o cuidado que devemos ter a usar "XXXXXX" (string) en C, pode enganar-nos com facilidade.

Correctamente é:

int n = 2;
char** pointer;
pointer = (char**) malloc(n*sizeof(char*));

pointer[0] = (char*)malloc(7*sizeof(char));
pointer[1] = (char*)malloc(4*sizeof(char));

pointer[0][0] = 's';
pointer[0][1] = 'a';
........etc....

Isto porque usando construtores do tipo -> "XXX" criam arrays de caracteres estáticos, que se vai sobrepor ao que foi alocado anteriormente.

Ou seja, até podes fazer como disseste, mas não vaz poder libertar a memória de cada string, só o array de ponteiros.

Eu até já nem me lembrava bem destes pormenores,  isto porque normalmente uso a classe <string> de c++ já para evitar estas coisas.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Desculpa la tar a ser chato mas o que posso fazer quanto a isto

juntar um int a uma string eu tentei fazer assim mas nhaa

strcat(dir->d_name,(char *)sb.st_size);

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não podes juntar assim. Antes tens de converter para string.

Exemplo:

char str[20];
sprintf(str, "%d", sb.st_size);

strcat(dir->d_name, str);

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

dir->d_name é um inteiro?

Não podes concatenar um inteiro assim.

Até porque dir->d_name é o destino da concatenação, e se isso é um inteiro, não faz sentido nenhum.

Para concatenares, tens de converter o inteiro para string com itoa(...)

Não esquecer que ao fazer estas conversões e concatenações, o ponteiro char* de destino tem de ter espaço suficiente para o resultado, e que muitas vezes inclui o \0

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

#include <dirent.h> 
#include <string.h>
#include <sys/types.h> 
#include <sys/stat.h> 

#include <stdio.h>
#include <stdlib.h>

typedef struct dirent dirent;

char **getList(char *dire){

char **lista = (char**) malloc(50*sizeof(char*));

int i = 0;
struct stat sb;
char *str = (char *)malloc(50);
DIR *d;

dirent *dir;
d = opendir(".");
if(d){
    	while ((dir = readdir(d)) != NULL){
    		if (stat(dir->d_name, &sb) == 0 && (strcmp(dir->d_name,".")) && (strcmp(dir->d_name,".."))){
    			lista[i] = (char*)malloc(20*sizeof(char));
    			sprintf(str,"%d",(int)sb.st_size);
    			strcat(str," - ");
    			strcat(str,dir->d_name);
    			lista[i] = str;
    		}
      		i++;
    	}
    free(str);
    closedir(d);
  	}
  	return lista;
}

int main(){

char **l = getList("");
int i = 0;
while(l[i] != NULL){
	printf("%s\n",l[i]);
	i++;
}
return 0;
}

Porque é que isto não funca :S ele ta a meter todo bem mas depois para fazer printf no main dá buraco :'(

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Só uma pergunta, isso tudo é para obter a listagem do directório actual? É que com um ficheiro temporário fazias isso mais rápido e mais simples. A não ser que fosses aconselhado a fazer sem ficheiros temporários, senão eu optava por fazer.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não é facil estar a interpretar esse código, até porque existe algumas coisas em que não mostras a definição.

Ora, não funciona é muito vago. Não funciona como?

Rebenta? Consegues fazer debug e ver a linha onde rebenta? Chega a escrever alguma coisa?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lista[i] = (char*)malloc(20*sizeof(char));
...
lista[i] = str;

acho que isto não está bem... estás a copiar o apontador para 'str' (que é sempre o mesmo) para 'lista[ i ]', e no fim fazes 'free' da memória apontado por ele, ou seja, no fim ficas com um conjunto de apontadores inválidos armazenados em 'lista'... tens que copiar as strings e não os apontadores...

experimenta eliminar a primeira linha e colocar em vez da segunda: lista[ i ] = strdup(str);, deve resolver este problema.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Rebenta? Consegues fazer debug e ver a linha onde rebenta? Chega a escrever alguma coisa?

Pelo que testei não escreve nada. se ele soubesse à partida de quanta memória precisava era mais fácil, é por isso que eu digo que a opção do ficheiro temporário era a melhor.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Como o Rui Carlos disse.

Para além de copiares o ponteiro, ainda estas a criar um memory leak. A memória alocada por:

lista = (char*)malloc(20*sizeof(char));

retorna um ponteiro, e que depois vai ser perdido com a escrita:

lista = str;

criando uma posição de memória que não está acessivel no código.

Em vez de escrever em um str temporário, suponho que o teu objectivo seja escrever directamente em lista.

Gestão de memória em C não é propriamente topico facil, e é preciso ter bastante cuidado. É necessário obedecer a protocolos estabelecidos.

Uma regra muito importante, que nem sempre é cumprida assiduamente.

Um ponteiro retornado por uma função, (ou neste caso um array) traz consigo não apenas os seus valores, mas também a responsabilidade de libertar a sua memória. Ou seja, a responsabilidade da gestão de memória é passada juntamente com o ponteiro.

Se o objectivo não é passar essa responsabilidade, mas só os valores, então deve-se transmitir uma referência e não um ponteiro.

Esta regra está para além do compilador. Logo, não te esqueças de libertar memória de um ponteiro enviado por uma função.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

:S cada vez estou mais confuso :confused: a ideia era com a função getList criar um array de strings tipo "tamanho - ficheiro" e ele realmente cria o problema é que depois no mais não entra no loop penso que é pelo primeiro valor do apontador estar a NULL mas não sei pk :S

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já descobri o prob :S lol era o i++ que tinha de tar dentro do if e eu tinha fora:S

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não deixei na mesma ha só fiz akela modificação com o strdup que o Rui Carlos referiu para depois fazer free ao apontador depois de o usar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não deixei na mesma ha só fiz akela modificação com o strdup que o Rui Carlos referiu para depois fazer free ao apontador depois de o usar.

não te esqueças de apagar a outra linha em que fazia o 'malloc'.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mas libertar o que. É que o código que estava, alocava 2 vezes.

Podes coloca o código final?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

#include <dirent.h> 
#include <string.h>
#include <sys/types.h> 
#include <sys/stat.h> 

#include <stdio.h>
#include <stdlib.h>

typedef struct dirent dirent;

char **getList(char *dire){

char **lista = (char**) malloc(50*sizeof(char*));

int i = 0;
struct stat sb;
char *str = (char *)malloc(50);
DIR *d;

dirent *dir;
d = opendir(".");
if(d){
    	while ((dir = readdir(d)) != NULL){
    		if (stat(dir->d_name, &sb) == 0 && (strcmp(dir->d_name,".")) && (strcmp(dir->d_name,".."))){
    			lista[i] = (char*)malloc(20*sizeof(char));
    			sprintf(str,"%d",(int)sb.st_size);
    			strcat(str,"\t\t- ");
    			strcat(str,dir->d_name);
    			lista[i] = strdup(str);
    			i++;
    		}
    	}
free(str);
    closedir(d);
  	}
  	return lista;
}

Tá assim.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lista[i] = (char*)malloc(20*sizeof(char));
...
lista[i] = str;

[...]

experimenta eliminar a primeira linha e colocar em vez da segunda: lista[ i ] = strdup(str);, deve resolver este problema.

tal como já te tinha dito, devias ter apagado uma linha.

com o 'strdup' deixa de ser necessária a linha: lista[ i ] = (char*)malloc(20*sizeof(char));

o 'strdup' já aloca o espaço, se quiseres ser tu a alocá-lo então deves usar o 'strcpy'.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora