Ir ao conteúdo

C Criar espaço na memória para CHAR, com propriedades de VETOR em LISTA estática.


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

Estou com um programa em desenvolvimento, quando executo ele compila normalmente. Quando seleciono a opção 1 na execução ele me pede as informações que desejo adicionar à lista. Ele pede o RA do aluno e até ai beleza.. Mas quando pede o nome do arquivo (char arquivo[20]) ele simplesmente encerra a execução do programa. Acredito que seja problema de alocação dinâmica de memoria por meio de ponteiros, mas estou preso nessa parte, com uma dificuldade de como implementar isso.

PS: Sou estudante de Análise e Desenvolvimento de Sistemas.

Segue o código:


 

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

#define tam 5

typedef struct tlista{
    int ra[5];
    char arquivo[20];
    char extensao[20];
    int matricula[5];
    int ini;
    int fim;
}tlista;

tlista lista;
int op;

void menu();
void show_info();
void add_info();
void del_info();
void clear();

int main(){
    setlocale(LC_ALL, "portuguese");
    op = 1;
    lista.ini = 0;
    lista.fim = 0;
    while(op != 0){
        system("cls");
        show_info();
        menu();
        scanf("%d", &op);
        switch(op){
            case 1:
            add_info();
            break;

            case 2:
            del_info();
            break;

            //Trecho comentado, ainda em desenvolvimento. Ignorar case3.

           /* case 3:
            clear();
            break; */
        }
    }
    printf("\n\n Até breve! Nos vemos depois.");
    return(0);
}

void menu(){
    printf("Selecione uma alternativa:\n\n");
    printf("[1] Adicionar Novo.\n");
    printf("[2] Remover Existente.\n");
    printf("[3] Limpar tudo.\n");
    printf("[0] Sair.\n\n");
}

void show_info(){
    int i;
    for ( i = 0; i < tam; i++)
    {
        printf("--------------------\n");
        printf("RA: %d\n", lista.ra[i]);
        printf("Arquivo: %s.%s\n", lista.arquivo[i], lista.extensao[i]);
        printf("Matricula: %d\n", lista.matricula[i]);
        printf("--------------------\n");
    }
}
void add_info(){
    if (lista.fim == tam){
        printf("A lista encheu! Remova elementos.\n\n");
        system("pause");
    }

    else{
        system("cls");
        printf("Digite o RA do aluno: ");
        scanf("%d", &lista.ra[lista.fim]);
        printf("Digite o nome do arquivo: ");
        scanf("%s", lista.arquivo[lista.fim]);
        printf("Digite a extensao do arquivo: ");
        scanf("%s", lista.extensao[lista.fim]);
        printf("Digite a matricula do professor: ");
        scanf("%d", lista.matricula[lista.fim]);
        lista.fim++;
    }
}
void del_info(){
    if (lista.ini == lista.fim){
        printf("A lista esvaziou! Adicione registros.");
        system("pause");
    }

    else{
        int i;
        for(i=0; i <tam; i++){
            lista.ra[i] = lista.ra[i+1];
            lista.arquivo[i] = lista.arquivo[i+1];
            lista.extensao[i] = lista.extensao[i+1];
            lista.matricula[i] = lista.matricula[i+1];
        }
        lista.ra[lista.fim] = 0;
        lista.arquivo[lista.fim] = "N/A";
        lista.extensao[lista.fim] = "N/A";
        lista.matricula[lista.fim] = 0;
        lista.fim--;
    }
}
//void clear();

 

  • Amei 1
Postado

@marcoosvlopes

24 minutos atrás, marcoosvlopes disse:

Acredito que seja problema de alocação dinâmica de memoria por meio de ponteiros

Que ponteiros? Que alocação dinâmica? 🤔

 

28 minutos atrás, marcoosvlopes disse:

Quando seleciono a opção 1 na execução ele me pede as informações que desejo adicionar à lista

O que você considera uma lista?

 

A respeito de seu programa...

