Autor Tópico: Retornando vetor de strings em C  (Lida 12178 vezes)

Offline mhkgalvez

  • Usuário Ubuntu
  • *
  • Mensagens: 289
  • Não temas: A Esperança VIVE!!!
    • Ver perfil
    • The Century Truth - Conhecendo a Verdade deste Século.
Retornando vetor de strings em C
« Online: 04 de Junho de 2010, 15:22 »
Olá pessoal, tenho uma função que desejo que retorne um vetor de Strings em C.

Estou usando
Código: [Selecionar]
char *hasError(char *stream), mas não dá certo.

Minha função main:

Código: [Selecionar]
int main (int argc,char *argv[])
{
    char *text;
    text = takeEptSpc("5 5 ");
    char *ret;
    
    ret = hasError("5 5 ");

    int i = 0;

    for (i = 0; i < 5; i++)
        printf("%s", ret[i]);
    return 0;
}

Na execução, ele retorna erro de segmentação.

O que posso fazer para retornar corretamente um vetor de strings?
« Última modificação: 04 de Junho de 2010, 15:24 por mhkgalvez »
"A quem vencer, eu o farei coluna no templo do meu Deus, e dele nunca sairá; e escreverei sobre ele o nome do meu Deus, e o nome da cidade do meu Deus, a nova Jerusalém, que desce do céu, do meu Deus, e também o meu novo nome."

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Retornando vetor de strings em C
« Resposta #1 Online: 04 de Junho de 2010, 18:38 »
mhkgalvez poste o código completo, senão num tem como saber onde tá a falha  :P
Gentoo — Controle total sobre o sistema.

Offline mhkgalvez

  • Usuário Ubuntu
  • *
  • Mensagens: 289
  • Não temas: A Esperança VIVE!!!
    • Ver perfil
    • The Century Truth - Conhecendo a Verdade deste Século.
Re: Retornando vetor de strings em C
« Resposta #2 Online: 04 de Junho de 2010, 18:50 »
Função hasError:

Código: [Selecionar]
char *hasError(char *stream, char mode)
{
    int i = 0, htmlCodeLenght = 1;
    int *listGt, *listLt;
    int countLt = 0, countGt = 0;
    char *htmlCode = stream;
    char *out[5];

    stream = takeEptSpc(stream);

    //Initializing out array   
    for (i = 0; i < 5; i++)
    {
        out[i] = "";
    }
    //End initializing out array

    //Looking at '<' and '>' chars
    htmlCodeLenght = countString(htmlCode);
    for (i = 0; i < htmlCodeLenght; i++)
    {
        if (htmlCode[i] == '<')
        {
            countLt++;
        }
        if (htmlCode[i] == '>')
        {
            countGt++;
        }
    }

    if (countGt != countLt)
    {
        printf("Error 1 of HTML Tag. The tags weren't opened or closed correctly.");
        out[0] = "Error 1 of HTML Tag. The tags weren't opened or closed correctly.";
        if (mode == 'o')
            return out;
    }

    listLt = (int *) malloc(countGt * sizeof(int));
    listGt = (int *) malloc(countGt * sizeof(int));

    for (i = 0; i < countGt; i++)
    {
        if (htmlCode[i] == '<')
        {
            listLt[i] = i;
        }
        if (htmlCode[i] == '>')
        {
            listGt[i] = i;
        }
    }

    for (i = 0; i < countGt; i++)
    {
        if (listGt[i] < listLt[i])
        {
            printf("Error 2 of HTML Tag. The tags weren't opened or closed correctly.");
            out[1] = "Error 2 of HTML Tag. The tags weren't opened or closed correctly.";
            if (mode == 'o')
                return out;
        }
    }
    //End looking at '<' and '>' chars

    //Looking at order of '<' and '>' chars
    int ind = 0;

    for (i = 0; i < countGt; i++)
    {
        while (htmlCode[ind] != '<' && htmlCode[ind] != '>')
            ind++;

        if (htmlCode[ind] == '>')
        {
            printf("Error 3 of HTML Tag. The tags weren't opened or closed correctly.");
            out[2] = "Error 3 of HTML Tag. The tags weren't opened or closed correctly.";
            if (mode == 'o')
                return out;
        }
        if (htmlCode[ind] == '<')
        {
            while (htmlCode[ind] != '>')
            {
                if (htmlCode[ind] == '<')
                {
                    printf("Error 4 of HTML Tag. The tags weren't opened or closed correctly.");
                    out[3] = "Error 4 of HTML Tag. The tags weren't opened or closed correctly.";
                    if (mode == 'o')
                        return out;
                }
                ind++;
            }
        }
    }
    //End looking at order of '<' and '>' chars

    printf("Código HTML sem nenhuma falha");
    return out;
}

