Ir ao conteúdo

Posts recomendados

Postado

 /* É que eu não estou conseguindo resolver esse Programa :(  

1. Escreva uma função, que insira dados de N funcionários da Universidade Cabo Verde e envia-los para ficheiro como o nome 
funcionarios.txt (o programa deverá informar quantos funcionários deseja inserir no sistema?);

2. Escreva uma função, que imprima registos de todos os funcionários que se encontra no ficheiro com o nome funcionarios.txt, inserido 
anteriormente?

3. Escreva uma função, que imprima os funcionários por categoria.

4. Escreva uma função, que permite calcular quanto gasta a universidade com os funcionários por categoria?

5. Temos três tipos de categorias dos funcionários [Docente, Diretor e Técnico], sabendo que o funcionário que é Docente recebe 2500$ 
por cada hora, um Diretor recebe 3500$ por hora, e um Técnico recebe 1500$ por hora. Escreva uma função, que mostra o salário de 
um determinado funcionário dependendo do seu salário liquido por hora, sabendo que INPS é de 12%, IUR é de 20% e sindicato é de 
1%; 

6. Escreva uma função, que ordena os funcionários na ordem crescentes e envia-los para o ficheiro com o nome 
ordenar_funcionarios.txt;

7. Escreva uma função, que imprima todos os funcionários com salario maior que 75000$.

8. Escreva uma função, que dado nº de NIF permite eliminar todas as informações desse funcionário.  

*/


//bibliotecas
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <conio.h>
#include <time.h>


//Dados do funcionário
struct Funcionario {
    char nome[20];
    int NIF[20];
    char categoria[20];
    float salario;
    int Hora_Trabalhados;
};

// Para não atrapalhar o bom funcionamento
void pressioneEnter() {
    char c;
    do {
        c = getch();
    } while (c != 13);
}



void IncerirFuncionario(struct Funcionario funcionario[],int n) {
    system("COLOR 0F");
    int i;
    FILE *file; // cria variável ponteiro para o arquivo
    file= fopen("funcionarios.txt", "w"); //abrindo o arquivo
    if(file == NULL) //testando se o arquivo foi realmente criado
        printf("\n-->Nao foi possivel abrir o fecheiro\n\n");
    else {
        printf ("\n\n\n\n\tUNICV \n\n");
        printf("\n\n\n\t\tDigite o numero de Funcionarios que pretende registrar: ");
        scanf("%i",&n);
        fflush(stdin);
        system("cls");
        static int i=0;
        int y=n+i;
        if(y>99)
            menu(funcionario,n);
        printf("\n\n\n\t\t-------- INSCRIÇÃO DE FUNCIONÁRIO --------\n\n");
        fprintf(file,"\n\n\t----- LISTA DOS FUNCIONÁRIOS ----\n\n");
        fprintf(file,"\tNome      NIF 	  Salário     Categoria  Horas\n\n");
        for(; i<y; i++) {
            system("COLOR 0B");
            // para obter dados e armazenar no arquivo
            printf("\n\tDigite o nome do funcionário: ");
            scanf(" %s",&funcionario[i].nome);
            printf("\n\tDigite o NIF do funcionário: ");
            scanf("%d",&funcionario[i].NIF);
            printf("\n\tDigite o salario do funcionario: ");
            scanf("%f", &funcionario[i].salario);
            printf("\n\tDigite a categoria do funcionário: ");
            scanf(" %s", &funcionario[i].categoria);
            printf("\n\tDigite a Hora trabalhados pelo funcionário: ");
            scanf("%d", &funcionario[i].Hora_Trabalhados);
            printf("\n\n");
            //A Escrevendo no arquivo
            fprintf(file,"\t%s \t %d \t %.1f \t %s\t %d\n",funcionario[i].nome,funcionario[i].NIF,funcionario[i].salario,funcionario[i].categoria,funcionario[i].Hora_Trabalhados);
        }
        printf("\n\t\t-------------------------<3--------------------------\n");
        printf("\n\t Incritos com sucesso! \n\n\t Registado no fecheiro -> funcionarios.txt\n\n");
        printf ("\n\n\n\t\t\tPressione ENTER para Continuar->");
        fflush(stdin);
        pressioneEnter();
        system("cls");
        menu(funcionario,y);
    }
    fclose(file); // para fechar o arquivo
}

