Ir ao conteúdo
  • Cadastre-se

Variável global ou local? como alterar seu valor no decorrer da execução?


Posts recomendados

Galera, estou desenvolvendo um programa de vendas e encontrei o seguinte problema. Toda vez que realizo uma venda um arquivo txt é criado e uma variável vai incrementando o valor (Ex, pedido1.txt, pedido2.txt...). Comecei declarando essa variável local, dentro da função venda dados, só que toda vez que eu saia da função e precisava retornar pra criara uma nova venda, essa variável voltava ao seu valor inicial e eu não conseguia gerar o txt, porque outro já tinha sido criado com o mesmo nome. Passei ela pra global, pra tentar corrigir, mas não funcionou também. Alguém tem alguma ideia de como resolver?

 

Segue o código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <conio.h>
#include <locale.h>
#include <windows.h>

#define BUFFER 64

#define acima 72 // Comandos do teclado pela tabela asc
#define abaixo 80
#define esc 27
#define enter 13

FILE *arquivo; // ponteiro para apontar o txt das vendas.
int volta = 0, conta = 0, ped = 1; // Variável para armazenar a lista de pedidos.  É DECLARADA DE FORMA GLOBAL porque SE DECLARAR DENTRO DA FUNÇÃO, SEMPRE QUE VOLTARMOS PELO WHILE, ELA VAI VOLTAR A SER 1.

// Estrutura da lista declarada para armazenar dados.
typedef struct lista {
        char *nome;
        float preco;
        int cod;
        float valor;
        struct lista *proximo;
} Dados;

//Prototipo das funcoes de manuseio dos dados. 
Dados *inicia_dados(char *nome, float preco, int cod);
Dados *insere_dados(Dados *dados, char *nome, float preco, int cod);
void exibe_dados(Dados *dados);
void busca_dados(Dados *dados, int chave);
Dados *deleta_dados(Dados *dados);
int checa_vazio(Dados *dados);
void venda_dados(Dados *dados, FILE *arquivo, int volta, int conta, int ped);

// Prototipo das funcoes do menu.
void insere(void);
void exibe(void);
void busca(void);
void deleta(void);
void venda(void);

// Inicializa a estrutura de dados principal. 
Dados *principal = NULL;

//**************************************************************  FUNÇÃO INICIA_DADOS (STRUCT) *************************************************************************
// Cria a nova lista apontando o proximo no para NULL.
Dados *inicia_dados(char *nome, float preco, int cod) {

        Dados *novo;

        novo = (Dados *)malloc(sizeof(Dados));

        novo->nome = (char *)malloc(strlen(nome)+1);
        strncpy(novo->nome, nome, strlen(nome)+1);

        novo->preco = preco;
        novo->cod = cod;

        novo->proximo = NULL;

        return novo;
}


//**************************************************************  FUNÇÃO INSERE_DADOS (STRUCT) *************************************************************************
// Como a lista nao esta mais vazia, apontamos o proximo no para lista anterior.
Dados *insere_dados(Dados *dados, char *nome, float preco, int cod) {

        Dados *novo;

        novo = (Dados *)malloc(sizeof(Dados));

        novo->nome = (char *)malloc(strlen(nome)+1);
        strncpy(novo->nome, nome, strlen(nome)+1);

        novo->preco = preco;
        novo->cod = cod;


        novo->proximo = dados;

        return novo;
}


//**************************************************************  FUNÇÃO EXIBE_DADOS *************************************************************************
// Percorre todos os campos da lista e imprime ate o ponteiro proximo chegar em NULL.
void exibe_dados(Dados *dados) {

        fprintf(stdout, "Cadastro:\n\n");

        fprintf(stdout, "------------------------\n");

        for (; dados != NULL; dados = dados->proximo) {
                fprintf(stdout, "Nome do produto: %s\n", dados->nome);
                fprintf(stdout, "Código do produto: %d\n", dados->cod);
                fprintf(stdout, " R$: %4.2f reais \n", dados->preco);
                fprintf(stdout, "------------------------\n ");
        }
        printf("Pressione uma tecla para continuar.");
        getch();
}