O valor da variável `op´ (declarada no escopo global sem necessidade) faz com que o controle seja transferido para o escopo do while, e então as funções show_info() e menu() são chamadas.

Você não inicializou nenhuma das variáveis da struct tlista (rotulada sem necessidade aparente), logo:

image.png.b965859d5966a0de97d34ab06ece7fa4.png

Sem inicializar as variáveis, não há como saber o valor das mesmas.

E bem, existem outros problemas:

image.thumb.png.2daacb702bdf69045443e140831b9a35.png

Basta ler e interpretar. Por exemplo, este primeiro diz que o especificador de formato `%s´ espera um argumento do tipo `char*´, mas o argumento é do tipo `int´, e ele te diz a linha:

printf("Arquivo: %s.%s\n", lista.arquivo[i], lista.extensao[i]);

Talvez o intuito seria declarar um vetor de strings, mas no caso `arquivo´ e `extensao´ são apenas strings comuns, e ao indexá-las está apenas imprimindo um caractere.

  • Curtir 3
Postado

@marcoosvlopes    ponteiros é coisa bem complicada mesmo , eu também não sei fazer código com ponteiros , não   ,  mas seu programa está fechando repentinamente por que você não colocou esse símbolo  & no scanf :na função add_info(); , além de que a declaração da variáveL extensao ,se refere a uma string apenas , e você está lendo para um vetor   :

#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#define tam 5
typedef struct tlista
{
    int ra[5];
    char arquivo[20][30];
    char extensao[20][30];
    int matricula[5];
    int ini;
    int fim;
}tlista;

tlista lista;
int op;

