【问题标题】:C Programming - Airline Reservation System - Why isn't my save file function working?C 编程 - 航空公司预订系统 - 为什么我的保存文件功能不起作用?
【发布时间】:2021-09-14 06:55:43
【问题描述】:
#include <stdio.h>  
#include <string.h>
#include <stdlib.h>
#include <conio.h>


struct airlines{
    char name[50];
    char origin[50];
    char destination[50];
    char dtime[50];
    char atime[50];
    char age[50];
}
struct airlines *p;
typedef struct airlines lines[50];

void reserve(struct airlines *p);
void edit(struct airlines *p, int newent);
void search(lines *p, int newent);
void AgeS();
void OriginS();
void DestinationS();
void deletecus(lines *p, int newent, int del);
void display(struct airlines *p, int newent);
void displayall(lines *p, int newent);
void saveFile(struct airlines *p);


int main(){
    
    int sel;
    int newent=0 , editcust, del;
    lines airlinesnew;
    begin = stream = NULL;
    
    do {
    printf("\n\n\t*******************************************************************");
    printf("\n\t                  BREEZE AIRLINES ONLINE BOOKING                 ");
    printf("\n\t*******************************************************************");
    printf("\n\n\t\t1. Reserve a seat");
    printf("\n\n\t\t2. Edit a reservation");
    printf("\n\n\t\t3. Search existing reservations");
    printf("\n\n\t\t4. Delete existing reservations");
    printf("\n\n\t\t5. Display existing reservations");
    printf("\n\n\t\t6. Exit program");
    printf("\n\n\t\tWhich option would you like to choose?: ", &sel);
    scanf("%d", &sel);
    system("cls");
    switch (sel){
        case 1:
            reserve(&airlinesnew[newent]);
            newent++;
            break;
        case 2:
            displayall(&airlinesnew, newent);
            printf("\nWhich entry would you like to edit?: ");
            scanf("%d", &editcust);
            edit(&airlinesnew[editcust-1], newent);
            break;
        case 3:
            search(&airlinesnew, newent);
            break;
        case 4:
            displayall(&airlinesnew, newent);
            printf("Which entry do you want to delete?: ");
            scanf("%d", &del);
            deletecus(&airlinesnew, newent, del);
            newent--;
            break;
        case 5:
            displayall(&airlinesnew, newent);
            break;
        case 6:
            saveFile(&airlinesnew[newent]);
            break;
        default:
            printf("\nInvalid Choice ");
            printf("\nPlease select only from 1-6 ");
    }
    } while (sel != 6);
    return 0;
}

void reserve(struct airlines *p){
    
    printf("\n\tReservation Details");
    printf("\n\tName: ");
    scanf(" %[^\n]s", &(*p).name);
    printf("\n\tAge: ");
    scanf(" %[^\n]s", &(*p).age);
    printf("\n\tOrigin: ");
    scanf(" %[^\n]s", &(*p).origin);
    printf("\n\tDestination: ");
    scanf(" %[^\n]s", &(*p).destination);
    printf("\n\tTime of departure (use military time): ");
    scanf(" %[^\n]s", &(*p).dtime);
    printf("\n\tTime of arrival (use military time): ");
    scanf(" %[^\n]s", &(*p).atime);
    system("cls");
}

void edit(struct airlines *p, int newent){
    
    char nname[50];
    char nage[50];
    char norigin[50];
    char ndestination[50];
    char ndtime[50];
    char natime[50];

    display( &(*p), newent-1 );
    printf("\nEditing the entry: ");
    
    printf("\n\t New Name: ");
    scanf(" %[^\n]s", &nname );
    strcpy( (*p).name,  nname );
    
    printf("\n\t New age: ");
    scanf(" %d", &nage );
    strcpy( (*p).age,  nage );
    
    printf("\n\t New Origin: ");
    scanf(" %[^\n]s", &norigin );
    strcpy( (*p).origin,  norigin );
    
    printf("\n\t New Destination: ");
    scanf(" %[^\n]s", &ndestination );
    strcpy( (*p).destination,  ndestination );
    
    printf("\n\t New time of departure (use military time): ");
    scanf(" %[^\n]s", &ndtime );
    strcpy( (*p).dtime,  ndtime );
    
    printf("\n\t New time of arrival (use military time): ");
    scanf(" %[^\n]s", &natime );
    strcpy( (*p).atime,  natime );
    system("cls");
}


void search(lines *p, int newent){
    int sel1;
    char Ageint[50];
    char Originint[50];
    char Destinationint[50];
    
    do {
        printf ("\nWhich heading would you like to search:");
        printf ("\n1. Age");
        printf ("\n2. Origin");
        printf ("\n3. Destination");
        printf ("\n4. Return");
        printf ("\nHeading number: ");
        scanf ("%d", &sel1);

        switch (sel1)
        {
        case 1: 
        printf ("\nEnter age: ");
        scanf ("%d", &Ageint);
        for (int i = 0; i < newent; i++){
        if( strcmp( (*p)[i].age, Ageint ) == 0 ){
            display( &(*p)[i] , i );
                }
            }
        break;
        case 2:
        printf ("\nEnter origin: ");
        scanf(" %[^\n]s", &Originint );
        for (int i = 0; i < newent; i++){
        if( strcmp( (*p)[i].origin, Originint ) == 0 ){
            display( &(*p)[i] , i );
                }
            }
        break;
        case 3:
        printf ("\nEnter destination: ");
        scanf(" %[^\n]s", &Destinationint );
        for (int i = 0; i < newent; i++){
        if( strcmp( (*p)[i].destination, Destinationint ) == 0 ){
            display( &(*p)[i] , i );
                }
            }
        break;
        case 4:
            main();
        default:
            printf("\nInvalid Choice ");
            printf("\nPlease select only from 1-4 ");
        }
    } while (sel1 != 4);
}

void deletecus(lines *p, int newent, int del){
    int i;
    
    for( i = del-1; i < newent; i++ ){
        strcpy( (*p)[i].name,  (*p)[i+1].name );
        strcpy( (*p)[i].age,  (*p)[i+1].age );
        strcpy( (*p)[i].origin,  (*p)[i+1].origin );
        strcpy( (*p)[i].destination,(*p)[i+1].destination);
        strcpy( (*p)[i].dtime,  (*p)[i+1].dtime );
        strcpy( (*p)[i].atime,  (*p)[i+1].atime );
    }
}

void display(struct airlines *p, int newent){
    printf("\nReservation list:");
    printf("\n");
    printf("Passport No. %d\n", newent+1);
    printf("Name: %s", (*p).name);
    printf("\n");
    printf("Age: %s", (*p).age);
    printf("\n");
    printf("Origin: %s", (*p).origin);
    printf("\n");
    printf("Destination: %s", (*p).destination);
    printf("\n");
    printf("Time of departure: %s", (*p).dtime);
    printf("\n");
    printf("Time of Arrival: %s", (*p).atime);
    printf("\n");
}

void displayall(lines *p, int newent){
    int i;
    for (i=0;i<newent;i++){
        display(&(*p)[i], i);
    }
}

void saveFile(struct airlines *p)
{
    FILE *fptr;
    fptr = fopen("reserved_seats", "a+");
    
    if(!fptr)
    {
        printf("Error\n");
        return;
    }

    fprintf(fptr, "%15s", (*p).name);
    fprintf(fptr, "%15s", (*p).age);
    fprintf(fptr, "%15s", (*p).origin);
    fprintf(fptr, "%15s", (*p).destination);
    fprintf(fptr, "%15s", (*p).dtime);
    fprintf(fptr, "%15s", (*p).atime);
    fprintf(fptr, "\n");
    
    printf("\nSaved successfully");
    fclose(fptr);
}







这是我当前的航空公司预订系统代码。所需的功能之一是保存输入的数据,这样当程序关闭时,它仍然会显示保存的数据,因为它将访问保存的文件。但是在执行保存功能时,程序确实创建了一个文件,但是它没有输入数据,它只是一个没有任何内容的文件。请帮忙

【问题讨论】:

  • 无关:(*p).member也可以写成p-&gt;member。

标签: c struct


【解决方案1】:

当您调用saveFile() 时,newent 索引未指向数组中的最后一个条目;它指向数组中的第一个“空”空间。

您需要指定要保存的索引...或者,如果您信任您的用户,只需保存newent - 1

case 6:
    if (newent > 0) saveFile(&airlinesnew[newent - 1]); // save the last entry
    break;

要保存所有条目,您需要一个循环。要么调用你的函数(可能重命名saveEntry())newent 次,要么使用一个新函数(saveArray())来获取整个数组和有效元素的数量

    case 6:
        // assuming newent has the number of valid entries
        for (int i = 0; i < newent; i++) {
            saveEntry(&airlinesnew[i]);
        }

或

void saveArray(struct airlines *a, int n); // prototype

// ...

    case 6:
        // assuming newent has the number of valid entries
        saveArray(airlinesnew, newent);
        break;

// ...

void saveArray(struct airlines *a, int n) {
    // open file
    for (int i = 0; i < n; i++) {
        // write a[i] to file
    }
    // close file
}

【讨论】:

  • 可能还想指出,即使在修复之后saveFile 也根本不够用,因为它只尝试保存一个条目而不是整个有效数据。
  • 是的@kaylum,saveFile() 措辞不当(...或实施不当)
  • 感谢大家的帮助,我确实意识到它确实试图只保存一个条目,我该如何更改它以保存整个有效数据?我真的很陌生,非常需要帮助,非常感谢。
  • @BuggritZ:添加了选项以将其全部保存在我的答案中。
  • 最简单的方法是始终读取和写入整个文件(可能创建备份)。或者,使用fseek() 将下一个读/写定位在正确的位置(对于文本文件,如果很难找到)。或者...使用适当的数据库。
【解决方案2】:

您的代码中有一些需要解决的问题:


第一:

正如 cmets 中已经提到的,您保存/加载数据的方法很糟糕。 程序启动后读取整个文件,将其加载到数据结构中,并在程序停止时将其写回。为此定义两个函数:

int count_file_lines(FILE *stream)
{
    int n;
    for (n = 0; EOF != (scanf("%*[^\n]"), scanf("%*c")); ++n)
        ;
    
    rewind(stream);
    return n;
}
int load_file(const char *filename, char **lines, int *n)
{
    FILE *stream = fopen(filename, "r");
    if (!stream)
        return 0;
    
    *n = count_file_lines(stream);
    lines = malloc(*n * sizeof *lines);
    if (!lines) {
        fclose(stream);
        return 0;
    }
    
    char line[1024]; // Can be more
    int i = 0;
    
    while(fgets(line, sizeof line, stream)) {
        line[strcspn(line, "\n")] = '\0'; // Remove \n read by fgets()
        lines[i++] = strdup(line);
    }
    
    fclose(stream);
    return 1;
}
int save_file(const char *filename, char **lines, int n)
{
    FILE *stream = fopen(filename, "w");
    if (!stream)
        return 0;
    
    for (int i = 0; i < n; i++)
        fprintf(stream, "%s\n", lines[i]);
    
    fclose(stream);
    return 1;
}

然后使用sscanf()进行解析。


第二:

不要使用scanf() 来读取输入。它非常容易出错。请改用fgets() 和sscanf() 进行解析:

fgets(string, sizeof string, stdin));
string[strcspn(string, "\n")] = '\0'; // Replace '\n' with '\0'

if (sscanf(string, "%d", &intval) != 1) { // Get an int and check for errors
    // Error code
}

您的主要代码应如下所示:

int main()
{
    do {
        // Print menu
        
        // Read selection
        
        // If selection is valid, load_file()
        
        // switch-case ...
        // case 6: save_file()
    } while (sel != 6);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-08
    • 2016-07-19
    • 1970-01-01
    • 2021-05-01
    • 2019-07-23
    • 2020-05-05
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多