//**************************************************************  FUNÇÃO BUSCA_DADOS *************************************************************************
// Percorre a lista comparando o nome com a chave.
void busca_dados(Dados *dados, int chave) {

        int achou = 0;

        fprintf(stdout, "Cadastro:\n\n");
        for (; dados != NULL; dados = dados->proximo) {
                if (dados->cod == chave) {

                        printf("------------------------\n");
                        printf("Nome do produto: %s\n", dados->nome);
                        printf("Código do produto: %d\n", dados->cod);
                        printf("R$ %4.2f reais \n", dados->preco);
                        printf("------------------------\n");
                        achou++;
                }
        }

        if (achou == 0)
                printf("Nenhum resultado encontrado.\nPressione uma tecla para continuar.\n");
        else
                printf("Foram encontrados %d registros. \nPressione uma tecla para continuar.\n", achou);

}

//**************************************************************  FUNÇÃO DELETA_DADOS *************************************************************************
// Deleta o ultimo registro inserido.

Dados *deleta_dados(Dados *dados) {

        Dados *novo;

        novo = dados->proximo;

        free(dados->nome);
        free(dados);

        fprintf(stdout, "O ultimo registro inserido foi deletado com sucesso.\n");
        Sleep(1);

        return novo;
}

//**************************************************************  FUNÇÃO CHECA_VAZIO *************************************************************************
// apenas checa se a struct aponta pra NULL.
int checa_vazio(Dados *dados) {

        if (dados == NULL) {
                fprintf(stdout, "Lista vazia!\n");
                Sleep(1000);
                main();
        } else
                return 0;
}


//**************************************************************  FUNÇÃO VENDA_DADOS *************************************************************************
void venda_dados(Dados *dados, FILE *arquivo, int volta, int conta, int ped) {

	int qnt, chave, produto = 1; // Conta vai marcar o número de pedidos na fila
    float valor =0, preco;
    char cmd[256];
	
        do{
        	int achou = 0; // é declarada aqui, porque se não mesmo que um produto não estivesse cadastrado ele continuaria a venda
        	Dados *b_dados = dados; // Ponteiro para resetar o for. O For, depois de executado para no item escolhido, logo, é como se ignora-se todos os itens antes do escolhido
        	
        	
        		if (!checa_vazio(principal)) { //teste se tá vazio, como na função busca, mas tudo em uma função só
                		fprintf(stdout, "\n Digite o código do produto: \n--> ");
                		scanf("%d", &chave);


        printf("\n Cadastro:\n");
        for ( ; dados != NULL; dados = dados->proximo)
		 {
                 if (dados->cod == chave)
				 {

                        printf(" ------------------------\n");
                        printf(" Nome do produto: %s\n", dados->nome);
                        printf(" Código do produto: %d\n", dados->cod);
                        printf(" R$ %4.2f reais \n", dados->preco);
                        printf(" ------------------------\n");
                        achou++;
                        break;
                }
        }

        if (achou == 0)
                printf("Nenhum resultado encontrado.");
        else{
                printf("\n\n Foram encontrados %d registros. \n\n", achou);
															   conta++;  //adiciona o número do pedido .txt

        printf(" Quantidade: ");
		scanf("%d", &qnt);


						 arquivo = fopen("pedido.txt","a"); //criando arquivo .txt
                         
                        				 if(arquivo == NULL)
                                	     printf("Erro ao se comunicar com o servidor da cozinha!"); // não conseguiu salvar o .TXT

                         				 else {
    			 						        fprintf(arquivo," Pedido número: %d", conta);
    			 						        fprintf(arquivo,"\n\n-------------------------\n");
   			    						        fprintf(arquivo," NOME: %s \n", dados->nome);  // Vai escrever isso no .txt
   			    						        fprintf(arquivo," QUANTIDADE: %d\n", qnt);
   			    						        fprintf(arquivo,"-------------------------\n");
   		              	                      }
   		              	  fclose(arquivo);
   		              	 		sprintf(cmd,"rename pedido.txt pedido%d.txt", ped);//muda o nome do pedido, assim, a cada nova venda é criado um novo .txt
						 		system(cmd);
						 				
						  
       
		valor = valor + (dados->preco * qnt); // variável acumulativa
        printf("\n Valor total R$: %4.2f", valor);
        }
        
        dados = b_dados;// Reseta o for  
        
        printf("\n\n Digite 1 para adicionar outro produto a venda, ou 0 para sair ");
        scanf("%d", &volta);
        
        	if (volta == 1) 
        	{
        		ped++;// incrementa o valor do pedido, para mudar os txt subsequentes. ENTRA AQUI, porque SE FOR ADICIONAR MAIS UM PRODUTO, NÃO CRIAR UM NOVO TXT DE PEDIDO
        		produto++;// volta a 1 sempre, toda vez que sai da função
				printf("\n\n****************  PRODUTO 0%d  ****************\n", produto);
        	}
        	else if(volta == 0)
        		 main(); //volta pra main
        		
        
        		
          }// chave do if lá em cima
        }while(volta == 1);
        
       
}