void menu();
void show_info();
void add_info();
void del_info();
void clear();
void gotoxy_2(int , int );
void saindo();
int main()
{
    printf("aqui\n");
    setlocale(LC_ALL, "portuguese");
    op = 1;
    lista.ini = 0;
    lista.fim = 0;
    while(op != 0)
    {
        system("cls");
        menu();
        scanf("%d", &op);
        switch(op)
        {
        case 0:
            printf("\n\n\tSaindo Do Programa . . . !\n");
            break;
        case 1:
            add_info();
            break;
        case 2:
            del_info();
            break;
        case 4:
            show_info();
            break;
        default:
            printf("Opcao inVaLida . . . !\n\n");
            //Trecho comentado, ainda em desenvolvimento. Ignorar case3.

           /* case 3:
            clear();
            break; */
        }
    }
    printf("\n\n Até breve! Nos vemos depois.\n");
    saindo();
    printf("\n\n\n");
    return(0);
}
void menu()
{
    printf("\n\nSelecione uma alternativa:\n");
    printf("[0] Sair.\n");
    printf("[1] Adicionar Novo.\n");
    printf("[2] Remover Existente.\n");
    printf("[3] Limpar tudo.\n");
    printf("[4] mostrar Lista.\n");
    printf("    Digita a Opcao \\> ");
}
void show_info()
{
    int i;
    printf("\n----  ListanDo Todos os CadastroS   -------\n");
    for ( i = 0; i < lista.fim; i++)
    {
        printf("------------------------\n");
        printf("RA --------: %d\n", lista.ra[i]);
        printf("Arquivo ---: %s.%s\n", lista.arquivo[i], lista.extensao[i]);
        printf("Matricula -: %d\n", lista.matricula[i]);
        printf("--------------------\n");
    }
    printf("\n\n\t\tTecle . . . !\n");
    system("pause");
}
void add_info()
{
    char c;
    if (lista.fim == tam){
        printf("A lista encheu! Remova elementos.\n\n");
        system("pause");
    }

    else
    {
        system("cls");
        printf("Digite o RA do aluno ------------: ");
        scanf("%d", &lista.ra[lista.fim]);
        while( c = fgetc (stdin) != '\n'); // limpar o buffer do teclado
        printf("Digite o nome do arquivo --------: ");
        scanf("%s", lista.arquivo[lista.fim]);    // s de string pode pegar mais de um caractere
        // e aqui está tentando colocar muitos carateres dentro de apenas um byte , não Dá !
        printf("Digite a extensao do arquivo ----: ");
        scanf("%s", lista.extensao[lista.fim]);   // limpar o buffer do teclado
        while( c = fgetc (stdin) != '\n'); // limpar o buffer do teclado
        printf("Digite a matricula do professor -: ");
        scanf("%d", &lista.matricula[lista.fim]); // faltou esse & simbolo
        while( c = fgetc (stdin) != '\n');        // limpar o buffer do teclado
        lista.fim++;
    }
}
void del_info(){
    if (lista.ini == lista.fim){
        printf("A lista esvaziou! Adicione registros.");
        system("pause");
    }

    else{
        int i;
        for(i=0; i <tam; i++){
            lista.ra[i] = lista.ra[i+1];
            strcpy(lista.arquivo[i] , lista.arquivo[i+1]);
            strcpy(lista.extensao[i] , lista.extensao[i+1]);
            lista.matricula[i] = lista.matricula[i+1];
        }
        lista.ra[lista.fim] = 0;
        strcpy(lista.arquivo[lista.fim] , "N/A");
        strcpy(lista.extensao[lista.fim] , "N/A");
        lista.matricula[lista.fim] = 0;
        lista.fim--;
    }
}
//void clear();
void saindo()
{
    int letras[8][5] =
    {
        {15,16,14, 1,30}, /* letra  S */
        {14,17,31,17,17}, /* letra  A */
        {14, 4, 4, 4,14}, /* letra  I */
        {17,25,21,19,17}, /* letra  N */
        {30,17,17,17,30}, /* letra  D */
        {14,17,17,17,14}, /* letra  O */
        { 0, 0, 0, 0, 0}, /* letra    */
        { 1 , 2, 4, 0,16}, /* letra  ! */
    };
    int i, w,px,py,x;                          // variáveis simples
    HANDLE hOut;                               // controle dos dispositivos do pc
    hOut= GetStdHandle(STD_OUTPUT_HANDLE);     // pega a saída padrão
    CONSOLE_SCREEN_BUFFER_INFO SBInfo;         // informações sobre a buffer da tela
    GetConsoleScreenBufferInfo(hOut, &SBInfo); // pega a posição do cursor do console
    px = SBInfo.dwCursorPosition.X;            // pX será a posição da coluna do cursor no console
    py = SBInfo.dwCursorPosition.Y;            // pY será a posição da linha do cursor no console
    int y1=py+1,x1=20,y2=y1,x2=x1,j,a,b;       // y1=linha inicial  y2 para recuperar a linha inicial
    gotoxy_2(0,y1+30);
    gotoxy_2(0,y1-10);
    for(i=0;i<8;i++){                          // sao 8 letras
        for(j=0;j<5;j++){                      // o caractere é de 5 linhas                         /
            x1 = x2;
            a=letras[i][j];                    // pega o numero da 1 linha do caractere
            for(b=0;b<5;b++){                  // aqui eh um numero de apenas 8 bits
                gotoxy_2(x1,y1);
                if(a % 2 != 0){                // se bit 0 igual 1
                    printf("%c",219);          // coloca espaço invertido senão coloca espaço normal
                }
                else{
                    printf(" ");               // senão coloca espaço normal
                }
                a=a/2;                         // dividindo numero por 2 desloca os bits para direita
                x1--;
                Sleep(10);
            }
            y1++;                              // muda para proxima linha
            x1=x2;                             // volta para a coluna inicial
        }                                      // proxima linha
        x2=x2+6;                               // avança 6 colunas posicionando para o prox caract
        y1=y2;                                 // volta para linha inicial
    }                                          // escreveu o primeiro caractere
}
void gotoxy_2(int coluna, int linha)           // escrever na linha e coluna desejada
{
    COORD c;
    c.X = coluna;
    c.Y = linha;
    SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE), c);
}

 

  • Curtir 1
  • Amei 1
Postado
Citação

Criar espaço na memória para CHAR, com propriedades de VETOR em LISTA estática

 

Não deu pra entender o que seria isso.

 

Criar espaço na memória para char: apenas declare
 

    char letra;

 

char não tem propriedades. vetor é algo declarado como 
 

    tipo 	vetor[21];

 

vetor em lista estática? Essa eu não sei. Uma lista não é um vetor. Pode ser implementada em um vetor usando os índices do vetor para montar a lista. Se for assim e o vetor for estático então pode ter um vetor estático implementando uma lista.

 

De volta ao programa

 

