簡體   English   中英

緩沖區溢出或其他

[英]Buffer overflow or something else

我正在創建一個有關座位預定的程序。 我被要求對某些變量使用unsigned short和unsigned int,因此這就是為什么要這樣設置它們的原因。 我有一個可以正常運行的程序。 但是,當我在函數內部傳輸所有內容時,一切似乎都可以正常工作,但是在我的結構內部, 奇怪的值開始被保存到整個位置 ..我只想保存文件的值(從第2行->結尾)文件)。 因為我有一個要初始化的結構,所以我必須先閱讀txt文件和數量的座位,因此我在函數(本地var)內部和主體中聲明了此變量(passenger)2次。問題? 如果我不使用任何功能,一切正常!

所以有問題的代碼:

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

int i,j,numberofseats,temp;
char platenr[8],selection,buff[60];
char firstname[20];
char lastname[20];
char phone[11];
char *p;
typedef struct
    {
    char fullname[40];
    unsigned short phonenr[10];
    unsigned int seatnr;
    }PASSENGERS;

void readfile( void)
{
    FILE *businfo;
    businfo = fopen ("bus.txt","r");
    if (businfo == NULL)
        {
        printf("Error Opening File, check if file bus.txt is present");
        exit(1);}
    else
        {
        fscanf(businfo,"%s %d",platenr, &numberofseats);
        printf("Bus Licence plate Nr is: %s and number of seats is: %d", platenr, numberofseats);
        PASSENGERS passenger[numberofseats];
        for (j=0;j<numberofseats;j++)
            {passenger[j].seatnr=j+1;
            strcpy(passenger[j].fullname,"\0");
            }
        while (fgets(buff,sizeof(buff),businfo)!=0)
            {sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
            strcpy(passenger[temp-1].fullname,firstname);
            strcat (passenger[temp-1].fullname, " ");
            strcat(passenger[temp-1].fullname,lastname);
            printf("%s",passenger[temp-1].fullname);
            i=0;
            for (p=phone;*p!='\0';p++)
                {
                (passenger[temp-1].phonenr[i])=*p -'0';
                i++;
                }
            }
           }
}

