Pergunta

as said on the title, my function is not calculating the correct amount os characters in a given string.

The function is this one:

   void contar(char **texto, int *quantidade, int N)
 {
    int i, j, aux;

    for(i=0;i<N;i++)
    {
        for(j=0;texto[i][j]!='\0';j++)
        {
            aux = (int) texto[i][j];            
            /* If upper case */
            if(64 < aux && aux < 91)
            {
                aux = aux - 65;
                quantidade[aux]++;
            }
            /* If lower case */
            else if(96 < aux && aux < 123)
            {
                aux = aux - 71;
                quantidade[aux]++;
            }
        }
    }
    for(i=0;i<52;i++)
    {
        printf("\n i-%d  %d\n", i, quantidade[i]);
    }
 }

My objective is: take the character, check his number according to the ASCII table. If the number represents an Upper Case Character, I subtract it by 65 and use it as the index of my vector and increment the vector in that position. If it is a Lower Case Character, I subtract it by 71, because the last Upper Case Character is Z, which corresponds to 90. And the 'a' corresponds 97. So 90 - 65 = 25 and 97 - 65 = 32, as I dont wanna leave this gap in the vector, I do 97 - 65 - 6.

What is happening is that, for certain characters, the function is counting 1 character less. For example, on the text below, the function counts only 5 'A', when there is actually 6.

Duvidas Frequentes E um grau do ensino superior obtido em cursos de Graduacao, ministrados pela Universidade, destinados a alunos que tenham concluido o ensino medio ou equivalente. A Unicamp oferece cursos de Graduacao em diferentes areas do conhecimento. A estrutura de ensino e pesquisa da Unicamp esta, em sua maior parte, no campus de Barao Geraldo, em Campinas. Em Piracicaba funciona a Faculdade de Odontologia de Piracicaba (FOP); em Limeira, a Faculdade de Tecnologia (FT) e Faculdade de Ciencias Aplicadas (FCA); em Paulinia, o Centro de Pesquisas Quimicas, Biologicas e Agricolas (CPQBA); em Sumare, o Hospital Estadual; e, em Hortolandia, o Hospital Mario Covas.