//**************************************************************  FUNÇÃO INSERE  *************************************************************************

/* Obtem os dados necessarios para chamar as funcoes de manuseio de dados. */
void insere(void) {

        char *nome;
        int cod;
        float preco;


        nome = (char *)malloc(BUFFER);
       

        printf("\n Digite o nome do produto: ");
        scanf("%s", nome); 

        printf("\n Digite o código do produto: ");
        scanf("%d", &cod);

        printf("\n Digite o preço: ");
        scanf("%f", &preco);

        printf("\n\n PRODUTO CADASTRADO!");

        if (principal == NULL)
                principal = inicia_dados(nome, preco, cod);
        else
                principal = insere_dados(principal, nome, preco, cod);
}

//**************************************************************  FUNÇÃO EXIBE  *************************************************************************
void exibe(void) {

        if (!checa_vazio(principal))
                exibe_dados(principal);

}

//**************************************************************  FUNÇÃO BUSCA  *************************************************************************
void busca(void) {

        int chave;

        if (!checa_vazio(principal)) {

                printf("Digite o código do produto: \n--> ");
                scanf("%d", &chave);

                busca_dados(principal, chave);
                getch();
        }
}
//**************************************************************  FUNÇÃO DELETA  *************************************************************************
void deleta(void) {

        if (!checa_vazio(principal))
                principal = deleta_dados(principal);
}

//**************************************************************  FUNÇÃO VENDA  *************************************************************************

void venda(void){
              //  venda_dados(principal, arquivo);
              venda_dados(principal, arquivo, volta, conta, ped);
            }


//************************************************************* FUNÇÕES DA SETA **************************************************************************
inicio01()
{
   system("cls");
   printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("   --> Nova venda                 \n");
   printf("       Cadastrar produto          \n");
   printf("       Exibir produtos            \n");
   printf("       Buscar produto             \n");
   printf("       Deletar Dados              \n");
   printf("       Sair                       \n");
   printf("   -------------------------------");

int ch;
ch=getch();

	if (ch==enter)
		{
	 	system("cls");
	 	printf("\t NOVA VENDA\n\n");
     	venda();//Chama a função
     	sleep(1000);
    	}

	if (ch==224)
   		ch=getch();
   		
   			if (ch==acima)
      		inicio06();
      		
  			else if (ch==abaixo)
      		inicio02();
      		
   			else
      		inicio01();
}

//************************************************************** INÍCIO 02 ***********************************************************************
inicio02()
{
   system("cls");
   printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("       Nova venda                 \n");
   printf("   --> Cadastrar produto          \n");
   printf("       Exibir produtos            \n");
   printf("       Buscar produto             \n");
   printf("       Deletar Dados              \n");
   printf("       Sair                       \n");
   printf("   -------------------------------");
int ch;
ch=getch();

	if (ch==enter)
		{
		system("cls");
		printf("\t CADASTRO DE PRODUTOS\n\n");
     	insere();
   	    Sleep(1000);
 	    }
   
	else if (ch==224)
   		ch=getch();
   if (ch==acima)
      inicio01();
   else if (ch==abaixo)
      inicio03();
   else
      inicio02();
}