int main(void)
{
readfile();
PASSENGERS passenger[numberofseats];

問題是您在函數readfile()中聲明了一個本地數組,並且一旦該函數終止,它就會丟失。 您需要能夠將更改返回給main() 為此,您有一些選擇。 一種是可以在main()聲明該數組,然后將函數更改為void readfile(PASSENGERS passenger[]) 在這種情況下,您將執行以下操作:

int main()
{
PASSENGERS passenger[numberofseats];
readfile(passenger);
// more code

基本上,您將傳遞一個指向存儲在數組中元素的內存位置的指針,該指針位於main()本地,該函數將填充數組,有效地返回更改。

另一種選擇是在函數中動態分配數組(帶有malloc()系列),並使其返回類似PASSENGERS *readfile(void)的指針。 如果在編譯時未知席位數,則此選項可能更合適,因此您需要在必要時動態增大或縮小數組。 但是,此選項將使您省去手動管理內存的負擔,例如在完成后free()分配已分配的內存。

因為您說您將從文件中讀取numberofseats ,所以后者是更好的主意,因此您的代碼將如下所示:

PASSENGERS *readfile(void)
{ 
   FILE *businfo;
   PASSENGERS *passenger;
   businfo = fopen ("bus.txt","r");
   // do the checks, read the numberofseats
   passenger = malloc(numberofseats * sizeof *passenger);
   // read the values, fill the array
   fclose(businfo); // do not forget to close the file
   return passenger;
}

int main()
{
    PASSENGERS *passenger = readfile();
    // more code
    free(passenger);
    return 0;
}

函數foo名為x的變量與函數bar名為y的變量無關。 換句話說: passengermainpassengerreadfile是不同的變量。 更改一個不會影響另一個。

您想要的可能更像這樣:

int main(void)
{
    PASSENGERS passenger[numberofseats];
    readfile(passenger);
             ^^^^^^^^^
             Pass array as a pointer
    ....
}

void readfile(PASSENGERS* passenger)
{
    ....

    // REMOVE THIS: PASSENGERS passenger[numberofseats];


}

在該通知旁邊:

// Global variables gets zero initialized
int i,j,numberofseats,temp;
        ^^^^^^^^^^^^
        Becomes zero at start up

但您仍然可以在main中使用它:

PASSENGERS passenger[numberofseats];

那可能不是您真正想要的。

由於您嘗試讀取該函數中的座位數,因此它確實暗示您要使用動態內存分配。 喜歡:

PASSENGERS* readfile()
{
     .....
     .....

     PASSENGERS* p = malloc(numberofseats * sizeof(PASSENGERS));

     .....
     .....
     return p;
}

int main(void)
{
    PASSENGERS* passenger = readfile();
     .....
     .....
     free(passenger);
     return 0;
}

如果您不希望動態分配 ,則必須將numberofseats的輸入移動到main ,這樣才能在聲明數組之前完成。

好的,所以在開始動態分配之前,我要做的是在main開頭指定最大席位數,然后從此處完成我的代碼,如下所示。 我在第43、109行中有2條警告消息,似乎無法修復。

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

int i,j,numberofseats,temp;
char platenr[8],selection;
char firstname[20],lastname[20];
char phone[11];
char *p;
typedef struct
    {
    char fullname[40];
    unsigned short phonenr[10];
    unsigned int seatnr;
    }PASSENGERS;

void readfile(PASSENGERS passenger[])
{   char buff[60];
    FILE *businfo;
    businfo = fopen ("bus.txt","r");
    if (businfo == NULL)
        {
        printf("Error Opening File, check if file bus.txt is present");
        exit(1);}
    else
        {
        fscanf(businfo,"%s %d",platenr, &numberofseats);
        printf("Bus Licence plate Nr is: %s, and Number of Seats is: %d.", platenr, numberofseats);

        for (j=0;j<numberofseats;j++)
            {passenger[j].seatnr=j+1;
            strcpy(passenger[j].fullname,"\0");
            }
        while (fgets(buff,sizeof(buff),businfo)!=0)
            {sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
            strcpy(passenger[temp-1].fullname,firstname);
            strcat (passenger[temp-1].fullname, " ");
            strcat(passenger[temp-1].fullname,lastname);
            i=0;
            for (p=phone;*p!='\0';p++)
                {
                (passenger[temp-1].phonenr[i])=*p -'0';
                i++;
                }
            }
           }
}

void countfreeseats(PASSENGERS passenger[]){
    int freeseats = 0;
        for (j=0; j<numberofseats; j++)
            {
            strcmp(passenger[j].fullname,"\0")==0 ? freeseats = freeseats + 1 : freeseats ;}
            printf ("There are %d Free Seats in this Bus. \n", freeseats);
            printf("Seats that are Available are:\n");

        for (j=0; j<numberofseats; j++)
            {if (strcmp(passenger[j].fullname,"\0")==0)
                printf ("%u\n", passenger[j].seatnr);
            }
        freeseats = 0;
        }

void changeData(PASSENGERS *target){
    unsigned short tempdigit;
    printf("Enter Passenger's first name:");
    scanf("%s",firstname);
    printf("Enter Passenger's last name:");
    scanf("%s",lastname);
    strcpy(target->fullname,firstname);
    strcat (target->fullname, " ");
    strcat(target->fullname,lastname);
    printf("Enter Passenger's phone Nr:");
    scanf("%s",phone);
    i=0;
    for (p=phone;*p!='\0';p++)
        {
        (target->phonenr[i])=*p -'0';
        i++;
        }


    }

void searchpassenger(PASSENGERS passenger[], char selection)
{       char tempsel,tmpfirst[20],tmplast[20];
        unsigned short tempphone[10];
     if (selection == '1')
        {   printf("Enter Passenger's first name:");
            scanf("%s",tmpfirst);
            printf("Enter Passenger's last name:");
            scanf("%s",tmplast);
            strcat (tmpfirst, " ");
            strcat(tmpfirst,tmplast);
            for (j=0;j<numberofseats;j++)
            if (strcmp(passenger[j].fullname,tmpfirst)==0)
                printf ("Passenger %s has Seat Nr #: %u\n",tmpfirst,passenger[j].seatnr);
        }
        else if (selection == '2')
        {   printf("Enter Passenger's Phone Nr:");
            scanf("%s",phone);
            i=0;
            for (p=phone;*p!='\0';p++)
            {
            (tempphone[i])=*p -'0';
            i++;
            }
            for (j=0;j<numberofseats;j++)
            {if (strcmp(tempphone,passenger[j].phonenr)==0)
                printf("Passenger %s has Seat Nr %hd already Booked",passenger[j].fullname,passenger[j].seatnr);
            }
        }
        }



void cancelSeat(PASSENGERS *target){
    strcpy(target->fullname,"\0");
    for (i=0;i<10;i++)
    target->phonenr[i]=0;
    printf("Seat Nr %d is now Free",temp);

    }

void showList(PASSENGERS passenger[])
{
 printf("The following Seats are Booked: \n Name, PhoneNr, SeatNr\n\n");                                    /*Emfanisi minimatos*/
        for (i=0; i<numberofseats; i++)
            if (strcmp(passenger[i].fullname,"\0")!=0)
            {
                printf("%s, ",passenger[i].fullname);
                for (j=0;j<10;j++)
                {printf("%hu",passenger[i].phonenr[j]);}

                printf(", %u\n",passenger[i].seatnr);
            }
}


void writeFile(PASSENGERS passenger[])
   {
    FILE * output;                                      /* Dilosi onomatos arxeiou */
    output = fopen("output.txt","w");    /*dimiourgia i eggrafi pano se iparxon arxeio me onoma output.txt,  mesw tis parametrou w*/
    fprintf(output,"%s %d \n",platenr,numberofseats);    /* mesw tis fprintf eksagogi pinakidas kai epikefalidas "Diagramma leoforeiou" sto arxeio output.txt. Allagi grammis opou xreiazetai*/
    for (i=0; i<numberofseats; i++)
        {if (strcmp(passenger[i].fullname,"\0")!=0)
        {
            fprintf(output,"%s ",passenger[i].fullname);
            fprintf(output,"%u ",passenger[i].seatnr);
            for (j=0;j<10;j++)
            fprintf(output,"%hu",passenger[i].phonenr[j]);
            fprintf(output,"%s","\n");
        }
        }
        fclose(output);                                     /* Kleisimo arxeiou*/
        printf("File Saved as Output.txt");
   }

int main(void)
{


PASSENGERS passenger[53];
readfile(passenger);

    do{
    printf("\n\nNeo Sistima Katagrafis Thesewn Leoforeiou\n");
    printf("Please make a selection:\n\n");
    printf("0. Exit\n");
    printf("1. Empty Seats \n");
    printf("2. Book Specific Seat \n");
    printf("3. Advanced Search of Booked Seats\n");
    printf("4. Cancel Seat Booking\n");
    printf("5. Show List of Booked Seats\n");
    scanf(" %c",&selection);

    if (selection=='1')
  countfreeseats(passenger);

    else if (selection=='2')
        {
        printf("Please give seat nr (between 1 and %d) that you want to book:\n", numberofseats);
        scanf("%d",&temp);
        if (temp >numberofseats || temp <= 0)
            {printf("Error: Seat nr should be between 1 and %d", numberofseats);}
         else if (strcmp(passenger[temp-1].fullname,"\0")!=0)
            printf("Error: Seat is already booked");

        else
        changeData(&passenger[temp-1]);

        }

 else if (selection=='3')
        {
        char tempsel;
        printf("Do you want to search with Name (1) or Phone Nr (2)?\n");
        scanf(" %c",&tempsel);
        searchpassenger(passenger,tempsel);
        }





    else if (selection=='4')
        {
        printf("Please give Seat Nr (between 1 and %d) that you want to Cancel Booking:\n", numberofseats);
        scanf("%d",&temp);
        if (temp >numberofseats || temp <= 0)
            {printf("Error: Seat nr should be between 1 and %d", numberofseats);}
         else if (strcmp(passenger[temp-1].fullname,"\0")==0)
            printf("Error: Seat is already free");

        else
        cancelSeat(&passenger[temp-1]);

        }

    else if (selection=='5')                                                            /*Menu 6 - Emfanisi listas kratimenon thesewn taksinomimenon kata ayksonta arithmo*/
        {
            showList(passenger);

        }



    } while (selection!='0');
    {
    writeFile(passenger);
    }


    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM