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

Nazgulled

Acrescentar uma string a um array de strings

16 mensagens neste tópico

Supondo que eu tenho isto:

char *str1[] = {"AA", "BB"};
char *str2[] = {"UM", "DOIS", "TRES"};

Como é que a partir destes 2 arrays de strings posso obter um array de strings com o conteúdo:

{"AA", "BB", "UM", "DOIS", "TRES"}

Anyone?  :wallbash:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crias um novo array e colocas os dois.

Para a criação de um novo podes usar o realloc(...), pode ser que seja possivel esticar o array actual. Mas nada é garantido.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Lol... e como faço eu isso? Era isso que estava a perguntar...

Já andei a tentar inventar, mas não consigo por nada a funcionar...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O realloc no teu caso é provavel que não funcione porque estás a iniciar os arrays na stack. E parece-me que o realloc não vai conseguir copiar ponteiros da stack.

A solução provavelmente será alocar os arrays na heap e realocar um desses arrays.

Ou simplesmente esquecer o realloc e copiar tudo. A diferença é que em um lado copias ponteiros e no outro tens de copiar todo o conteudo.

O que me leva a verificar que tens de fazer alguma coisa para identificar o tamanho desses arrays. Nem que seja um '\0'

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tas a complicar de mais para mim lol... tas ai a falar de coisas que eu nunca ouvi, tipo "heap"?? Eu dei este exemplo porque acho que seria simples para me explicarem o que teria de fazer para que isto funcionasse... O que eu realmente pretendo:

Eu tenho uma função generica que vai imprimir um simples menu com determinadas opções, essas opções esta declarado como no exemplo acima. Tipo:

char *menuops[] = {"Opção 1", "Opção 2", "Opção 3"};

Depois, só tenho de passar a variavel "menuops" como argumento dessa tal função. Eu já tenho isto a funcionar, mas apenas para o menu principal, onde tenho ja definido no codigo a variavel "menuops" com as devidas opções, isto esta a funcionar.

O que eu pretendo fazer agora é, ler de determinado directório os ficheiros (os seus nomes) que lá existem e usar os nomes como opções do menu. Ler ficheiro de um directório já consegui fazer, o que me falta agora é pegar nesses nomes e coloca-los num array de strings para posteriormente passar esse array para a função que imprime o menu.

Essas explicações técnicas que falas ai, não me dizem nada, porque estas a falar de coisas das quais eu não sei. Eu apenas quero a forma mais simples de ter um array definido como:

char *menuops[];

E conforme for necessário, adicionar-lhe strings, que neste caso, serão os nomes dos ficheiros...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então em palavras simples. Tens de criar um novo array com o tamanho dos dois e copiar tudo de um lado para o outro. Melhor será criar um array já com algum tamanho adicional. De qualquer forma a inserção é dinâmica, o que torna impossivel escapares pelo menos ao malloc(...)

Para dar um exemplo do que estava a falar anteriormente:

char **str1 = (char**)malloc(2*sizeof(char*));
char **str2 = (char**)malloc(3*sizeof(char*));

str2[0] = (char*)malloc(3*sizeof(char));

str2[0] = "UM\0"; 

char **str3 = (char**)realloc(str2, 5*sizeof(char*));

std::cout<<str3[0];

 

cout é c++ mas se quiseres substitiu por printf(...)

Os arrays não são lá grande coisa para fazer o que queres. Eu aconselhava listas ligadas. Mas isso é contigo.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu sei o que é o cout e o cin :D

Para aquilo que eu quero fazer, acho o teu código um bocado confuso e acabei por conseguir desta forma:

char *options[] = {"Option 1", "Option 2", "Option 3"};
char **myStringArray;
int i, numOps;

numOps = sizeof(options) / sizeof(char *);

myStringArray = malloc(numOps * sizeof(char *));

for (i = 0; i < numOps; i++) {
myStringArray[i] = malloc(strlen(options[i]) * sizeof(char));
strcpy(myStringArray[i], options[i]);
}

for (i = 0; i < numOps; i++) {
printf("%s\n", myStringArray[i]);
}

return 0;

Quanto ás listas ligadas... Eu pensei nisso, facilitava-me um bocado as coisas porque já sei trabalhar com elas e esta cena de apontadores à misturar com arrays de strings e por ai, ainda me confundo um pouco, mas esta solução, parece-me simples e eficaz para o que eu pretendo. Com listas ligadas ia ter mais código e para este objectivo simples acho desnecessário o uso de listas ligadas.

De qualquer forma, obrigado pela ajuda... Se notares ai algum pormenor no código que possa ser melhorado avisa... Sem altera-lo muito, porque para mim, isto está simples e funciona.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

a vantagem de usar o 'realloc' é que se houver espaço para aumentar o array não é necessário copiar os elementos já existentes (e mesmo quando é necessário o 'realloc' faz isso automaticamente).

só mais uma observação em relação ao teu último código, a linha

