1

建物内の部屋の数を管理する C プロジェクトを行っています。部屋を予約するか事前予約するかを選択できます。そのために、ユーザーにいくつかのデータ (名前、部屋を予約したい時間、予約したい部屋) を入力するように求めます。

私はすでにそれを行うことができました。ただし、すでに予約されている部屋を事前予約するオプションをユーザーに提供できるようにする必要もあります。そのため、予約がキャンセルされた場合、同じ時間に事前予約した最初のユーザーがその部屋に割り当てられます。 .

「事前予約」とは何を意味するか: ユーザーを FIFO (先入れ先出し) の哲学に従う順番待ちリストに入れる

それを行う方法を提案できますか?

これは私のヘッダーファイルです:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

#define ARQ "Dados.txt" /*ARQUIVO COM OS DADOS*/

#define OP_INSERIR     '1'
#define OP_ALTERAR     '2'
#define OP_APAGAR      '3'
#define OP_LISTAR      '4'
#define OP_PESQUISAR   '5'
#define OP_PRERESERVAR '6'

#define OP_SAIR       '0'

#define OP_PESQ_HORAS '1'
#define OP_PESQ_NOME  '2'

char *MainMenu[]={
    "\n\tM E N U    P R I N C I P A L\n",
    "1. Fazer Reserva",
    "2. Alterar Reserva",
    "3. Apagar Reserva",
    "4. Listar Reservas",
    "5. Pesquisar",
    "0. Sair",
    NULL
};

char *PesqMenu[]={
    "1. Pesquisar por Intervalo de Tempo",
    "2. Pesquisar por Nome",
    "0. Voltar",
    NULL
};

FILE *fp;

typedef struct{
    char Nome[100];
    int Sala;
    int Hora_inicio;
    int Minuto_inicio;
    int Hora_fim;
    int Minuto_fim;
    char Status; /* '*' Indica que o registo está apagado */
} PESSOA;

プログラムの残りの部分 (.c ファイルに分割することができませんでした。コンパイラは、「このプロジェクトはまだビルドされていないようです。ビルドしますか?」という質問にループします。この問題でも私を助けることができます、私は感謝します):

#include "header.h"

void Mensagem(char *msg);

/*Lê os dados de um registo introduzidos pelo utilizador*/

void Ler_Pessoa(PESSOA *p){

    printf("Introduza o seu Nome (Primeiro e Ultimo) : "); gets(p->Nome);
    printf("Introduza o numero da sala que quer reservar:  "); scanf("%d", &p->Sala);
    printf("Introduza a partir de que horas quer reservar a sala (HH:MM): "); scanf("%2d:%2d",&p->Hora_inicio , &p->Minuto_inicio);
    printf("Introduza ate que horas quer reservar a sala (HH:MM): "); scanf("%2d:%2d", &p->Hora_fim , &p->Minuto_fim);
    p -> Status = ' ';
    fflush(stdin);
    system("cls");
}

void Mostrar_Pessoa(PESSOA p){
    printf("Nome          : %s\n",p.Nome);
    printf("Sala Reservada: %d\n",p.Sala);
    printf("Hora Inicial  : %2d:%2d",p.Hora_inicio , p.Minuto_inicio);
    printf("\tHora Final    : %2d:%2d\n",p.Hora_fim , p.Minuto_fim);
}

/*Adicionar uma Pessoa ao Arquivo */

void Adicionar_Pessoa(PESSOA p){
    fseek(fp , 0L , SEEK_END);
    if (fwrite(&p, sizeof(p), 1, fp)!=1)
        Mensagem("Adicionar Pessoa: Falhou a escrita  do Registo");
}

/* Coloca uma mensagem na tela */

void Mensagem(char *msg){
    printf(msg);
    getchar();
}
/*
 * Verifica se o Arquivo já existe. Se não existir, ele é criado.
 * Se já existir, abre-o em Modo de Leitura e Escrita (r+b)
 */

 void Inic(){
     fp = fopen(ARQ, "r+b"); /* Tenta Abrir*/
     if (fp==NULL){
         fp=fopen(ARQ, "w+b"); /*Cria o Arquivo*/
         if (fp==NULL){
             fprintf(stderr, "ERRO FATAL: Impossivel Criar Arquivo de Dados \n");
             exit(1);
         }
     }
 }