void ImprimirFuncionarios(struct Funcionario funcionario[],int n) {
    FILE *file;

    file = fopen("C:\\Users\\alex\\Desktop\\teste4\\funcionarios.txt", "r");
    if(file == NULL)
        printf("\n-->Nao foi possivel abrir o fecheiro\n\n");

    else {
        int i;
        printf("\n\n\n\t\t------- LISTA DOS FUNCIONÁRIOS ------\n\n");
        for(i=0; i<n; i++) {
            system("COLOR 0F");
            fscanf(file,"%s",funcionario[i].nome);
            fscanf(file,"%d",funcionario[i].NIF);
            fscanf(file,"%.1f $00",funcionario[i].salario);
            fscanf(file,"%s",funcionario[i].categoria);
            fscanf(file,"%d horas",funcionario[i].Hora_Trabalhados);
            printf("\n\tNome: %s",funcionario[i].nome);
            printf("\n\tNIF: %d",funcionario[i].NIF);
            printf("\n\tSalario: %.1f $00", funcionario[i].salario);
            printf("\n\tCategoria: %s",funcionario[i].categoria);
            printf("\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados);
            printf("\n\n----------------------------------------------------------\n");
        }
    }

    printf ("\n\n\n\t\t\tPressione ENTER para Continuar->");
    fflush(stdin);
    pressioneEnter();
    system("cls");
    fclose(file);

}
void OrdenarFuncionario(struct Funcionario *funcionario,int n) {

    int i, j;
    struct Funcionario aux;

    for (i=1; i<n; i++) {
        aux = funcionario[i] ;

        for (j=i; (j>0)&&(aux.salario < funcionario[j-1].salario);j--) {
            funcionario[j]=funcionario[j-1];
            funcionario[j] = aux;
        }

    }
    printf("\n\n\n\t------- LISTA DOS FUNCIONÁRIOS POR ORDEM CRESCENTE ------\n\n");

    for (i=0; i<n; i++) {

        printf("\n\tNome: %s",funcionario[i].nome);
        printf("\n\tNIF: %d",funcionario[i].NIF);
        printf("\n\tSalario: %.1f $00", funcionario[i].salario);
        printf("\n\tCategoria: %s",funcionario[i].categoria);
        printf("\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados);
        printf("\n\n----------------------------------------------------------\n");

    }

    printf ("\n\n\n\t\t\tPressione ENTER para Continuar->");
    fflush(stdin);
    pressioneEnter();
    system("cls");
}


void EliminarFuncionario(struct Funcionario funcionario[],int n) {
    FILE *file;

    //Abre o arquivo novamente para leitura
    file = fopen("funcionarios.txt", "r+");
    if(file == NULL)
        printf("\n-->Nao foi possivel abrir o fecheiro\n\n");

    else {
        int nif, i;
        char resp;
        printf("\n\tInforme o NIF do funcionario a ser Eliminado: ");
        scanf("%d",&nif);

        while( funcionario[i].NIF == nif ) {

            //if ( funcionario[i].ativo== 1 ) {

                printf("\n\tNome: %s",funcionario[i].nome);
                printf("\n\tNIF: %d",funcionario[i].NIF);
                printf("\n\tSalario: %.1f $00", funcionario[i].salario);
                printf("\n\tCategoria: %s",funcionario[i].categoria);
                printf("\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados);
                printf("\n\n----------------------------------------------------------\n");
           // }
            printf("\n\tDeseja realmente eliminar o Funcionário? S/N:");
            scanf("%c",&resp);

            if ( ( resp == 'S' ) || ( resp == 's' ) ) {
             //   funcionario[i].ativo=0;
                printf("\n\tFuncionário eliminado com sucesso\n");
                break;
            } else {
                if ( ( resp == 'N' ) || ( resp == 'n' ) ) {
                    printf("\tEliminação cancelada!\n");
                    break;
                }
            }
        }
        i++;

        if ( i > 99 )
            printf("\n\n\t\tNIF não encontrado\n");
    }
    fclose(file);
    printf ("\n\n\n\t\t\tPressione ENTER para Continuar->");
    fflush(stdin);
    pressioneEnter();
    system("cls");
}

void menu(struct Funcionario funcionario[],int n) {
    int op;
    do {
        system("COLOR 0F");  //Menu
        printf("\n\n\t\t\t\t---> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n\n");
        printf("\n\t\t* 1 ------- INSERIR OS FUNCIONÁRIOS E ENVIA-LOS PARA O FICHEIRO ------------------------ *\n");
        printf("\n\t\t* 2 ------- IMPRIMIR A LISTA DOS FUNCIONÁRIOS DO FICHEIRO ------------------------------ *\n");
        printf("\n\t\t* 3 ------- IMPRIMIR OS FUNCIONÁRIOS POR CATEGORIA ------------------------------------- *\n");
        printf("\n\t\t* 4 ------- GASTO DA UNIVERSIDADE COM OS FUNCIONÁRIOS ---------------------------------- *\n");
        printf("\n\t\t* 5 ------- CALCULAR O SALÁRIO DE UM FUNCIONÁRIO X EM FUNÇÃO DO SEU SALÁRIO POR HORA --- *\n");
        printf("\n\t\t* 6 ------- ORDENAR FUNCIONÁRIO NA ORDEM CRESCENTE ------------------------------------- *\n");
        printf("\n\t\t* 7 ------- IMPRIMIR OS FUNCIONÁRIOS COM SALÁRIO MAIOR QUE 75000$ ---------------------- *\n");
        printf("\n\t\t* 8 ------- ELIMINAR UM FUNCIONÁRIO A PARTIR DO Nº DO NIF ------------------------------ *\n");
        printf("\n\t\t* 0 ------- Sair\n\n");
        printf("\n\tEscolha uma opcao: ");
        scanf("%d",&op);
        printf("\n");
        switch (op) {
        case 0:
            printf("\t\t\t\t\t\t\t\t\t\t-> Saindo... \n");
            printf ("\tPressione ENTER para Sair->");
            fflush(stdin);
            pressioneEnter();
            system("cls");
            break;
        case 1:
            system("cls");
            IncerirFuncionario(funcionario,n);
            break;
        case 2:
            system("cls");
            ImprimirFuncionarios(funcionario,n);
            break;
        case 6:
            system("cls");
            OrdenarFuncionario(funcionario,n);
            break;
        case 8:
            system("cls");
            EliminarFuncionario(funcionario,n);
            break;
        default:
            system("COLOR C0");
            printf("\n\t\t\t\t*-*-*-*-- ERRO --> Numero INVALIDO!\n\n");
            printf ("\n\tPressione ENTER para Tentar Novamente->");
            fflush(stdin);
            pressioneEnter();
            system("cls");
        }
    } while (op != 0);

}
int main() {
    setlocale(LC_ALL, "Portuguese");
    struct Funcionario funcionario[100];
    int n;
     int *p;
    p = (struct Funcionario *)malloc(sizeof(struct Funcionario));

    if (p == NULL) {
        printf("\n\t ERRO MEMÓRIA INSUFICIENTE!\n");
        exit(1);//Terminar o programa
    }
    system("COLOR F0"); //Abertura do programa
    printf("\n\n\n\n\n\t\t\t....................................................................\n");
    printf("\n\t\t\t\t----> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n");
    printf("\n\t\t\t.....................................................................\n\n\n\n\n");
    printf ("\n\t\t\t                                                                      UNICV \n\n");
    printf ("\n\tPressione ENTER para iniciar->");
    fflush(stdin);
    pressioneEnter();
    system("cls");
    menu(funcionario,n);
     free(p);
    return 0;
}

 

  • Curtir 1
Postado
32 minutos atrás, vangodp disse:

você esqueceu por o prototipo da função menu antes de main. Em C/C++ tudo o que for usado deve estar declarado antes, a implementação você pode levar para outro lugar, incluindo outro arquivo.

continuo...
 

//Obrigado :)
//Funções declarads antes do main:
void menu(struct Funcionario funcionario[],int n);
void IncerirFuncionario(struct Funcionario funcionario[],int n);
void ImprimirFuncionarios(struct Funcionario funcionario[],int n);
void ImprimirFuncionariosCategoria(struct Funcionario funcionario[],int n);
void GastoFuncionario( struct Funcionario funcionario[],int n);
void CalcularSalario( struct Funcionario funcionario[], int n);
void OrdenarFuncionario(struct Funcionario* funcionario, int n);
void ImprimirFuncionariosSalario(struct Funcionario funcionario[],int n);
void EliminarFuncionario( struct Funcionario funcionario[], int n);

 

  • Curtir 1
Postado
3 minutos atrás, vangodp disse:

porque aqui na hora de ler ta perguntando em qual dos 20 nifs fazer a inserção...


scanf ( "%d", &funcionario[i].NIF );

o programa pensa que são 20 nifs então você teria:


scanf ( "%d", &funcionario[0].NIF );

scanf ( "%d", &funcionario[1].NIF );

scanf ( "%d", &funcionario[2].NIF );
...
scanf ( "%d", &funcionario[19].NIF );

 

adicionado 0 minutos depois

@Andrah Correto...! Agora você pode chamar qualquer função desde qualquer função >_<

O nif não deveria ser um vector certo?

  • Curtir 1
Postado
3 minutos atrás, vangodp disse:

Se você n tiver 20 nifs então mude de int NIF[20]; para int NIF;.
Um conselho.... somente use letras maiusculas para constantes tipo:
const int NIF;
ou
#define  numeroNIFs 20

Não são 20 NIFs kkkk

é int NIF. 

Ta bom Obrigado

  • Curtir 1
Postado
11 minutos atrás, vangodp disse:

ok... arrume isso então hehe, sobre tudo onde tiver lendo e imprimindo esses nifs

adicionado 0 minutos depois

talvez seja interessante guardar o nif em uma string

adicionado 3 minutos depois

assim você pode tomar os dados desse jeito"000.000.000-00"

adicionado 4 minutos depois

é só uma ideia hehe

adicionado 8 minutos depois

É preciso usar malloc para alocar uma única estrutura em main?

adicionado 8 minutos depois

Em todo caso o tipo do ponteiro deveria ser struct Funcionario * e n int

sim fica mas fácil na hora de eliminar os funcionários por NIF

o malloc() não sabia como usar então coloquei no main mas eu tinha usado o colloc()  nas funções antes depois eu tirei e coloquei o malloc no main 

  • Curtir 1
Postado
10 minutos atrás, vangodp disse:

//bibliotecas
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <conio.h>
#include <time.h>

//Dados do funcionário
struct Funcionario {
    char nome[20];
    int NIF;
    char categoria[20];
    float salario;
    int Hora_Trabalhados;
};

// Para não atrapalhar o bom funcionamento
void menu ( struct Funcionario funcionario[], int n );

void pressioneEnter() {
    char c;
    
    do {
        c = getch();
    } while ( c != 13 );
}



void IncerirFuncionario ( struct Funcionario funcionario[], int n ) {
    system ( "COLOR 0F" );
    FILE *file; // cria variável ponteiro para o arquivo
    file = fopen ( "funcionarios.txt", "w" ); //abrindo o arquivo
    
    if ( file == NULL ) //testando se o arquivo foi realmente criado
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
    else {
        printf ( "\n\n\n\n\tUNICV \n\n" );
        printf ( "\n\n\n\t\tDigite o numero de Funcionarios que pretende registrar: " );
        scanf ( "%i", &n );
        fflush ( stdin );
        system ( "cls" );
        static int i = 0;
        int y = n + i;
        
        if ( y > 99 )
            menu ( funcionario, n );
            
        printf ( "\n\n\n\t\t-------- INSCRIÇÃO DE FUNCIONÁRIO --------\n\n" );
        fprintf ( file, "\n\n\t----- LISTA DOS FUNCIONÁRIOS ----\n\n" );
        fprintf ( file, "\tNome      NIF 	  Salário     Categoria  Horas\n\n" );
        
        for ( ; i < y; i++ ) {
            system ( "COLOR 0B" );
            // para obter dados e armazenar no arquivo
            printf ( "\n\tDigite o nome do funcionário: " );
            scanf ( " %s", funcionario[i].nome );
            printf ( "\n\tDigite o NIF do funcionário: " );
            scanf ( "%d", &funcionario[i].NIF );
            printf ( "\n\tDigite o salario do funcionario: " );
            scanf ( "%f", &funcionario[i].salario );
            printf ( "\n\tDigite a categoria do funcionário: " );
            scanf ( " %s", funcionario[i].categoria );
            printf ( "\n\tDigite a Hora trabalhados pelo funcionário: " );
            scanf ( "%d", &funcionario[i].Hora_Trabalhados );
            printf ( "\n\n" );
            //A Escrevendo no arquivo
            fprintf ( file, "\t%s \t %d \t %.1f \t %s\t %d\n", funcionario[i].nome, funcionario[i].NIF, funcionario[i].salario, funcionario[i].categoria, funcionario[i].Hora_Trabalhados );
        }
        
        printf ( "\n\t\t-------------------------<3--------------------------\n" );
        printf ( "\n\t Incritos com sucesso! \n\n\t Registado no fecheiro -> funcionarios.txt\n\n" );
        printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
        fflush ( stdin );
        pressioneEnter();
        system ( "cls" );
        menu ( funcionario, y );
    }
    
    fclose ( file ); // para fechar o arquivo
}

void ImprimirFuncionarios ( struct Funcionario funcionario[], int n ) {
    FILE *file;
    
    file = fopen ( "C:\\Users\\alex\\Desktop\\teste4\\funcionarios.txt", "r" );
    
    if ( file == NULL )
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
        
    else {
        int i;
        printf ( "\n\n\n\t\t------- LISTA DOS FUNCIONÁRIOS ------\n\n" );
        
        for ( i = 0; i < n; i++ ) {
            system ( "COLOR 0F" );
            fscanf ( file, "%s", funcionario[i].nome );
            fscanf ( file, "%d", &funcionario[i].NIF );
            fscanf ( file, "%f", &funcionario[i].salario );
            fscanf ( file, "%s", funcionario[i].categoria );
            fscanf ( file, "%d horas", &funcionario[i].Hora_Trabalhados );
            printf ( "\n\tNome: %s", funcionario[i].nome );
            printf ( "\n\tNIF: %d", funcionario[i].NIF );
            printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
            printf ( "\n\tCategoria: %s", funcionario[i].categoria );
            printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
            printf ( "\n\n----------------------------------------------------------\n" );
        }
    }
    
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    fflush ( stdin );
    pressioneEnter();
    system ( "cls" );
    fclose ( file );
    
}
void OrdenarFuncionario ( struct Funcionario *funcionario, int n ) {

    int i, j;
    struct Funcionario aux;
    
    for ( i = 1; i < n; i++ ) {
        aux = funcionario[i] ;
        
        for ( j = i; ( j > 0 ) && ( aux.salario < funcionario[j - 1].salario ); j-- ) {
            funcionario[j] = funcionario[j - 1];
            funcionario[j] = aux;
        }
        
    }
    
    printf ( "\n\n\n\t------- LISTA DOS FUNCIONÁRIOS POR ORDEM CRESCENTE ------\n\n" );
    
    for ( i = 0; i < n; i++ ) {
    
        printf ( "\n\tNome: %s", funcionario[i].nome );
        printf ( "\n\tNIF: %d", funcionario[i].NIF );
        printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
        printf ( "\n\tCategoria: %s", funcionario[i].categoria );
        printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
        printf ( "\n\n----------------------------------------------------------\n" );
        
    }
    
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    fflush ( stdin );
    pressioneEnter();
    system ( "cls" );
}


void EliminarFuncionario ( struct Funcionario funcionario[], int n ) {
    FILE *file;
    
    //Abre o arquivo novamente para leitura
    file = fopen ( "funcionarios.txt", "r+" );
    
    if ( file == NULL )
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
        
    else {
        int nif, i=0;
        char resp;
        printf ( "\n\tInforme o NIF do funcionario a ser Eliminado: " );
        scanf ( "%d", &nif );
        
        while ( funcionario[i].NIF == nif ) {
        
            //if ( funcionario[i].ativo== 1 ) {
            
            printf ( "\n\tNome: %s", funcionario[i].nome );
            printf ( "\n\tNIF: %d", funcionario[i].NIF );
            printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
            printf ( "\n\tCategoria: %s", funcionario[i].categoria );
            printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
            printf ( "\n\n----------------------------------------------------------\n" );
            // }
            printf ( "\n\tDeseja realmente eliminar o Funcionário? S/N:" );
            scanf ( "%c", &resp );
            
            if ( ( resp == 'S' ) || ( resp == 's' ) ) {
                //   funcionario[i].ativo=0;
                printf ( "\n\tFuncionário eliminado com sucesso\n" );
                break;
            } else {
                if ( ( resp == 'N' ) || ( resp == 'n' ) ) {
                    printf ( "\tEliminação cancelada!\n" );
                    break;
                }
            }
        }
        
        i++;
        
        if ( i > 99 )
            printf ( "\n\n\t\tNIF não encontrado\n" );
    }
    
    fclose ( file );
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    fflush ( stdin );
    pressioneEnter();
    system ( "cls" );
}

void menu ( struct Funcionario funcionario[], int n ) {
    int op;
    
    do {
        system ( "COLOR 0F" ); //Menu
        printf ( "\n\n\t\t\t\t---> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n\n" );
        printf ( "\n\t\t* 1 ------- INSERIR OS FUNCIONÁRIOS E ENVIA-LOS PARA O FICHEIRO ------------------------ *\n" );
        printf ( "\n\t\t* 2 ------- IMPRIMIR A LISTA DOS FUNCIONÁRIOS DO FICHEIRO ------------------------------ *\n" );
        printf ( "\n\t\t* 3 ------- IMPRIMIR OS FUNCIONÁRIOS POR CATEGORIA ------------------------------------- *\n" );
        printf ( "\n\t\t* 4 ------- GASTO DA UNIVERSIDADE COM OS FUNCIONÁRIOS ---------------------------------- *\n" );
        printf ( "\n\t\t* 5 ------- CALCULAR O SALÁRIO DE UM FUNCIONÁRIO X EM FUNÇÃO DO SEU SALÁRIO POR HORA --- *\n" );
        printf ( "\n\t\t* 6 ------- ORDENAR FUNCIONÁRIO NA ORDEM CRESCENTE ------------------------------------- *\n" );
        printf ( "\n\t\t* 7 ------- IMPRIMIR OS FUNCIONÁRIOS COM SALÁRIO MAIOR QUE 75000$ ---------------------- *\n" );
        printf ( "\n\t\t* 8 ------- ELIMINAR UM FUNCIONÁRIO A PARTIR DO Nº DO NIF ------------------------------ *\n" );
        printf ( "\n\t\t* 0 ------- Sair\n\n" );
        printf ( "\n\tEscolha uma opcao: " );
        scanf ( "%d", &op );
        printf ( "\n" );
        
        switch ( op ) {
            case 0:
                printf ( "\t\t\t\t\t\t\t\t\t\t-> Saindo... \n" );
                printf ( "\tPressione ENTER para Sair->" );
                fflush ( stdin );
                pressioneEnter();
                system ( "cls" );
                break;
                
            case 1:
                system ( "cls" );
                IncerirFuncionario ( funcionario, n );
                break;
                
            case 2:
                system ( "cls" );
                ImprimirFuncionarios ( funcionario, n );
                break;
                
            case 6:
                system ( "cls" );
                OrdenarFuncionario ( funcionario, n );
                break;
                
            case 8:
                system ( "cls" );
                EliminarFuncionario ( funcionario, n );
                break;
                
            default:
                system ( "COLOR C0" );
                printf ( "\n\t\t\t\t*-*-*-*-- ERRO --> Numero INVALIDO!\n\n" );
                printf ( "\n\tPressione ENTER para Tentar Novamente->" );
                fflush ( stdin );
                pressioneEnter();
                system ( "cls" );
        }
    } while ( op != 0 );
    
}
int main() {
    setlocale ( LC_ALL, "Portuguese" );
    struct Funcionario funcionario[100];
    int n;
    struct Funcionario* p = ( struct Funcionario * ) malloc ( sizeof ( struct Funcionario ) );
    
    if ( p == NULL ) {
        printf ( "\n\t ERRO MEMÓRIA INSUFICIENTE!\n" );
        exit ( 1 ); //Terminar o programa
    }
    
    system ( "COLOR F0" ); //Abertura do programa
    printf ( "\n\n\n\n\n\t\t\t....................................................................\n" );
    printf ( "\n\t\t\t\t----> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n" );
    printf ( "\n\t\t\t.....................................................................\n\n\n\n\n" );
    printf ( "\n\t\t\t                                                                      UNICV \n\n" );
    printf ( "\n\tPressione ENTER para iniciar->" );
    fflush ( stdin );
    pressioneEnter();
    system ( "cls" );
    menu ( funcionario, n );
    free ( p );
    return 0;
}
  Mostrar conteúdo oculto

Screenshot_3.thumb.png.e4a431f38f25bd18685f86658f0f58fd.png

 

adicionado 1 minuto depois

Vou rodar ele e ver o que acontece.... Quero ver o arquivo gerado.

adicionado 3 minutos depois

Temos outro erro... mas agora é problema de sujeira na memória.
 

  Mostrar conteúdo oculto

Screenshot_3.png.0396a34f4baee05b9b9829bfd0eb8818.png

 

adicionado 7 minutos depois

você precisa limpar o buffer antes de ler strings ou chars...
Deveria buscar alguns tutoriais de como limpar o buffer em C para aprender a faze-lo corretamente. A forma mais fácil é pondo o fflush(stdin) mas nao lhe recomendo fazer isso,tTem comportamento indefinido... pode sair um dragão na sua tela. >_<

o  fflush(stdin);  faz isso ele limpa o lixo de  memoria 

  • Curtir 1
Postado

Adicionei a função flush e troquei todos os fflush(stdin) pela função flush(), não testei mas deve funcionar normalmente:

//bibliotecas
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <conio.h>
#include <time.h>

//Dados do funcionário
struct Funcionario {
    char nome[20];
    int NIF;
    char categoria[20];
    float salario;
    int Hora_Trabalhados;
};

// Para não atrapalhar o bom funcionamento
void menu ( struct Funcionario funcionario[], int n );

void pressioneEnter() {
    char c;
    
    do {
        c = getch();
    } while ( c != 13 );
}

void flush(){
    int c;
    /*Lê todos os caracteres até encontrar '\n' ou EOF:*/
    while( (c = getchar()) != '\n' && c != EOF );
}

void IncerirFuncionario ( struct Funcionario funcionario[], int n ) {
    system ( "COLOR 0F" );
    FILE *file; // cria variável ponteiro para o arquivo
    file = fopen ( "funcionarios.txt", "w" ); //abrindo o arquivo
    
    if ( file == NULL ) //testando se o arquivo foi realmente criado
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
    else {
        printf ( "\n\n\n\n\tUNICV \n\n" );
        printf ( "\n\n\n\t\tDigite o numero de Funcionarios que pretende registrar: " );
        scanf ( " %i", &n );
        flush ();
        system ( "cls" );
        static int i = 0;
        int y = n + i;
        
        if ( y > 99 )
            menu ( funcionario, n );
            
        printf ( "\n\n\n\t\t-------- INSCRIÇÃO DE FUNCIONÁRIO --------\n\n" );
        fprintf ( file, "\n\n\t----- LISTA DOS FUNCIONÁRIOS ----\n\n" );
        fprintf ( file, "\tNome      NIF 	  Salário     Categoria  Horas\n\n" );
        
        for ( ; i < y; i++ ) {
            system ( "COLOR 0B" );
            // para obter dados e armazenar no arquivo
            printf ( "\n\tDigite o nome do funcionário: " );
            scanf ( " %s", funcionario[i].nome );
            printf ( "\n\tDigite o NIF do funcionário: " );
            scanf ( " %d", &funcionario[i].NIF );
            printf ( "\n\tDigite o salario do funcionario: " );
            scanf ( " %f", &funcionario[i].salario );
            printf ( "\n\tDigite a categoria do funcionário: " );
            scanf ( " %s", funcionario[i].categoria );
            printf ( "\n\tDigite a Hora trabalhados pelo funcionário: " );
            scanf ( " %d", &funcionario[i].Hora_Trabalhados );
            printf ( "\n\n" );
            //A Escrevendo no arquivo
            fprintf ( file, "\t%s \t %d \t %.1f \t %s\t %d\n", funcionario[i].nome, funcionario[i].NIF, funcionario[i].salario, funcionario[i].categoria, funcionario[i].Hora_Trabalhados );
        }
        
        printf ( "\n\t\t-------------------------<3--------------------------\n" );
        printf ( "\n\t Incritos com sucesso! \n\n\t Registado no fecheiro -> funcionarios.txt\n\n" );
        printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
        flush ();
        pressioneEnter();
        system ( "cls" );
        menu ( funcionario, y );
    }
    
    fclose ( file ); // para fechar o arquivo
}

void ImprimirFuncionarios ( struct Funcionario funcionario[], int n ) {
    FILE *file;
    
    file = fopen ( "C:\\Users\\alex\\Desktop\\teste4\\funcionarios.txt", "r" );
    
    if ( file == NULL )
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
        
    else {
        int i;
        printf ( "\n\n\n\t\t------- LISTA DOS FUNCIONÁRIOS ------\n\n" );
        
        for ( i = 0; i < n; i++ ) {
            system ( "COLOR 0F" );
            fscanf ( file, " %s", funcionario[i].nome );
            fscanf ( file, " %d", &funcionario[i].NIF );
            fscanf ( file, " %f", &funcionario[i].salario );
            fscanf ( file, " %s", funcionario[i].categoria );
            fscanf ( file, " %d horas", &funcionario[i].Hora_Trabalhados );
            printf ( "\n\tNome: %s", funcionario[i].nome );
            printf ( "\n\tNIF: %d", funcionario[i].NIF );
            printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
            printf ( "\n\tCategoria: %s", funcionario[i].categoria );
            printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
            printf ( "\n\n----------------------------------------------------------\n" );
        }
    }
    
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    flush ();
    pressioneEnter();
    system ( "cls" );
    fclose ( file );
    
}
void OrdenarFuncionario ( struct Funcionario *funcionario, int n ) {

    int i, j;
    struct Funcionario aux;
    
    for ( i = 1; i < n; i++ ) {
        aux = funcionario[i] ;
        
        for ( j = i; ( j > 0 ) && ( aux.salario < funcionario[j - 1].salario ); j-- ) {
            funcionario[j] = funcionario[j - 1];
            funcionario[j] = aux;
        }
        
    }
    
    printf ( "\n\n\n\t------- LISTA DOS FUNCIONÁRIOS POR ORDEM CRESCENTE ------\n\n" );
    
    for ( i = 0; i < n; i++ ) {
    
        printf ( "\n\tNome: %s", funcionario[i].nome );
        printf ( "\n\tNIF: %d", funcionario[i].NIF );
        printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
        printf ( "\n\tCategoria: %s", funcionario[i].categoria );
        printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
        printf ( "\n\n----------------------------------------------------------\n" );
        
    }
    
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    flush ();
    pressioneEnter();
    system ( "cls" );
}


void EliminarFuncionario ( struct Funcionario funcionario[], int n ) {
    FILE *file;
    
    //Abre o arquivo novamente para leitura
    file = fopen ( "funcionarios.txt", "r+" );
    
    if ( file == NULL )
        printf ( "\n-->Nao foi possivel abrir o fecheiro\n\n" );
        
    else {
        int nif, i=0;
        char resp;
        printf ( "\n\tInforme o NIF do funcionario a ser Eliminado: " );
        scanf ( " %d", &nif );
        
        while ( funcionario[i].NIF == nif ) {
        
            //if ( funcionario[i].ativo== 1 ) {
            
            printf ( "\n\tNome: %s", funcionario[i].nome );
            printf ( "\n\tNIF: %d", funcionario[i].NIF );
            printf ( "\n\tSalario: %.1f $00", funcionario[i].salario );
            printf ( "\n\tCategoria: %s", funcionario[i].categoria );
            printf ( "\n\tHoras de trabalho: %d horas", funcionario[i].Hora_Trabalhados );
            printf ( "\n\n----------------------------------------------------------\n" );
            // }
            printf ( "\n\tDeseja realmente eliminar o Funcionário? S/N:" );
            scanf ( " %c", &resp );
            
            if ( ( resp == 'S' ) || ( resp == 's' ) ) {
                //   funcionario[i].ativo=0;
                printf ( "\n\tFuncionário eliminado com sucesso\n" );
                break;
            } else {
                if ( ( resp == 'N' ) || ( resp == 'n' ) ) {
                    printf ( "\tEliminação cancelada!\n" );
                    break;
                }
            }
        }
        
        i++;
        
        if ( i > 99 )
            printf ( "\n\n\t\tNIF não encontrado\n" );
    }
    
    fclose ( file );
    printf ( "\n\n\n\t\t\tPressione ENTER para Continuar->" );
    flush ();
    pressioneEnter();
    system ( "cls" );
}

void menu ( struct Funcionario funcionario[], int n ) {
    int op;
    
    do {
        system ( "COLOR 0F" ); //Menu
        printf ( "\n\n\t\t\t\t---> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n\n" );
        printf ( "\n\t\t* 1 ------- INSERIR OS FUNCIONÁRIOS E ENVIA-LOS PARA O FICHEIRO ------------------------ *\n" );
        printf ( "\n\t\t* 2 ------- IMPRIMIR A LISTA DOS FUNCIONÁRIOS DO FICHEIRO ------------------------------ *\n" );
        printf ( "\n\t\t* 3 ------- IMPRIMIR OS FUNCIONÁRIOS POR CATEGORIA ------------------------------------- *\n" );
        printf ( "\n\t\t* 4 ------- GASTO DA UNIVERSIDADE COM OS FUNCIONÁRIOS ---------------------------------- *\n" );
        printf ( "\n\t\t* 5 ------- CALCULAR O SALÁRIO DE UM FUNCIONÁRIO X EM FUNÇÃO DO SEU SALÁRIO POR HORA --- *\n" );
        printf ( "\n\t\t* 6 ------- ORDENAR FUNCIONÁRIO NA ORDEM CRESCENTE ------------------------------------- *\n" );
        printf ( "\n\t\t* 7 ------- IMPRIMIR OS FUNCIONÁRIOS COM SALÁRIO MAIOR QUE 75000$ ---------------------- *\n" );
        printf ( "\n\t\t* 8 ------- ELIMINAR UM FUNCIONÁRIO A PARTIR DO Nº DO NIF ------------------------------ *\n" );
        printf ( "\n\t\t* 0 ------- Sair\n\n" );
        printf ( "\n\tEscolha uma opcao: " );
        scanf ( " %d", &op );
        printf ( "\n" );
        
        switch ( op ) {
            case 0:
                printf ( "\t\t\t\t\t\t\t\t\t\t-> Saindo... \n" );
                printf ( "\tPressione ENTER para Sair->" );
                flush ();
                pressioneEnter();
                system ( "cls" );
                break;
                
            case 1:
                system ( "cls" );
                IncerirFuncionario ( funcionario, n );
                break;
                
            case 2:
                system ( "cls" );
                ImprimirFuncionarios ( funcionario, n );
                break;
                
            case 6:
                system ( "cls" );
                OrdenarFuncionario ( funcionario, n );
                break;
                
            case 8:
                system ( "cls" );
                EliminarFuncionario ( funcionario, n );
                break;
                
            default:
                system ( "COLOR C0" );
                printf ( "\n\t\t\t\t*-*-*-*-- ERRO --> Numero INVALIDO!\n\n" );
                printf ( "\n\tPressione ENTER para Tentar Novamente->" );
                flush ();
                pressioneEnter();
                system ( "cls" );
        }
    } while ( op != 0 );
    
}
int main() {
    setlocale ( LC_ALL, "Portuguese" );
    struct Funcionario funcionario[100];
    int n;
    struct Funcionario* p = ( struct Funcionario * ) malloc ( sizeof ( struct Funcionario ) );
    
    if ( p == NULL ) {
        printf ( "\n\t ERRO MEMÓRIA INSUFICIENTE!\n" );
        exit ( 1 ); //Terminar o programa
    }
    
    system ( "COLOR F0" ); //Abertura do programa
    printf ( "\n\n\n\n\n\t\t\t....................................................................\n" );
    printf ( "\n\t\t\t\t----> SISTEMA DE REGISTO E CONTROLE DE FUNCIONÁRIO \n" );
    printf ( "\n\t\t\t.....................................................................\n\n\n\n\n" );
    printf ( "\n\t\t\t                                                                      UNICV \n\n" );
    printf ( "\n\tPressione ENTER para iniciar->" );
    flush ();
    pressioneEnter();
    system ( "cls" );
    menu ( funcionario, n );
    free ( p );
    return 0;
}

 

  • Amei 1
Postado
22 minutos atrás, Andrah disse:

o  fflush(stdin);  faz isso ele limpa o lixo de  memoria 

 

Não é uma boa definição.  E não funciona para stdin. Alguns compiladores fazem isso mas o padrão da linguagem estabelece claramente que fflush() só está defindo para fluxos --- streams --- de saída e que o comportamento para o caso de streams de entrada é indefinido. O propósito de fflush() não é limpar nada: é enviar as coisas que estão esperando para ser enviadas. 
 

Isso acontece porque o sistema, por razões de eficiência, usa buffers e armazena valores em buffers para enviar quando achar que é hora. E às vezes você quer que descarregue --- flush --- numa certa hora ao invés de ficar esperando. E aí usa fflush() que não vai limpar nada. Vai transmitir. Como um printf() por exemplo. Se não entendeu pergunte de novo e mostro um exemplo mais elaborado.

 

E no caso de stdin --- o fluxo padrão de entrada --- não se está falando nem de memória nem de "lixo". O que você quer fazer é ler e desprezar o que tem no buffer de teclado PORQUE ALGUÉM TECLOU e descartar.

 

Em geral o que você quer é apenas ler e descartar o '\n' que encerrou a última leitura. E talvez alguma bobagem que o usuário digitou num scanf() para ler um número. Mais uma vez, se não entendeu pergunte de novo e mostro um exemplo mais elaborado.

 

Uma rotina como essa abaixo teria o efeito que você quer e não dependeria de estar usando um certo compilador

void    flush()
{
    int ch = 0;
    do { ch = getc(stdin); } while ((ch != '\n') && (ch != EOF));
};	// flush()

scanf() é

int scanf(const char *format, ...)

scanf() retorna um int com o número de itens lidos. Use. É melhor para você e leva a programas mais sólidos... scanf() é uma rotina "ativa" que pode "comer" linhas e linhas de sua entrada por exemplo.

E na verdade não escrita para ler valores do teclado. Foi escrita por um grande programador e para ler entrada formatada. scan formatted input era o objetivo e deu o nome a ela

  • Amei 1
Postado
22 minutos atrás, vangodp disse:

também n aconselho muito o uso desse flush @isrnick >_<. O porque você pode ver aqui:

 

 

Tenho feito uma campanha aqui para explicar isso em meio milhão de tópicos.

 

Não se trata de sujeira. E não é lixo de memória. São valores que foram digitados.


Em geral tudo começa --- e muitas vezes termina --- pelo '\n' que encerrou a última leitura se você usa scanf().

 

Entenda que se o usuário entrou com 1234>ENTER> para entrar com um int e você usou scanf() para ler, quando você ler isso vai ter o seu int com 1234 e no buffer de entrada vai estar lá o solitário <ENTER> ou '\n' esperando para ser consumido. E é esse valor dependendo da máscara que usou em scanf() numa próxima leitura, que vai zoar toda a entrada: scanf() vai pegar esse <ENTER> e dar por resolvida a próxima leitura, Só que não leu nada e como parece que tem uma lei que impede tratar o retorno de scanf() ou usar outra rotina para ler do teclado --- a confusão está feita. Se você vai ler vários campos então vai zoar tudo....

 

scanf() não foi escrita para isso. E o valor de retorno é para ser usado.

 

Se não fez sentido o que eu expliquei, experimente no Windows usar 
 

    PeekConsoleInput()

que mostra o que tem no buffer da console ANTES de você ler, ou pergunte e tento mostrar um exemplo melhor.

 

 

  • Obrigado 2
Postado
1 minuto atrás, vangodp disse:

Ja que você entrou em tecnicismos agora n vai ficar no meio n é?

 

:)  que significa? O que seria o "tecnicismo"? 

  • Haha 1
Postado
1 minuto atrás, arfneto disse:

 

:)  que significa? O que seria o "tecnicismo"? 

queria saber tmb kkkk

poderiam me ajudar a fazer os outros códigos né? :) kkkkk

