Help in solving the program

Asked

Viewed 78 times

0

Goodnight,

I would like to put between program to be given in C, but I think this is reading a file in txt and I just wanted to save and then could search selected that option.

Someone can help ?

It’s urgent who can help.`

// Programa para guardar filmes.
// Menu iniciar que pergunta ao utilizador se deseja ler ou gravar


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

//definir nome do arquivo

#define arquivo  "c:\\Filmes\\filmes.txt"

// funções utilizadas

int    menu           ();
void   ler            (FILE*);
int    gravar         (FILE*);
int    escrever_dados (FILE*);

int main(void)
{
//reservar espaço na memoria;
FILE *file = (FILE*)malloc(sizeof(file));

int select = 0;

while (select==0)
{
    //Escolha das funções do menu;
    //Aqui a função menu retorna o dado selecionado e executa a respectiva função;
    //Vai executar enquanto o menu não retornar o valor 3;
    switch(select = menu())
    {
    case 1:
        ler(file);
        break;

    case 2:
        gravar(file);
        break;

    case 3:
           return 0;
    default:
        break;

    }
}
return 0;
}
int menu()
{
printf("\n Digite uma das opcoes:\n   ler, gravar ou fim:");

char palavra [50];

//Espera pela palavra inserida pelo teclado e guarda a mesma na variavel "palavra"
scanf("%s",palavra);
//limpa o buffer do teclado;
fflush (stdin);
//converter todas as letras da variavel para maiusculas;
strupr(palavra);

//Ira aparecer entao a palavra digitada;
//Caso não seja a que se pretende ira retornar '0';
//Ira voltar ao menu para que o utilizador volte a inserir nova opção;
if        (!strcmp(palavra, "LER")     ==1)  return 1;
else if   (!strcmp(palavra, "GRAVAR")  ==1)  return 2;
else if   (!strcmp(palavra, "FIM")     ==1)  return 3;
else                                         return 0;

}

void ler (FILE*file)
{
  system    ("cls");
  printf    ("\n\n");

  file     = fopen (arquivo,"r");

  // Se o arquivo não abrir ira retornar 0, entao o negado(!) e para inverter e entrar na condição para mostrar a mensagem de erro.
  if (!file)
  {
   printf("\n\n Arquivo não encontrado!\n\n");
  }
  else
  {
   char c;

   //Verifica se o primeiro arquivo e igual a EOF(-1), o que indica o final do arquivo;
   if((c = getc (file))==EOF)
   {
       printf("Arquivo esta vazio!");
   }

   //Faz a leitura do arquivo carater a carater e mostra no ecra ate ao fim;
   while((c = getc(file))!= EOF)
   {
       printf("%c",c);
   }
  }
  //pausa
  getchar();
}

int gravar (FILE *file)
{
// "a": insere no fim; se não existir arquivo ele criara com "w";
if( (file = fopen(arquivo, "a") )||(file = fopen(arquivo,"w")))

{
    while(escrever_dados(file)){}
    return 0;
}
}

int escrever_dados(FILE *file)
{
char       codigo[20];
char       filme [20];
char       genero[20];
char       sair  [20];

printf     ("\n\nCodigo:");
//limpa buffer do teclado;
fflush      (stdin);
//captura a string;
gets        (codigo);
//copia a string para a variavel sair;
strcpy      (sair, codigo);
//comparar valor da string com a palavra FIM, caso seja = sai e retorna o valor '0';
// caso sejam diferentes então continua;
if(!strcmp(strupr(sair),"FIM")) return 0;

printf    ("Filme:");
fflush    (stdin);
gets      (filme);
strcpy    (sair, filme);

if(!strcmp(strupr(sair),"FIM")) return 0;

printf    ("Genero:");
fflush    (stdin);
gets      (genero);
strcpy    (sair, genero);

if(!strcmp(strupr(sair),"FIM")) return 0;

fprintf    (file,"\nCodigo:%s",codigo);
fprintf    (file,"    Filme:%s",filme);
fprintf    (file,"        Genero:%s",genero);

return 1;


}`
  • 1

    I think there are many problems in your code. I start with: what is the meaning you want with FILE *file = (FILE*)malloc(sizeof(file));?

2 answers

2

Good evening, your code there are some errors, so the text will be a little long...

Prototypes of the functions

Start with the prototypes of its functions:

int    menu           ();
void   ler            (FILE*);
int    gravar         (FILE*);
int    escrever_dados (FILE*);

Remove the spaces between the parentheses and their name, also decrease the space between the type of return with the name, so it is more organized:

int menu(void);
void ler(FILE*);
int gravar(FILE*);
int escrever_dados(FILE*);

Another problem is their arguments, note that you forgot to put the variable, you just put the type. The prototype needs to look like this:

int menu(void);
void ler(FILE *file);
int gravar(FILE *file);
int escrever_dados(FILE *file);

Now prototypes can use a pointer to files, before they could not because they were not declared.

Pointer declaration for this

In this part of the code you don’t need to use malloc:

FILE *file = (FILE*)malloc(sizeof(file));

When you do FILE *file; the file pointer is already created. Create a pointer to the file using the malloc() would only be useful if the pointer was encapsulated in another file, but as this is not the case then just do it:

FILE *file = NULL;

Leave the pointer equal to NULL is not required, but this may prevent you from using pointers pointing to unknown places in memory... So recommend you always match the NULL pointers not currently used.

Select variable

The variable select is kind of useless in your code, because the return of the function menu() can be used without problem on the switch:

switch(select = menu()) // Isso dá no mesmo
switch(menu()) // que isso

fopen()

It’s not necessarily a mistake, but the fopen() returns NULL when it fails, but it’s probably the same thing in C, I’m not sure... But I think your code will look more elegant with:

if(file != NULL)
/* Você ainda pode otimizar espaço ao fazer isso */
if((file = fopen(arquivo,"r")) == NULL) return /* numero com erro */; /* E aqui pode encerrar a função/programa em caso de erro, pode usar um return para sair da função com erro */

/* Aqui será ativado em caso de sucesso */

Forgetting to close the file

At the end of the function ler() you forget the fclose(nome_do_arquivo) to close the file. Remember that in C the data does not go directly to the disk file but to the stream, the fclose is to warn the program that all changes in that file have already ended and it can close and download the data there, if you do not do so then there are chances of losing the data... You also forget the fclose in function gravar()... Example of what the fclose() in your code:

fclose(file);

fflush(stdin)

A very common mistake is the use of fflush(stdin), Maybe this command is so popular because many of the Federal teachers recommend it, I don’t know why, but it happens a lot and I speak from experience... In short: fflush() have the undefined behavior when the argument is stdin, I mean, it might work, it might not work, or there could be other things... Even if it works on your PC I recommend not to use, this command is very poorly seen among programmers.

One solution to solve this problem that some recommend is the setbuf(stdin, NULL), but that command doesn’t work on every computer. I won’t go into too much detail, as questions about how to clean the buffer have already been discussed a lot. The solution I give you is this::

void limpar_buffer(void)
{
    char lixo;
    do
    {
        lixo = getchar();
    }while(lixo != '\n');
}

I wrote it in a very didactic way for you to understand, but it is possible to compress this function. Use it whenever you’re sure there’s trash in the buffer.

Keyboard reading with gets or scanf("%s")

These functions do not serve to read strings from the keyboard, as they do not necessarily have a character limit to be read, that is, if the user writes something with 50 characters and the string is only 20 in size then 30 characters will be read and put somewhere in memory (probably in the following positions of its vector, that is, v[21], v[22], ..., v[30], consider that from v[21] they are not parts of its vector). This problem is called overflow, check it out later.

To solve the problem most recommend using the fgets(variavel_que_ficara_a_string, tamanho_da_string, stdin). Example of use:

char nome[20];
fgets(nome, 20, stdin);

This way you set a limit of 20 characters to be read

fgets problems with the clean buffer function that I recommended

I especially do not recommend using the fgets, for some reasons, the main thing that really comes to the case is that it has a problem with the buffer.

Well, when the fgets read less characters or the expected amount so it does not leave garbage in the buffer and this is great, but if the user type a larger amount then the characters that do not enter the array/string will be as memory junk. Test the code below to see:

char nome[5], n[5];
fgets(nome, 5, stdin);
fgets(n, 5, stdin);
printf("%s \n", nome);
printf("%s \n", n);

In the code above type names with less than 5 characters and note the output, then type a name with 6 or more characters and notice that the trash that will be assigned to the second fgets.

The first solution to solve this is to use the function of limpar_buffer() that I recommended, but with that we have a problem. The problem is that the lmipar_buffer() function will open the keyboard input if the buffer is clean and this would cause a "pause" in the program, and that’s not what we want. Because it is not possible to predict whether fgets will leave garbage in the buffer then we cannot use the limar_buffer together with fgets.

One solution is to create the function itself to read a string:

void ler_string(char *nome, int tamanho)
{
    char letra, i = 0;
    do
    {
        letra = getchar();
        if(letra != '\n' && i < tamanho - 1)
        {
            nome[i] = letra;
            i++;
        }
    }while(letra != '\n');
    nome[i] = '\0';
}

The above function can be compacted, but I wrote so as to make it easier to understand it. This function will never leave junk in the buffer independent of what the user type.

Problem using getchar to pause program

Many use the getchar() as an alternative to the system("pause"), is a great alternative if you want to pause to avoid closing the window when the program ends, but if used in the middle of the program the getchar() can leave a trash in the buffer and bring an unexpected behavior. Example:

printf("Pressione enter para continuar... \n");
getchar();
printf("Digite um caractere: ");
scanf("%c", &n);

In the above program if the user type enter then fine, but if you type something like aofhdskajfe hit enter then the a will be "deleted" and the rest will look like garbage in the buffer, that is, the scanf would read the "o" and that is not what we want. out that the trash can be read in a string without us waiting. A simple solution to this is to use the function limpar_buffer() to pause the screen, it always pauses the screen when there is no garbage in the buffer (so it does not get along with fgets as I mentioned). The code above would look like this:

printf("Pressione enter para continuar... \n");
limpar_buffer();
printf("Digite um caractere: ");
scanf("%c", &n);

These are the main problems I found in your code, there may be more, I don’t know. Make the changes and see. I didn’t test with the changes I mentioned because I spent a lot of time analyzing your code and writing this answer and so I’m a little tired. But I hope I have helped in something. In case there is still some problem then let me know.

  • 1

    One observation: in the prototypes of the functions it is not necessary to put the variable, only the type is enough.

  • I didn’t know that kkk, thanks for the remark!

-1

inserir a descrição da imagem aquiAfter the changes when opening to try to save and when choosing to save this returns to "start" I cannot save anything. Hit the code to record and then see what I recorded.

  • it would be interesting to consider and use the form of editing your post, because it is not interesting to put answer on answer.. See more: https://answall.com/help/how-to-ask

  • You can send the code after the changes?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.