/*
 * Faz um Menu Simples com as opções do vector de Strings.
 * Seleciona a Opção, usando o primeiro caracter de cada string.
 * Devolve o primeiro caracter da opção
 */

 char Menu(char *Opcoes[]){
     int i;
     char ch;
     while(1){
         printf("\n");
         for (i=0 ; Opcoes[i] != NULL ; i++){
             printf("\n\t\t%s\n\n", Opcoes[i]);
         }
         printf("\n\n\t\tOpcao : ");
         ch = getchar(); fflush(stdin);
         system("cls");
         for (i=0 ; Opcoes[i]!=NULL ; i++){
             if (Opcoes[i][0]==ch)
                return ch;
         }
     }
 }

void Inserir_Pessoa(){
    PESSOA x;
    Ler_Pessoa(&x);
    Adicionar_Pessoa(x);
}

void Alterar_Pessoa(){
    PESSOA x;
    long int n_reg;
    char resp;
    printf("Qual o No. do Registo: ");
    scanf("%ld",&n_reg);
    fflush(stdin);
    if (fseek(fp, (n_reg-1)*sizeof(PESSOA),SEEK_SET)!=0){
        Mensagem("Registo Inexistente!!!");
        return;
    }
    if (fread(&x, sizeof(PESSOA),1,fp)!=1){
        Mensagem("Problemas na Leitura do Registo!!!");
        return;
    }
    if (x.Status == '*'){
        Mensagem("Um Registo Apagado nao pode ser alterado!!!\n\n");
        return;
    }
    printf("\n\nDados Actuais\n\n");
    Mostrar_Pessoa(x);
    printf("\n\nDeseja alterar a sua reserva? (s/n): "); resp = getchar();
    if(toupper (resp)!= 'S')
        return;
    fflush(stdin);
    printf("\n\nNovos Dados\n\n");
    Ler_Pessoa(&x);

    // Recuar um Registo no Arquivo//
    fseek(fp, -(long) sizeof(PESSOA), SEEK_CUR);
    // Reescrever o Registo;
    fwrite(&x, sizeof(PESSOA), 1, fp);
    fflush(fp); /*Despejar os dados no Disco*/
}

void Apagar_Pessoa(){
    PESSOA x;
    long int n_reg;
    char resp;

    printf("Qual o No. do Registo: ");
    scanf("%ld",&n_reg); fflush(stdin);
    if (fseek(fp,(n_reg-1)*sizeof(PESSOA),SEEK_SET)!=0){
        Mensagem ("Registo Inexistente!!!");
        return;
    }
    if (fread (&x, sizeof(PESSOA), 1 ,fp)!=1){
        Mensagem("Problemas na Leitura do Registo!!!");
        return;
    }
    if (x.Status=='*'){
        Mensagem("O Registo ja esta Apagado!!!\n\n");
        return;
    }
    printf("\n\nDados Actuais\n\n");
    Mostrar_Pessoa(x);
    printf("\n\nApagar o Registo (s/n)?: "); resp=getchar();
    fflush(stdin);
    if(toupper (resp)!= 'S')
        return;
    x.Status='*';

    fseek (fp, -(long) sizeof(PESSOA) , SEEK_CUR);
    fwrite(&x, sizeof(PESSOA), 1, fp);
    fflush(fp); /*Despejar os dados para o Disco*/
    system("cls");
}

void Listar_Pessoa(){
    long int N_Linhas = 0;
    PESSOA reg;
    rewind(fp);
    while(1){
        if (fread(&reg, sizeof(reg), 1 ,fp )!= 1) break; /*Sair do Ciclo*/
        if (reg.Status == '*') continue ; /*Passa ao próximo*/
        Mostrar_Pessoa(reg);
        N_Linhas++;
        if (N_Linhas %20==0)
            Mensagem("PRESSIONE <ENTER> para continuar . . .");
    }
    Mensagem("\n\nPRESSIONE <ENTER> para continuar . . ."); /*No fim da Listagem*/
}