adicionado 2 minutos depois

@vangodp Teria sim eu entende o que você me explicou 

Postado
15 minutos atrás, vangodp disse:

 

Em fim... é só uma a mais de tantas hehehe.

Né kkkkk

adicionado 11 minutos depois

@vangodp me ajuda ai com as outras funções *_*

Postado

@vangodp Você definiu char buffer com tamanho 100, mas deveria usar a constante BUFSIZ que é o tamanho ótimo de buffer estimado para um arquivo I/O.

 

Usar a função setbuf(stream, buffer) é uma abreviação de usar setvbuf(stream, buffer, _IOFBF, BUFSIZ) , note que já é assumido o tamanho BUFSIZ para o buffer, se quiser usar um buffer com tamanho diferente terá que usar a função setvbuf() diretamente alterando o último parâmetro, ao invés de setbuf().

 

Outro problema é que você declarou o buffer dentro da função main, mas para stdin e stdout tem que ser declarado no escopo global, pois os streams de entrada só deve ser fechado quando o programa for finalizado, mas o buffer dentro do main será finalizado quando a função main acabar (e o stdin/stdout vai ficar sem buffer).

 

image.png.ca4c9e029dd485d34dfb63e72c99babf.png

Fonte: https://en.cppreference.com/w/c/io/setbuf

 

  • Curtir 1