Como apontado por outros, seu programa tem muitos erros ainda.

 

Muitos problemas provavelmente se devem à maneira como isso é explicado (ou não explicado) em cursos e livros.

 

typedef struct tlista {
    int ra[5];
    char arquivo[20];
    char extensao[20];
    int matricula[5];
    int ini;
    int fim;
}tlista;

 

Essa estrutura não representa bem uma lista. Pode insistir nisso, mas vai ter muito trabalho e pouco resultado.

 

Uma lista tem nós, cada nó tem um registro ou uma referência a um registro. Cada registro geralmente tem uma chave, um campo usado para comparação, porque a lista não é sempre uma simples fila de estruturas.
 

#define tam 5

typedef struct tlista {
    int ra[5];
    char arquivo[20];
    char extensao[20];
    int matricula[5];
    int ini;
    int fim;
}tlista;

tlista lista;
int op;
void menu();
void show_info();
void add_info();
void del_info();
void clear();

 

Esse trecho acima mostra alguns dos problemas maiores.

 

Essa estrutura não tem nenhum ponteiro, Não há razão para não ser anônima.

 

lista é global, uma ideia muito ruim e proibida em toda parte, escolas e empresas.

 

op parece ser a opção escolhida no menu :( e fica a pergunta: porque menu() não retorna a opção?

 

as funções retornam void e não tem um único argumento. Isso torna todas elas praticamente inúteis, bem como todo o código que envolva suas listas: vão servir para apenas uma lista, global, a tal lista. Nunca escreva assim. Use argumentos, parâmetros.

 

Nunca use system(). Não vai fazer nada, não vai aprender nada. Está programando em 😄 tem alcance a todas as funções do sistema. Aprenda as funções de que precisa. 

 

TESTE o retorno de scanf(). SEMPRE. É bem ingênuo não testar.

 

MOSTRE os valores que leu para se assegurar de que está tudo certo, em especial enquanto está aprendendo.

 

Não precisa de coisas como 5 printf() de uma linha para escrever 5 linhas...

 

Sugiro corrigir um mínimo dessas coisas e postar o novo código.

 

 

NUNCA escreva um programa interativo antes de testar as funções. Só vai perder tempo. MUITO tempo. 

 

 

        menu();
        scanf("%d", &op);

 

Um exemplo...

 

op é global. Por si só um problema. Mas

 

	op = menu();

 

menu deve retornar a opção, o simples. E poderia receber a lista de opções como parâmetro. Esse é o propósito de escrever funções e programas: poder reutilizar.

 

E menu()?
 

void menu() {
    printf("Selecione uma alternativa:\n\n");
    printf("[1] Adicionar Novo.\n");
    printf("[2] Remover Existente.\n");
    printf("[3] Limpar tudo.\n");
    printf("[0] Sair.\n\n");
}

 

Não seria melhor o simples? Sem entrar na questão da função em si, mas

 

    printf("\
Selecione uma alternativa:\n\n\
[1] Adicionar Novo.\n\
[2] Remover Existente.\n\
[3] Limpar tudo.\n\
[0] Sair.\n\n\
");

 

esse printf() vai gerar a mesma saída. Só que é muito mais fácil de ler e alterar, e muito mais rápido para executar...

  • Curtir 1
  • Amei 1
Postado

@Lucca Rodrigues Obrigado pela resposta, mas o no meu compilador não deu esses erros que no seu deu, ele foi normalmente, mas sabia que tinha algo errado e por isso fiquei confuso. Acho que ficou confuso a minha explicação a respeito do funcionamento do programa. Considero como LISTA uma estrutura de FILA, eu mencionei o nome errado, estava com a cabeça lá em lista encadeada, mas quero na verdade uma fila simples, uma struct com um vetor para armazenar os dados e dois inteiros para definir o inicio e o fim da fila.

 

@arfneto Agradeço demais a ajuda, ainda sou um mero estudante cheio de dúvidas, que muita das vezes não são sanadas por professores ou a forma que ensinam é muito confusa e complexa. Vou tomar todas as suas considerações e dos outros rapazes também, e corrigir o meu código. Agradeço imensamente a todos.

  • Curtir 1
Postado

@marcoosvlopes

2 minutos atrás, marcoosvlopes disse:

mas o no meu compilador não deu esses erros que no seu deu, ele foi normalmente.

Isso é um grande problema :D

 

10 minutos atrás, marcoosvlopes disse:

Considero como LISTA uma estrutura de FILA

A base de uma fila pode ser uma lista, contudo, nem sempre são a mesma coisa.

 

15 minutos atrás, marcoosvlopes disse:

Ele é para mostrar os valores logo de inicio vazios sim.

Mas como vai mostrar um valor que não se sabe qual é? Você não inicializou as variáveis.

 

Dê uma lida na resposta dos outros colegas, tente refazer seu programa.

  • Curtir 1
  • Solução
Postado
6 horas atrás, marcoosvlopes disse:

um mero estudante cheio de dúvidas, que muita das vezes não são sanadas por professores ou a forma que ensinam é muito confusa e complexa

 

Poste suas dúvidas, aqui por exemplo. Um tópico = uma dúvida. Pode ter sucesso, ou pode achar aqui pessoas mais confusas e complexas ;) não sei. Não sei se sua escola é paga, mas o forum é grátis :) 

 