myStringArray[ i ] = malloc(strlen(options[ i ]) * sizeof(char));

não deve ser necessária, não precisas de aumentar o tamanho dos arrays das strings (acho eu), penso que podes simplesmente copiar o apontador. mas mesmo que queiras copiar a string, parece-me que o espaço que estás a alocar não é suficiente (falto espaço para o '\0'), além disso podias usar apenas a função 'strdup', em vez das duas linhas que tens (myStringArray[ i ]=strdup(options[ i ]);).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Basicamente essa é a solução de copiar todo o conteudo que referi.

Usando a opção dinâmica podes copiar apenas os ponteiros, já que char **myStringArray é basicamente um array de ponteiros para char. Acelerando bastante a cópia. E com o realloc pode acontecer que nem seja necessário fazer a cópia de alguns ponteiros.

Rui Carlos:

Da forma como foi definido esta linha:

char *options[] = {"Option 1", "Option 2", "Option 3"};

Não pode copiar apontadores, porque o conteudo está na Stack do programa. Inclusive se o realloc for usado com a Stack , o programa rebenta porque não pode usar nem copiar a Stack.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não conhecia essa função strdup() thank u :D

Mas sabem que mais? No meu verdadeior código não funciona... dammit... no exemplo que postei em cima funciona na boa, mas no que eu realmente pretendo fazer, não está a funcionar.

void loadCategories(void) {
    struct dirent *dpItem;
    char **catList;
    int i, j;	

    DIR *dp;

    if((dp = opendir("data/games/JF")) != NULL) {   	
    	while((dpItem = readdir(dp)) != NULL) {
    		if(strcmp(dpItem->d_name, ".") && strcmp(dpItem->d_name, "..")) {
		catList[i] = strdup(dpItem->d_name);
    		}
    	}
    	
    	mvprintw(0,0, "%s\n", catList[0]);

refresh();

    	closedir(dp);
    }
}

A linha mvprintw(0,0, "%s\n", catList[0]); dá um segmentation fault e eu não entendo porquê... Fiz igual ao exemplo acima, a diferença é que no exemplo acima já tinha um array de strings com conteudo, agora, estou a ler nomes de ficheiros...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Provavelmente pelo facto de que estás a copiar a stack com strdup(...) e os endereços não são válidos. De qualquer forma como não conheço bem essa função não tenho a certeza. Mas alerto para o facto de não violar a Stack.

Bem neste caso é diferente. Esse d_name deve ser alocado dinâmicamente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já descobri... primeiro, tenho de inicializar o i a 0, mas eu pensava que todos os inteiros tivessem 0 ao serem declarados caso não lhes fosse atribuido um valor, parece que não... E segundo, eu estou apenas a alocar (com o strdup() agora mas anteriormente com o malloc()) memória para cada string do genero catList[ i ] = strdup() mas antes disto tinha de alocar também para a catList apenas do genero catList = malloc() antes do ciclo while. E agora já está a funcionar.

O único problema é que preciso de saber o número de strings (ou seja, número de ficheiros que estão no directório) que vou ter para alocar a memória necessária e para isso, acho que vou ter de percorrer o directório 2 vezes, ou será que não?

Por exemplo, antes do while, coloquei isto:

catList = malloc(2 * sizeof(char *));

Aquele 2 está ali porque apenas existem 2 ficheiros, mas se existirem mais? Será que ha outra forma de alocar esta memória sem eu saber quantos ficheiros estão lá?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Uma pergunta. Esse operador -> é de C++, afinal estamos em que?

Se é C++ usavas logo vector<> e tinhas o problema resolvido.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Basicamente essa é a solução de copiar todo o conteudo que referi.

Usando a opção dinâmica podes copiar apenas os ponteiros, já que char **myStringArray é basicamente um array de ponteiros para char. Acelerando bastante a cópia. E com o realloc pode acontecer que nem seja necessário fazer a cópia de alguns ponteiros.

Rui Carlos:

Da forma como foi definido esta linha:

char *options[] = {"Option 1", "Option 2", "Option 3"};

Não pode copiar apontadores, porque o conteudo está na Stack do programa. Inclusive se o realloc for usado com a Stack , o programa rebenta porque não pode usar nem copiar a Stack.

eu sei que o 'realloc' não funcionava no código que ele tinha colocado, mas aquilo era apenas um exemplo, na situação real provavelmente ele não vai fazer a inicialização das variáveis na declaração das mesmas logo poderá usar o 'malloc' sem aumentar a complexidade do código.


Provavelmente pelo facto de que estás a copiar a stack com strdup(...) e os endereços não são válidos. De qualquer forma como não conheço bem essa função não tenho a certeza. Mas alerto para o facto de não violar a Stack.

Bem neste caso é diferente. Esse d_name deve ser alocado dinâmicamente.

o 'strdup' faz um 'malloc' e depois um 'strcpy'. por isso o problema da stack já não existe porque no máximo vais ler de lá valores que são sempre copiados para a heap.

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