Considero que não tem erro nela, pois os vetores são iniciados com vazio no início. Por isso, creio que o erro esteja no tipo de retorno da função.
"A quem vencer, eu o farei coluna no templo do meu Deus, e dele nunca sairá; e escreverei sobre ele o nome do meu Deus, e o nome da cidade do meu Deus, a nova Jerusalém, que desce do céu, do meu Deus, e também o meu novo nome."

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Retornando vetor de strings em C
« Resposta #3 Online: 04 de Junho de 2010, 19:55 »
Realmente...parece que tá certo...

Você colocou todas as bibliotecas? Tá usando o gcc como compilador?
Gentoo — Controle total sobre o sistema.

Offline RonaldoRG

  • Usuário Ubuntu
  • *
  • Mensagens: 659
    • Ver perfil
    • Twitter: @rafas_andrade
Re: Retornando vetor de strings em C
« Resposta #4 Online: 04 de Junho de 2010, 20:30 »
Não seria porque você tá retornando "out" que está declarado como "char *out[5]" que é um vetor de ponteiros? Na função main você tá atribuindo o retorno da função para um ponteiro.

Eu fiz um teste simples aqui sobre esse retorno e deu erro.
Ubuntu 12.04

Offline mhkgalvez

  • Usuário Ubuntu
  • *
  • Mensagens: 289
  • Não temas: A Esperança VIVE!!!
    • Ver perfil
    • The Century Truth - Conhecendo a Verdade deste Século.
Re: Retornando vetor de strings em C
« Resposta #5 Online: 04 de Junho de 2010, 22:56 »
Pessoal, o que acontece é que fazia algum tempo que eu programava em C, e essa questão de trabalhar com strings em C sempre me confundiu, então, vejam bem:

-> Para eu criar um texto simples eu faria char *texto e atribuiria o valor da string, por exemplo:

Código: [Selecionar]
texto = "olá";
No caso de um vetor de strings, eu faria char *text[10] onde 10 seria o número de strings. E, na função hasError este tipo de uso está funcionando.
O problema é quando retorno isso. Eu tentei usar, como assinatura da função hasError um retorno char[], ou char hasError(...)[], ou ainda char[10], etc. Mas antes mesmo de compilar no NetBeans 6.8 acusa erro se sintaxe.

O problema de fazer sem ser uma variável de ponteiros é que, eu acho [me corrijam se eu estiver errado] que não dará para eu colocar as strings do tamanho que eu quiser. Desta maneira, ficarei limitado.

Volto a dizer que estou enferrujado. Haveria, então, alguma forma de contornar este problema?
"A quem vencer, eu o farei coluna no templo do meu Deus, e dele nunca sairá; e escreverei sobre ele o nome do meu Deus, e o nome da cidade do meu Deus, a nova Jerusalém, que desce do céu, do meu Deus, e também o meu novo nome."

Offline RonaldoRG

  • Usuário Ubuntu
  • *
  • Mensagens: 659
    • Ver perfil
    • Twitter: @rafas_andrade
Re: Retornando vetor de strings em C
« Resposta #6 Online: 04 de Junho de 2010, 23:30 »
Citar
No caso de um vetor de strings, eu faria char *text[10]
Ai você tá declarando um vetor de ponteiros com 10 posições, é como se fosse um ponteiro para ponteiro. Com isso você pode criar uma matriz de strings.
Para um vetor de strings basta "char text[10]", ai você tem um vetor de strings com 10 posições, ou usando ponteiros "char *text = (char*)maloc(10*sizeof(char));".
Ubuntu 12.04

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Retornando vetor de strings em C
« Resposta #7 Online: 05 de Junho de 2010, 15:21 »
Citar
No caso de um vetor de strings, eu faria char *text[10]
Ai você tá declarando um vetor de ponteiros com 10 posições, é como se fosse um ponteiro para ponteiro. Com isso você pode criar uma matriz de strings.
Para um vetor de strings basta "char text[10]", ai você tem um vetor de strings com 10 posições, ou usando ponteiros "char *text = (char*)maloc(10*sizeof(char));".
pra deixar mais simples ainda você pode inicializar o valor do vetor na declaração mesmo:
  char text[10]="olá";
Gentoo — Controle total sobre o sistema.

Offline mhkgalvez

  • Usuário Ubuntu
  • *
  • Mensagens: 289
  • Não temas: A Esperança VIVE!!!
    • Ver perfil
    • The Century Truth - Conhecendo a Verdade deste Século.
Re: Retornando vetor de strings em C
« Resposta #8 Online: 05 de Junho de 2010, 20:26 »
Tah mas e o problema do retorno!??? ???
"A quem vencer, eu o farei coluna no templo do meu Deus, e dele nunca sairá; e escreverei sobre ele o nome do meu Deus, e o nome da cidade do meu Deus, a nova Jerusalém, que desce do céu, do meu Deus, e também o meu novo nome."

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Retornando vetor de strings em C
« Resposta #9 Online: 05 de Junho de 2010, 21:43 »
Tah mas e o problema do retorno!??? ???
ainda não sei...

mas na sua função main você passou um parâmetro errado em 'hasError()', ou melhor dizendo, você só passou um parâmetro, mas a 'hasError()' tava definida para receber dois.
Gentoo — Controle total sobre o sistema.