Postado

Não sei ao certo quão correto é usar essa função setbuf para limpar stdin, mas se quiser usar no código basta trocar essa função flush:

void flush(){
    int c;
    /*Lê todos os caracteres até encontrar '\n' ou EOF:*/
    while( (c = getchar()) != '\n' && c != EOF );
}

 

Por isto:

char buffer[BUFSIZ];
void flush(){
    setbuf(stdin, buffer);
}

E não precisa mudar mais nada no código.

 

@vangodp Sobre flush que postei originalmente (a primeira nesse post) as coisas que ele apontou a meu ver não são falhas, se você entende o que a função faz, também entende em que situação deve usar e quando não, ou seja só usa quando houver certeza de que pelo menos o caractere '\n' vai ficar sobrando no stdin. E usar para pausar a tela é uma vantagem, pois é melhor do que usar um único getchar() para pausar, pois vai limpar qualquer coisa que digitar se a pessoa não der Enter imediatamente. Outra coisa que eu não entendi é pra que ele quer limpar o stdin antes de fazer qualquer leitura do teclado? Se não tem nada para limpar? flush deve ser usada após os scanfs para limpar o que sobrou.

 

  • Curtir 1
Postado
1 minuto atrás, vangodp disse:

qual problema você tem?

Em terminar o programa 

em fazer as funções para colocar nos case 

até agora só incerir dados e imprimir que eu acho que ta certo  

Postado
2 horas atrás, vangodp disse:

E uma coisa... \n no buffer para mim é lixo, diga o que diga

 

Vou dizer então algo. Repetir talvez.

 

o tal '\n' não é lixo. 


Exemplo:

 

Se você digitou 1234azul<ENTER> isso está lá no buffer do teclado. O sistema não sabe como você vai ler.
E você não leu ainda. Pode usar Peek e ver o que está lá, como eu disse. Não vou postar um exemplo aqui porque isso funciona bem com uma tela dinâmica onde você vê o buffer sendo consumido. Se eu postar um programa o leitor teria que rodar na máquina dele e suspeito que muitos sequer terminem de ler isso, quanto mais rodar um programa...

 

Mas se alguém disser que vai ler/rodar eu escrevo um.

 

Vou repetir: scanf() foi feita para... scan formatted input: ler entrada formatada. E é uma função genial, Economiza horas. Em coisas como ler um arquivo csv por exemplo, aqueles com campos separados por vírgulas.

 

O teclado não é isso. As pessoas são incrivelmente criativas ao digitar, como se sabe. Depois vou mostrar um exemplo curto.

 

De volta ao caso: o cara digitou isso: 1234azul<ENTER> e o sistema não sabe o que fazer com isso.