:) Imagino que não tenha achado confuso e complicado o que eu te expliquei, já que nada perguntou. Vou te mostrar algo ainda sobre a diferença entre a maneira que usou e uma maneira de escrever sua estrutura em torno dos seus dados.

 

6 horas atrás, marcoosvlopes disse:

Considero como LISTA uma estrutura de FILA, eu mencionei o nome errado, estava com a cabeça lá em lista encadeada, mas quero na verdade uma fila simples, uma struct com um vetor para armazenar os dados e dois inteiros para definir o inicio e o fim da fila

 

A fila pode ser implementada usando uma lista. A lista pode ser representada usando um vetor e parece ser o que está tentando fazer. E a lista é "encadeada" --- linked --- através dos índices de um vetor. É uma maneira comum de implementar, porque a performance é muito boa.

 

Se quer usar mesmo uma seção linear do vetor para a fila, uma coisa assim serviria, e pode até compilar já:

 

#define TAM 5
#include <stdio.h>

typedef struct
{
    char    arquivo[20];
    char    extensao[20];
    int     matricula[5];
    int     ra[5];

}   Info;


typedef struct
{
    Info        info[TAM];
    unsigned    size;

    unsigned    ini;
    unsigned    fim;

}   Fila;

int         add_info(Info* dado, Fila* fila);
int         del_info(Info* dado, Fila* fila, char campo);
int         show_info(Info* dado);

int         cria_fila(Fila* fila);
int         apaga_fila(Fila* fila);
int         mostra_fila(Fila* fila);


int main(void)
{
    return(0);
}


// insere dado na fila
int         add_info(Info* dado, Fila* fila) { return 0; };
// apaga dado da fila conforme o valor de opt
int         del_info(Info* dado, Fila* Fila, char opt){ return 0; };
// mostra um registro na tela
int         show_info(Info* dado) { return 0; };

// zera uma fila existente
int         apaga_fila(Fila* fila) { return 0; };
// prepara uma fila vazia
int         cria_fila(Fila* fila) { return 0; };
// mostra todos registros da fila
int         mostra_fila(Fila* fila) { return 0; };

// funcoes aux.
void        clear() {};
// mostra o menu, retorna a opcao
int         menu() { return 0; };

 

Entenda que em geral não se alocaria um vetor de estruturas mas provavelmente um vetor de ponteiros para Info.

 

Se escrever assim pode ter filas de qualquer coisa, pode ter várias filas no mesmo programa, e tudo fica mais fácil de testar e manter.

 

 

 

  • Curtir 2
  • Obrigado 1
Postado

@arfneto  Sua explicação foi clara e objetiva! Fico feliz de ver pessoas experientes como você se disponibilizarem para ajudar iniciantes como eu com tanta calma e paciência! Agradeço imensamente sua ajuda, aprendi demais com este tópico, e após essa experiência incrível aqui no fórum eu planejo continuar postando minhas dúvidas e tentar colaborar com a comunidade. Mais uma vez, obrigado!😄

  • Curtir 2

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...