Jump to content

Acrescentar uma string a um array de strings


Guest id194
 Share

Recommended Posts

Guest id194

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:

Link to comment
Share on other 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.

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other 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'

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other sites

Guest id194

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...

Link to comment
Share on other 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.

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other sites

Guest id194

Eu sei o que é o cout e o cin 😄

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.

Link to comment
Share on other 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 ]);).

Link to comment
Share on other 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.

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other sites

Guest id194

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

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...

Link to comment
Share on other 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.

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other sites

Guest id194

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á?

Link to comment
Share on other sites

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

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

Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!

Link to comment
Share on other 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.

Link to comment
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
 Share

×
×
  • 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.