//************************************************************** INÍCIO 03 ***********************************************************************
inicio03()
{
   system("cls");
    printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("       Nova venda                 \n");
   printf("       Cadastrar produto          \n");
   printf("   --> Exibir produtos            \n");
   printf("       Buscar produto             \n");
   printf("       Deletar Dados              \n");
   printf("       Sair                       \n");
   printf("   -------------------------------");
  
int ch;
ch=getch();

if (ch==enter)
    {
      system("cls");	
      printf("\t EXIBIR PRODUTOS\n\n");
      exibe();
      Sleep(1000);
	}

else if (ch==224)
   ch=getch();
   if (ch==acima)
      inicio02();
   else if (ch==abaixo)
      inicio04();
   else
      inicio03();
}

//************************************************************** INÍCIO 04 ***********************************************************************
inicio04()
{
   system("cls");
   printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("       Nova venda                 \n");
   printf("       Cadastrar produto          \n");
   printf("       Exibir produtos            \n");
   printf("   --> Buscar produto             \n");
   printf("       Deletar Dados              \n");
   printf("       Sair                       \n");
   printf("   -------------------------------");
  
int ch;
ch=getch();

if (ch==enter)
    {
      system("cls");
      printf("\t BUSCA DE PRODUTOS\n\n");
      busca();
      Sleep(1000);
	}

else if (ch==224)
   ch=getch();
   if (ch==acima)
      inicio03();
   else if (ch==abaixo)
      inicio05();
   else
      inicio04();
}

//************************************************************** INÍCIO 05 ***********************************************************************
inicio05()
{
   system("cls");
   printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("       Nova venda                 \n");
   printf("       Cadastrar produto          \n");
   printf("       Exibir produtos            \n");
   printf("       Buscar produto             \n");
   printf("   --> Deletar Dados              \n");
   printf("       Sair                       \n");
   printf("   -------------------------------");
  
int ch;
ch=getch();

if (ch==enter)
    {
     system("cls");
     printf("\t DELETAR DADOS\n\n");
     deleta();
     Sleep(1000); 
	}

else if (ch==224)
   ch=getch();
   if (ch==acima)
      inicio04();
   else if (ch==abaixo)
      inicio06();
   else
      inicio05();
}

//************************************************************** INÍCIO 06 ***********************************************************************
inicio06()
{
   system("cls");
    printf("\n   ------ Menu Principal --------\n");
   printf("                                 \n");
   printf("       Nova venda                 \n");
   printf("       Cadastrar produto          \n");
   printf("       Exibir produtos            \n");
   printf("       Buscar produto             \n");
   printf("       Deletar Dados              \n");
   printf("   --> Sair                       \n");
   printf("   -------------------------------");
  
int ch;
ch=getch();

if (ch==enter)
    {
     exit(0);
	}

else if (ch==224)
   ch=getch();
   if (ch==acima)
      inicio05();
   else if (ch==abaixo)
      inicio01();
   else
      inicio06();
}



//**************************************************************  FUNÇÃO MAIN  *************************************************************************


int main() {     
setlocale(LC_ALL, "Portuguese");
system("color 4E");
system("cls");

while(1)
inicio01();

return 0;
}

 

Link para o comentário
Compartilhar em outros sites

Quando invocamos uma função é quando realmente é reservado o espaço para a as variáveis declaradas dentro dessa função, assim com todas, incluindo main. Quando a função chega ao fim é liberado toda a memória que foi reservada, por isso o numero não permanece, porque cada vez que invocas uma função vai ser reservado o espaço e ela tomará o valor residual que estivesse nesse local ou o valor que foi atribuído na hora da declaração.