Se você usou por exemplo:

 

    scanf("%d", digito);

 

Então scanf() vai pegar os dígitos e ao encontrar o 'a' vai se dar por satisfeita. Não vai ler o 'a'  porque não é pra ela. Podia ser o <ENTER>. Estamos falando de um sistema operacional. 

Se a próxima leitura for

    scanf("%s", linha);

Adivinhe o que ela vai ler para a suposta string linha...

 

Sim, vai ler "azul" e o buffer vai ficar vazio. Só alegria.

 

Pergunta: e se o usuário queria de fato digito = 1234 e linha = "" (em branco) ? ia digitar o que? 1234<ENTER>

Vai funcionar? Não. E aí mais um momento de fúria para o infeliz aluno. 

 

No mesmo exemplo

 

Por outro lado, se o programa tivesse chamado fgets() para ler e não scanf(), o sistema não sabe nada disso. O buffer é o que está lá: 1234azul<ENTER>

 

Usando fgets()

    char linha[80];
    printf("[(fgets()] Entre com o numero e tecle ENTER: ");
    fgets(linha, 20, stdin);
    printf("fgets() leu %d caracteres\n", strlen(linha));
    for (int i = 0; i < strlen(linha); i += 1)
        printf("%d ", linha[i]);
    printf("\n");