The rest of the code is the following one:

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

 void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N);
 void matriz_ascii(char **texto, int **ascii, int N);
 void ordenar(int *quantidade, int *prioridade);
 void contar(char **texto, int *quantidade, int N);
 int checarMaior(int *quantidade, int i);
 void troca(int **ascii, int *prioridade, int N);

 int main()
 {
    int N, i, j, quantidade[52], prioridade[26], **ascii;
    char **texto;

    for(i=0;i<52;i++)
    {
        quantidade[i] = 0;
    }

    for(i=0;i<26;i++)
    {
        prioridade[i] = 0;
    }
    scanf("%d", &N);

    setbuf(stdin, 0);

    texto = malloc(N * sizeof(char *));
    ascii = malloc(N * sizeof(char *));

    for(i=0;i<N;i++)
    {
        texto[i] = malloc(501 * sizeof(char));
        ascii[i] = malloc(501 * sizeof(char));
    }

    for(i=0;i<N;i++)
    {
        fgets(texto[i], 501, stdin);
    }

    encriptar(texto, ascii, quantidade, prioridade, N);

    for(i=0;i<N;i++)
    {
        for(j=0;texto[i][j];j++)
        {
            texto[i][j] = (char) ascii[i][j];
        }
    }

    printf("\n");

    for(i=0;i<N;i++)
    {
        printf("%s", texto[i]);
    }

    printf("\n");

    for(i=0;i<26;i++)
    {
        printf("%d ", prioridade[i]);
    }

    printf("\n");       

    return 0;
 }

 void encriptar(char **texto, int **ascii, int *quantidade, int *prioridade, int N)
 {
    matriz_ascii(texto, ascii, N);

    contar(texto, quantidade, N);

    ordenar(quantidade, prioridade);

    troca(ascii, prioridade, N);
 }

 void matriz_ascii(char **texto, int **ascii, int N)
 {
    int i, j;

    for(i=0;i<N;i++)
    {
        for(j=0;texto[i][j]!='\0';j++)
        {
            ascii[i][j] = (int) texto[i][j];
        }
    }
 }

 void contar(char **texto, int *quantidade, int N)
 {
    int i, j, aux;

    for(i=0;i<N;i++)
    {
        for(j=0;texto[i][j]!=0;j++)
        {
            /*aux = (int) texto[i][j];
            printf("%d ", aux); */      
            /* Se for maiusculo */
            if(65 <= texto[i][j] && texto[i][j] <= 90)
            {
                aux = texto[i][j] - 65;
                quantidade[aux]++;
            }
            /* Se for minusculo */
            else if(97 <= texto[i][j] && texto[i][j] <= 122)
            {
                aux = texto[i][j] - 71;
                quantidade[aux]++;
            }
        }
        printf("\n");
    }
    /*for(i=0;i<52;i++)
    {
        printf("\n i-%d  %d\n", i, quantidade[i]);
    }*/
 }

 void ordenar(int *quantidade, int *prioridade)
 {
    int i, i_maior;
    for(i=0;i<26;i++)
    {
        quantidade[i] += quantidade[i+26];
    }

    for(i=0;i<26;i++)
    {
        i_maior = checarMaior(quantidade, 0);
        quantidade[i_maior] = -1;
        prioridade[i] = i_maior;
    }

 }

 int checarMaior(int *quantidade, int i)
 {
    int i_maior = i, maior = quantidade[i];

    for(i=i+1;i<26;i++)
    {
        if(quantidade[i] > maior)
        {
            maior = quantidade[i];
            i_maior = i;
        }
        else if(quantidade[i] == maior)
        {
            if(i < i_maior)
            {
                i_maior = i;
            }
        }
    }

    return i_maior;
 }

 void troca(int **ascii, int *prioridade, int N)
 {
    int i, j, i_aux, i_num, aux, valor = -1;
    for(i=0;i<N;i++)
    {
        for(j=0;ascii[i][j];j++)
        {   
            aux = ascii[i][j];
            /* Se for maiusculo */
            if(64 < aux && aux < 91)
            {
                aux = aux - 65;
                valor = 1;
            }
            /* Se for minusculo */
            else if(96 < aux && aux < 123)
            {
                aux = aux - 97;
                valor = 0;
            }
            else
            {
                valor = -1;
            }

            if(valor != -1)
            {
                for(i_aux=0;i_aux<26;i_aux++)
                {
                    if(prioridade[i_aux] == aux)
                    {
                        i_num = i_aux;
                    }
                }
                if(i_num % 2 == 0)
                    aux = prioridade[i_num+1];
                else
                    aux = prioridade[i_num-1];

                if(valor == 1)
                    ascii[i][j] = aux + 65;
                else if(valor == 0)
                    ascii[i][j] = aux +97;
            }
        }   
    }
 }

Any ideas of what I am doing wrong?

Thanks in advance!

Foi útil?

Solução

The quantidade function seems OK. But this loop in matriz_ascii has a problem:

for(i=0;i<N;i++)
    {
        for(j=0;texto[i][j]!='\0';j++)
        {
            ascii[i][j] = (int) texto[i][j];
        }
    }

This does not copy the null-terminator. But later on, in troca you have a loop that runs until ascii[i][j] == 0;. That loops will run off the end of the copied values until they happen to come across a 0 in other memory, which is bad.

As you point out in comments, you malloc the wrong amount of space also (on two different lines). You could have avoided that by using this idiom:

texto = malloc(N * sizeof *texto);
ascii = malloc(N * sizeof *ascii);

for(i=0;i<N;i++)
{
    texto[i] = calloc(501, sizeof *texto[i]);
    ascii[i] = calloc(501, sizeof *ascii[i]);
}

The reason I use calloc is so that if your fgets lines fail (e.g. due to end of input) then your array contains blank strings, which your code handles correctly. Without that, a short input file would cause your code to operate on uninitialized memory.

Other things you can do to make your code more readable and robust:

  • replace magic numbers like 65 with 'A',
  • replace loops that set things to 0 with initialization to = { 0 };, or calloc
  • Check that malloc does not return NULL.

Also you should make more of an effort to debug before posting on here. If something is not working, then change your code to add extra debugging output (or use a debugger) until you find out exactly which little piece is causing the program to go from good to bad. Also you can try valgrind.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top