Darcamo

  • Visitante
Re: Retornando vetor de strings em C
« Resposta #10 Online: 07 de Junho de 2010, 21:22 »
O problema é que em C puro você não tem realmente um tipo de variável para strings. O que é feito então em C é utilizar um vetor caracteres "como se fosse uma string", mas você não pode esquecer que isso na verdade é apenas um vetor de caracteres. Lembre-se também que um vetor nada mais é do que um ponteiro para o primeiro elemento do vetor.

Isso quer dizer que você deve sim dizer qual o tamanho do vetor quando declarar uma variável usada para guardar uma "string".
Quando você escreve algo como
Código: [Selecionar]
hello = "hello";o que acontece é que o "hello" é um array de char e a variável 'hello' recebe o endereço desse array de char então está tudo bem nesse caso.

Se você quiser copiar strings de uma variável para outra você deve usar a função strcpy. Se você simplesmente usar "=" você estará na verdade copiando o endereço de uma variável para a outra e ambas vão apontar para a mesma região de memória. Compile e rode o programa abaixo para ver esse efeito.
Código: [Selecionar]
int main(int argc, char *argv[])
{
    char* hello = "Hello Cruel World";
    char hello2[20];
    char* hello3;

    /* Vamos copiar usando strcpy */
    strcpy(hello2,hello);
    hello3 = hello;

    /* Vamos imprimir o conteudo de cada variável */
    printf("%s\n",hello);
    printf("%s\n",hello2);
    printf("%s\n",hello2);
   
    /* Vamos imprimir o valor dos ponteiros para cada variável */
    printf("%p\n",hello);
    printf("%p\n",hello2);
    printf("%p\n",hello3);

    /* Note que hello e hello3 possuem o mesmo ponteiro */
   
    return 0;
}

Da mesma forma, se você tentar comparar strings com
Código: [Selecionar]
stringA == stringBvocê estará comparando apenas se os ponteiros são iguais e não se o conteúdo das variáveis corresponde a mesma string. A maneira correta é utilizar a função strcmp. No exemplo acima se você fizer se você fizer o teste "hello==hello2" vai dar falso, mesmo que ambas as variáveis tenham o mesmo conteúdo.

Esse site
http://www.cplusplus.com/reference/clibrary/cstring/
é uma boa referência.

Ps: Na verdade não tenho muita experiência com C puro, já que quase sempre programo em C++ (std::string é de fato um tipo para strings e é bem melhor de se trabalhar que um vetor de char puro), então se eu disse alguma besteira deem um desconto, mas em geral trabalhar com "strings" em C é bem chato.

Offline farinha

  • Usuário Ubuntu
  • *
  • Mensagens: 65
    • Ver perfil
Re: Retornando vetor de strings em C
« Resposta #11 Online: 08 de Junho de 2010, 11:33 »
Já experimentou usar o gdb e correr o programa passo a passo a ver onde é que quebra? Ou usar printscreens para ir vendo onde quebra?

Offline fpissarra

  • Usuário Ubuntu
  • *
  • Mensagens: 246
    • Ver perfil
    • Lost in the e-Jungle
Re: Retornando vetor de strings em C
« Resposta #12 Online: 08 de Junho de 2010, 11:39 »
Darcamo está correto na interpretação sobre "strings" em C.
Eis uma possível solução para o seu problema:

Código: [Selecionar]
#include <malloc.h>
#include <stdio.h>
#include <string.h>

static const char STR1[] = "String 1";
static const char STR2[] = "String 2";

/* Um macrozinho só para facilitar a vida... */
#define COPY_CONS_STRING(a, i, s) \
  (a)[(i)] = (char *)malloc(sizeof(char)*strlen((s))+1); \
  strcpy((a)[(i)], (s));

/*
  Como o array de strings pode ser definido como um "char **",
  precisamos passar um "char ***" para podermos alocar o vetor e retorná-lo.
*/
int GetStringArray(char ***strArray)
{
  char **out;

#define NUM_ITEMS 2

  out = (char **)malloc(sizeof(char *) * NUM_ITEMS);
 
  COPY_CONST_STRING(out, 0, STR1);
  COPY_CONST_STRING(out, 1, STR2);

  *strArray = out;

  /* Retorna o número de strings no array de strings */
  return NUM_ITEMS;
}

/* Libera strings alocadas */
void FreeStringArray(char **strArray, int count)
{
  int i;

  for (i = 0; i < count; i++)
  {
    free(strArray[i]);
    strArray[i] = NULL;
  }

  free(strArray);
}

int main(int argc, char **argv)
{
  int strCount, i;
  char **strings;

  /* Pega array de strings */
  strCount = GetStringArray(&strings);

  for (i = 0; i < strCount; i++)
    printf("%s\n", strings[i]);

  /* Libera array de strings */
  FreeStringArray(strings, strCount);

  return 0;
}

Mas, você pode achar mais fácil mexer com a STL, em C++, usando os templates/classes "vector" e "string".

[]s
Fred