veja

image.png.0dd9aaf602631a59dfd38188bd4e8139.png

 

E lá está inclusive o <ENTER>, aquele 10 também conhecido por '\n' e nesse caso o <ENTER> que você disse que era lixo está aí e foi lido. 

 

Muito iniciante fica furioso porque fgets() lê o '\n' e coloca no fim da string porque pensa no imediato que é usar em um printf() mas os caras que escreveram isso é que são espertos: o tal <ENTER> faz parte da string e não do próximo campo a ser lido e simplesmente descartar seria uma decisão que poderia quebrar outros programas. E deixar lá é o que scanf() faz.

A escolha é e tem que ser de quem lê. O '\n' não pode sumir.

 

Exemplo: 

 

Você quer ler dois int. scanf() não foi feita para ler coisas do teclado, como eu já disse. Até o nome dela mostra para que foi escrita.

 

Mas aparentemente os instrutores não gostam dos alunos ou querem que eles sofram e então ensinam a ler usando scanf(). Dez linhas de código depois e tem que explicar o que o infeliz que está tentando aprender ainda não tem fundamento para entender: às vezes tem a p$%%a do '&'. Às vezes não. Às vezes é um ponteiro às vezes não e o instrutor sequer qualificou direito o que é um ponteiro. Uma string é um endereço, um int precisa de &. Um inferno.

 

Imagine um aluno do tipo que quase não existe: ele vai ler o manual e vê que scanf() tem uma máscara, como printf() com %isso ou %aquilo. Isso se chama especificador e eles são desa forma:

%[*][tamanho][modificador]tipo

Sério? E que eles tem uma série de "truques". E mesmo algumas coisas funcionam diferente do que está escrito, dependendo de você usar esse ou aquele compilador. É difícil entender isso. Porque é difícil mesmo. 

 

É para deixar o cara furioso. O simples fato de ler um char com %s e não %c cancela o programa do aluno. Você pode teclar duzentos ENTER na leitura do tal int e o programa zoa toda a tela. E o infeliz aluno caprichou para montar os prompts daquele cadastro chato com 5 campos e tal...

 

Um espaço por engano na tal máscara pode zoar tudo. Ou pode ser a solução porque vai pular os espaços e seu programa vai cancelar porque o cara digitou uma letra. Aí alguém te diz que você pode usar uma lista de caracteres válidos ou inválidos, uma expressão regular como [^abcd] que tudo vai funcionar. Sério? Expressões regulares, ponteiros, espaços significativos? Pobre estudante. Não, scanf() não é para isso.

 

Eu posso escrever uma expressão regular de meio metro, uma chamada a scanf() com 8 especificadores e fazer pose de guru, eu sei que é esperto tratar o retorno de scanf(). Posso citar várias possíveis máscaras para minimizar ou até resolver boa parte dos problemas. Mas é o meu caso. Eu programava em C nos anos 80 e já dizia isso. Mas e daí? Eu acho que não é o caminho. scanf() é frágil para isso. Ainda mais se você não trata o argumento de retorno, o que ninguém faz porque acho que ninguém ensina.

 

De volta ao exemplo

 

Mas então você escreve lá o simples

    printf("Entre com o numero e tecle ENTER: ");
    scanf("%d", &digito);
    printf("scanf() leu '%d'\n", digito);
    printf("\n");

    printf("Entre com outro numero e tecle ENTER: ");
    scanf("%d", &digito);
    printf("Leu %d\n", digito);

Normal certo?

 

caso 1
 

image.png.f694f2a76081204975c6df4bc0a1a421.png

 

Certinho! Muito bom.

 

caso 2
 

image.png.60486ac5b85bf8a0d56e665910578052.png

 

E zoou tudo. Podia ao menos ter lido o 2 para o segundo número, né? Mas não leu e ainda passou reto pela segunda leitura. Isso não é lixo no buffer. É algo que foi teclado. O sistema não tem como saber o que é importante ou não. 

 

Com cuidado é possível usar máscaras com scanf() que descartam o fim da linha mas com o tempo fica claro que é melhor ou ler linha a linha com fgets() e tratar no programa, ou ler letra a letra com getc() e fazer a mesma coisa.

 

Num programa o infeliz que está aprendendo quer ter controle e assim é muito mais simples. Você lê o que está lá. E trata. 

 

caso 3
 

image.png.a5fcc2d7c7ed552cda9ba660eef0a5fa.png
 

Claro que a Apple diria que o usuário não soube usar o equipamento. Mas o cara teclou um monte de enter, um a depois o 12 e o sistema até leu o 12. E zoou toda a tela. 

 

E aí o cara quer aprender a usar o cursor, limpar a tela, usar coisas como posicionar o cursor e tal. Mas o problema não era esse.

 

Ou era?

 

Na prática o que a gente quer é ter controle. scanf() não é para isso no caso do teclado. O simples é ler tudo como string via fgets() ou tudo como char via getc() e seguir de acordo. Em alguns casos até usar PeekConsoleInput() no Windows. No Linux e no Mac acho que não tem equivalente.

 