Vamos ver alguns mecanismos para saltar essas restrições.

Quero comentar antes que para uma variável poder ser utilizada ela deve estar declarada previamente, ou seja, ela deve ser visível para a operação que desejar realizar. Não será possível mudar valor de X se X não foi declarado, já seja de forma global como local, certamente essa regra você já sabe, mas só para confirmar deixo constância. Outra coisa a ter em conta e vai dado de mão com o que falei anteriormente, algumas variáveis não resistem a escopos, ou seja se crio uma função com uma variável Y dentro do corpo da função(entre { e }) quando a função termina a variável morre junto com o escopo, pois essa memória foi liberada quando o código chegou ao fim da função. Vou por também alguns exemplos de como sobreviver a escopos e conservar o valor das variáveis.

Vamos ver globais:

#include <stdio.h>

int n = 10;

int main ( void ) {
    
    int n = 20; // nesse ponto tenho 2 globais, e é perfeitamente valido
    
    //Se fizer um print:
    printf("%d\n\n", n); //Sai 20 por quê? Porque printf da preferência a variaveis locais
    
    //Se eu quiser me referir a global devo fazer uma manobra pouco ortodoxa tal que:
    { //Criar um escopo interno 
        extern int n; // Indicar que me estou referindo a n externa 
        printf("%d\n", n); //agora imprimirá 10 (n Global)
    }
    
    //Em c++ bastaria por :: adiante de n quando eu quiser me referir a n global ficando:: 
    //cout << ::n;
    
    return 0;
}

Com o comando extern nos referimos que a variável é externa, que está fora do escopo, ou incluindo ela pode estar em outro arquivo. Se ver uma variável com um extern quer dizer que a autentica está em outra parte, normalmente é uma global que está em algum arquivo, provavelmente main.c. Por exemplo... se crio uma int n=0 de forma global em main, e quero usar esse n em outro arquivo, devo declarar int n em cada arquivo que for utilizar porém com a palavra extern int n; e não devo por valor algum pois o valor é o que está em main. Se eu incrementar uma variável externa estarei incrementando uma só. Se tiver duvidas pergunte, ou busque algum vídeo sobre variáveis extern.
E como vimos, também podemos usar extern para nos referir a uma variável fora de main, é um pouco "gambiarra" mas perfeitamente possível. >_<

Variaveis estaticas...
Talvez a que lhe interesse mais.

#include <stdio.h>

void foo(){
    static int n = 0; //n é estatica e vai parar junto com as globais
    printf("%d\n", ++n);
}

int main ( void ) {
    foo();//1
    foo();//2
    foo();//3
    
    return 0;
}

Uma variável declarada dentro de uma função de forma estática quer dizer que essa variável seja criada logo ao iniciar main, e que ela não está exatamente dentro da função(na pilha), se não que está na parte das variáveis globais, mesmo que a função terminar ela continua na memória, somente será liberada quando sair de main.

Outra forma é passo por referencia e não por valor. Se temos n dentro de main e queremos passar n para outra função, e que ao alterar n o resultado seja refletido dentro da n de main devemos passar por referencia e não por valor. Passo por valor é igual a criar uma copia da variável dentro da outra função(você terá 2 n), e passo por referencia é igual a passar a autentica variável para outra função(passamos a direção da autentica variável n que está dentro de main).

E por ultimo vamos falar de uma variável que realmente resiste a todos os escopos desde seu momento de criação... memória dinâmica. Tão útil como perigosa ela resiste até mesmo ao fim do programa, continuará lá na memória até o computador apagar, se nós antes não a indicamos que libere espaço de forma explicita. Busque malloc/free, "memória dinâmica em C".

Acho que ja lhe dei todas as pautas para resolver seu problema. Se precisar de algo mais contundente, então melhor usar arquivos para guardar sua variável. Busque sobre arquivos INI, ou inclusive sobre como usar o registro de windows para guardar valores.

Realmente existe tantas técnicas como necessidades tiver. >_< Sorte!




 

 

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

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...