Função que retorna vetor de char em C

Eu estou tentando retornar o vetor de char mas não consigo.

char * FuncAluno(float nota){
    char res[20];
    if((nota < 0) || (nota > 100)){
       res[0] = 'E';
       res[1] = 'R';
       res[2] = 'R';
       res[3] = 'O';
    }
    else if(nota < 60){
       res[0] = 'R';
       res[1] = 'E';
       res[2] = 'P';
       res[3] = 'R';
       res[4] = 'O';
       res[5] = 'V';
       res[6] = 'A';
       res[7] = 'D';
       res[8] = 'O';
    }
    else{
       res[0] = 'A';
       res[1] = 'P';
       res[2] = 'R';
       res[3] = 'O';
       res[4] = 'V';
       res[5] = 'A';
       res[6] = 'D';
       res[7] = 'O';
    }
    return res;
}
int main(int argc, char** argv) {
    char res[20];
    float nota;
    scanf("%f", &nota);
    FuncAluno(nota);
    printf("%s", res);
    return (EXIT_SUCCESS);
}

Sei que pode ter alguns erros meio idiotas, faz pouco tempo que estou aprendendo C.

Oi @Raul01

crie a variável que você quer retornar como um ponteiro e use o malloc.

#include <stdio.h>
#include <stdlib.h> // esse é para o malloc //

char * FuncAluno(float nota){
    
    // declara como um ponteiro ...
    char *res;
    
    // alocando 20 posições de char
    // igual ponteiro ...
    res=malloc(20*sizeof(char));

    if((nota < 0) || (nota > 100)){
       res[0] = 'E';
       res[1] = 'R';
       res[2] = 'R';
       res[3] = 'O';
    }
    else if(nota < 60){
       res[0] = 'R';
       res[1] = 'E';
       res[2] = 'P';
       res[3] = 'R';
       res[4] = 'O';
       res[5] = 'V';
       res[6] = 'A';
       res[7] = 'D';
       res[8] = 'O';
    }
    else{
       res[0] = 'A';
       res[1] = 'P';
       res[2] = 'R';
       res[3] = 'O';
       res[4] = 'V';
       res[5] = 'A';
       res[6] = 'D';
       res[7] = 'O';
    }
    return res;
}
int main(int argc, char** argv) {
    float nota;
    scanf("%f", &nota);
    printf("%s", FuncAluno(nota));
    return 0;
}
1 curtida

esqueci de comentar, no seu código o erro era…
você não tinha atribuído nada a variável ‘res’ no main.
E quando você declara uma variável dentro da função, ela vai só existir dentro da função, quando você vai o ponteiro ‘char res[20];’ dentro da função é um alocamento estático ( existindo apenas na função) para que isso usamos o malloc.

1 curtida

vamos entender pq vc não consegue.

em C vc tem arrays e vc tem o ponteiro

um array é uma região contigua de memoria.

um ponteiro contem um endereço de memoria.

quando vc declara char res[20]; o compilador vai alocar uma região 20 vezes o tamanho sizeof(char).

agora vem a ideia de escopo. se vc declara uma variavel fora de qq função ela é dita “global” pois qq função pode ve-la. se vc declara uma variavel dentro de uma função ( ou melhor, dentro de qq bloco lexico ) ela sera acessivel apenas dentro daquele dominio - por isso ela é dita “local”.

acabou o escopo, acabou O ACESSO A variavel. simples assim. ( não utilize um ponteiro pra essa variavel ou vc vai ter surpresas… ).

vc declarou char res[20] dentro do main. esse array sera acessivel apenas dentro do main. FuncAluno não tem acesso a este escopo.

agora o que é a variavel ‘res’ ? é um array pois vc declarou-a como um array. vc acessa os elementos via res[0], res[1], etc. agora res também age como um ponteiro para a primeira posição de memoria e quando vc faz res[3] na verdade vc esta acessando uma posição de memoria 3 “chars” a frente da posição zero.

por isso um array em C começa em zero. o compilador sabe fazer rapidamente a aritmetica e vc tem o valor que vc quer.

agora pq vc não pode retornar um array? isso tem haver com a pilha de retorno do C. é meio complicado explicar isso.

mas vc pode retornar um endereço de memoria! sim!

agora memoria daonde? se vc declara uma variavel local a mesma tem um endereço de memoria e vc pode retornar. acontece que ao final da execução da função vc não tera aquela região de memoria disponivel, vai ser reusada em outra coisa e vc perdeu.

então vc tem duas opções

  1. recebe o ponteiro na lista de argumentos ( e todo mundo fica feliz )

  2. vc ALOCA dinamicamente memoria e retorna um ponteiro.

a alocação dinamica pode ser feito com malloc e cada malloc exige um ( e apenas um ) free senão vc tera memoria alocada mas não desalocada e isso gera um memory-leak ( o programa que cresce em memoria e come tudo, seu pior pesadelo ). se o seu programa é simples vc pode esquecer o free pois no final do programa tudo voltara ao sistema operacional ( mas se vc tiver um programa que faz coisas em um loop, como um servidor de alguma coisa, cada malloc vai comer um pouco de memoria e ai em algum momento babau ).

mas vc não precisa usar malloc. existem outros alocadores que usam outras tecnicas. de fato vc pode criar um array gigante como variavel global e retornar um endereço a partir desse array ( vc tem que garantir que não vai dar o mesmo pedaço duas vezes ). é divertido implementar isso ( ate pq vc precisa desalocar, é um exercicio interessante ).

enfim, o seu problema se resolve de uma forma simples: entendendo as regras de escopo e entendendo que arrays e ponteiros são quase a mesma coisa (porem tem suas diferenças e é importante sabe-lo)

4 curtidas

Nossa, muito obrigado pelo código e pela explicação (explicou melhor que meu professor). Eu aprendi alocação dinâmica recentemente e não estava muito entendido. Vlw msm.