Ler tudo como string é o que faz o runtime para seu programa por exemplo, ao montar a lista de argumentos argv. E se sabe que funciona.

 

Ler letra a letra é o mais seguro mas pode ser chato claro. Mas a lógica é a mesma de scanf() mas dentro do seu programa: você define por exemplo um conjunto de teclas possíveis, aceita só aquelas. Pode soar um beep quando não for o que você quer. E escreve uma função para cada caso. Ex: para ler um telefone você pode aceitar os dígitos e espaços e traços. Pode ter um '+' mas só no início e tal. Pode aceitar as letras como estão no teclado e substituir. Mas não vai aceitar outros símbolos. Para ler um inteiro pode ter um sinal, para ler um CPF você já pode ir calculando os dígitos enquanto lê. Em muitos casos você tem valores pré-existentes e pode mostrar uma lista deles, como nas pesquisas na web. Nada original.

 

Na interface gráfica você cria um campo e o sistema tem umas regras de edição e você cria um botão que aceita o valor por exemplo. Mas num jogo é definido um universo de teclas e apenas essas. Não por acaso os computadores de crianças tem umas teclas mais gastas que as outras...

 

Ou se pode usar scanf() ;) Recomendo ao menos ler o valor de retorno... Resolve talvez metade dos problemas, porque muitas vezes scanf() não lê nada e diz que não leu nada, mas o programa "não ouve" e passa adiante... Como no exemplo acima

 

 

 

 

image.png

  • Obrigado 1
Postado

@arfneto Ao dizer que é "lixo", não se esta dizendo que '\n' apareceu do nada ou indevidamente na stdin, claramente ele é acrescentado a string do stdin quando aperta Enter, exatamente como deveria.

 

O sentido de dizer que '\n' e qualquer outra coisa que sobrou até o '\n' na stdin, depois do scanf ler a parte relevante para a entrada de dados, ser um "lixo", é o de implicar que o que sobrou não será usado pelo programa logo deve ser descartado, ou seja está de fato tratando o texto contido na stdin.

 

  • Obrigado 1
Postado
14 minutos atrás, isrnick disse:

O sentido de dizer que '\n' e qualquer outra coisa que sobrou até o '\n' na stdin, depois do scanf ler a parte relevante para a entrada de dados, ser um "lixo", é o de implicar que o que sobrou não será usado pelo programa logo deve ser descartado, ou seja está de fato tratando o texto contido na stdin

 

Bem, acho que ficou claro o que eu queria dizer. Não é o caso de repetir. "Deve ser descartado" porque scanf() usou como delimitador e parou de consumir a entrada porque essa é a mecânica dessa função. E nesse particular caso, que nesses programas de estudantes é o mais comum, pode não mais ser lido. Se a  leitura fosse feita via fgets() o '\n' teria sido consumido. Se a leitura fosse feita via getc() tudo seria afinal consumido. 

 

No próprio exemplo usando scanf() para ler o int e uma string se o valor vem 1234string<enter> o scanf() leria tudo normalmente. Inclusive o ENTER.

 

Não se pode afirmar que ele deveria ser descartado porque depende do contexto. Mesmo que se use apenas scanf()

 

 

  • Curtir 1
Postado
43 minutos atrás, vangodp disse:

Mas o ponto mais importante é "coisas inúteis". Em nosso caso \n ou <ENTER> como você mostra é lixo. Em C/C++ se usa analogias para muitas coisas. Quando se referi a limpar buffer você imagina uma faxineira lá, de escovinha na mão, jogando o lixo fora? Não!!!! É pura analogia arfneto. Se a analogia é "LIMPAR O BUFFER", a pergunta é "do que", o que está lá é lixo mesmo que você n goste dessa analogia. Tendeu?

 

Mas você entendeu que

  • no exemplo que mostrei mesmo usando scanf() esses valores podem ser lidos e consumidos, inclusive o <ENTER>, imagino? No exemplo de 1234azul<ENTER> para ler o int e uma string?
  • que ao usar fgts() o '\n' é consumido e faz parte da string?
  • que ao usar getc() o '\n' vai ser obviamente consumido porque é a única maneira de saber que o int acabou de ser lido? Afinal a unidade é o caracter.

Eu entendo o que quer dizer. E eu imagino ter noção do que é uma analogia. Apenas tentei ressaltar o aspecto formal da coisa: o sistema tem o que foi digitado e não é possível simplesmente descartar algo. E não é exatamente lixo ou descartável. O sistema não sabe como isso vai ser consumido. E te mostrei os exemplos. Imagine a entrada padrão sendo redirecionada ou isso sendo gravado para ser lido de novo. Se você excluir esse '\n' vai interferir no programa.

 

50 minutos atrás, vangodp disse:

você quase é mais velho que a linguagem shuehsuhe.

você nem usa C não é? certamente você usa C# shuehs. ou pode que C++

 

:( :( É.Na época eu estava experimentando uma mudança de plataforma: do mainframe rodando OS/MVS e VM/CMS para o Unix. Quando saiu o tal "livro branco"do C, O livro de K&R, The C Programming Language, era super novidade e havia uma grande expectativa me conseguir um compilador para rodar no PDP-11 que eu podia usar de noite, e que nem rodava Unix ainda.O livro chegou muito antes. Mas logo a gente conseguiu um.
 

E era mais uma opção então. Como sempre, dependia da necessidade. Mas no IBM se usava mesmo COBOL e FORTRAN e Assembler às vezes. E no mini-computador que é como a gente chamava na época rodava Pascal, FORTRAN e aquela nova linguagem C. E o moderno era o Pascal. Eu até tinha o Pascal User Manual and Report do prof. Dijkstra. Tenho até hoje eu acho :D e ficava junto com o tal livro branco. C não era inicialmente levado a sério. Mas logo mudou. 

 

Isso é uma longa história. Mas hoje estamos voltando exatamente àquele paradigma, com tudo "na nuvem" e os usuários em "terminais".  Embora os terminais hoje tenham muitos recursos. Mesmo a virtualização já estava bem presente nos '80 com o VM/CMS. Você deve imaginar o que era VM nessa sigla. E nos 80 já havia uma versão de Pascal que rodava em máquinas virtuais com código interpretado, chamado pCode. Desenvolvido pela UCLA. Qualquer semelhança com a jvm é porque era a mesma coisa. Você podia escrever Interfaces em Pascal e depois desenvolver a tal Implementation. Igualzinho. Nos '80.

 

Seria legal eu ter lido isso numa revista ou na WikiPedia. Isso indicaria que eu não sou assim tão veterano. Mas é de memória mesmo :( 

 

  • Obrigado 1
Postado
7 horas atrás, vangodp disse:

O salário você precisaria calcular ele antes de mandar para o arquivo?

sim deveria calcular antes mesmo 

7 horas atrás, vangodp disse:

struct Funcionario* p = ( struct Funcionario * ) malloc ( sizeof ( struct Funcionario ) * X );

o struct Funcionario* p = ( struct Funcionario * ) malloc ( sizeof ( struct Funcionario ) );  coloquei porque o programa pede para usar memoria dinâmica , mas acho que fica melhor se eu utilizar o colloc(); em quanto faço as funções e pedir memoria para o computador ao longo da execução do programa 

 

7 horas atrás, vangodp disse:

Qual o valor desse y????

 O y é o valor de n+1 onde n é o valor total de funcionários que o usuário digitou fiz assim para poder ter quantos funcionários o usuário deseja  (<99).  

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

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!