void Pesquisar_HORAS(int ini, int fim){
    PESSOA reg;
    rewind (fp);

    while (fread(&reg, sizeof(PESSOA), 1, fp)){
        if (reg.Status != '*' && reg.Hora_inicio>=ini && reg.Hora_inicio <=fim)
            Mostrar_Pessoa(reg);
    }
    Mensagem("\n\nPRESSIONE <ENTER> para continuar . . . "); /* No fim da Listagem */
}

void Pesquisar_Nome(char *s){
    PESSOA reg;
    rewind(fp);

    while (fread(&reg , sizeof(PESSOA) , 1 , fp)){
        if (reg.Status!= '*' && strstr(reg.Nome,s))
            Mostrar_Pessoa(reg);
    }
    Mensagem ("\n\nPRESSIONE <ENTER> para continuar . . ."); /*No fim da Listagem*/
}

void main(){
    system("MODE con cols=100 lines=40");
    char Opcao;
    Inic();
    printf("Mini Projecto de Praticas de Programacao Procedimental\n");
    printf("Trabalho por:\n\nJoao Pedro Baptista de Oliveira, n%c 2010129867\nTomas Morgado de Carvalho Conceicao, n%c 2012138578\n\n",248,248);
    printf("----------------------------------------------------------------------------------------------------\n");
    time_t t;
    time(&t);
    printf("Data: %s\n", ctime(&t));
    printf("----------------------------------------------------------------------------------------------------\n");

    while ((Opcao =Menu(MainMenu))!=OP_SAIR){
        switch(Opcao){
            case OP_INSERIR: Inserir_Pessoa(); break;
            case OP_ALTERAR: Alterar_Pessoa(); break;
            case OP_APAGAR : Apagar_Pessoa(); break;
            case OP_LISTAR : Listar_Pessoa(); break;
            case OP_PESQUISAR:
            while ((Opcao=Menu(PesqMenu))!= OP_SAIR){
                switch (Opcao){
                    case OP_PESQ_HORAS:{
                        int n1,n2;
                        printf("Intervalo de horas: ");
                        scanf("%d",&n1);
                        printf("Ate: ");
                        scanf("%d",&n2);
                        fflush(stdin);
                        Pesquisar_HORAS(n1,n2); break;
                        }
                    case OP_PESQ_NOME:{
                        char string[BUFSIZ +1];
                        printf("Introduza o nome que quer pesquisar: ");
                        gets(string); fflush(stdin);
                        Pesquisar_Nome(string);
                    }
                }
            }
        }
    }
    printf("\n\t\tDepartamento de Engenharia Informatica - Universidade de Coimbra\n\n");
}
4

1 に答える 1

0

この情報をどのように保存しているかはわかりませんが (言語またはストレージ コードが投稿されていない可能性があります)、質問のタイトルはリンクされたリストを示唆しています。

この問題に対するかなり効率的な (メモリとパフォーマンスの両方の観点から) 解決策は、ハッシュ テーブルのキーが部屋の一意の識別子 (番号/ID) であるハッシュ テーブル (バケットを含む) を用意し、それぞれに値を格納することです。ハッシュテーブルのスロットは、部屋をリクエストしている人々の構造です (おそらくあなたのPESSOA構造体)。

次に、3 つの主なシナリオがあります。
- ハッシュ テーブル エントリiが空 (値/バケットなし) の場合、部屋は空いています。
- ハッシュ テーブル エントリの最初の値/バケットiは、現在ルームにいる人です。
- ハッシュ テーブル エントリの残りの値/バケットはi、部屋を待っている人です。

人を割り当てるために部屋の完全なリストを保存する必要がなく、特定の部屋を見つけるのに一定の時間がかかるため、これは効率的です。

新しい人が「事前予約」したい場合は、その情報を取得し、部屋 ID でハッシュ テーブル エントリにジャンプし、値/バケット リストに追加するだけです。人が部屋を放棄すると、部屋 ID によってハッシュ テーブル エントリにジャンプし、最初の値/バケットを削除します。基本的に、次の人を最初の値/バケットに上げます。

人の名前に基づいて部屋を見つける必要がある場合は、キーが人の名前で、値/バケットが同じ情報の構造体である 2 番目のハッシュ テーブルを維持できます。これには、部屋 ID も含まれている必要があります。このハッシュ テーブルのキーは、名前の衝突に対するバケットもサポートしている限り、一意である必要はありません。

于 2013-06-12T02:24:55.027 に答える