2013-12-12 84 views
0
#include <stdio.h> 
#include <stdlib.h> 

struct packets 
{ 
int source, destination, type, port; 
char data[50]; 
}; 

int addpacket(int *, struct packets *); 
void listpackets(int , struct packets *); 
void save(int, struct packets *); 

int main() 
{ 

struct packets *info; 
char choice; 
int records = 0; 

info = malloc(sizeof(struct packets)); 

do 
{ 
    puts("\n1. Add Packets\n");    //Menu with list of options. 
    puts("\n2. List all saved packets\n"); 
    puts("\n3. Save packets\n"); 
    puts("\n4. Clear all packet information\n"); 
    puts("\nx. Exit the programme\n"); 
    printf("\nPlease select your option: \n"); 
    scanf("%c", &choice);  //Reading the menu option entered. 

     if(choice == '\n')  //if the choice is the new line character read again. 
      scanf("%c", &choice); 

    switch (choice) 
     { 
      case '1': system("cls"); //Clears the screen 
         puts("\nYou have selected to Add packet information, follow on-screen instructions\n"); records = addpacket(&records, info); //calls function "addpacket" and sents a copy of records and pointer to struct info. 
         break; 
      case '2': system("cls"); //clears the screen 
         puts("\nAll packet information will now be displayed on the screen\n"); listpackets(records, info); 
         break; 
      case '3': system("cls"); //clears the screen 
         puts("\nAll packet information will now be saved\n"); save(records, info); 
         break; 
      case '4': system("cls"); //clears the screen 
         puts("\nAll packet information will now be deleted\n"); 
         break; 
      case 'x': puts("\nThe proframme will now close, Goodbye!\n"); //closes the programme. 
         break; 
      default : puts("\nIncorrect option, please select from menu\n"); //used if none of the menu options have been selected. 
         break; 
     } 
}while (choice != 'x'); //The programme will run until the "x" option is entered at the menu. 
return 0; 
} 

int addpacket(int *recCount, struct packets *info) 
{ 
int validation = 0; 
int stringlength = 0; 
int i = 0; 
char datatest[50]; 

do{ 
     printf("\nPlease enter the source address: \n"); 
     if (scanf("%i", &info[*recCount].source) == 1) 
     { 
      validation = 1; 
     } 
     else{ 
       validation = 0; 
       getchar(); 
       puts("\nThis is not a valid source address!\n"); 
      } 
    }while (validation != 1); 

    printf("\nPlease enter destination address: \n"); 
    scanf("%i", &info[*recCount].destination); //pointer to the destination address. 

printf("\nPlease enter type: \n"); 
scanf("%i", &info[*recCount].type); // pointer to the address of the type. 
printf("\nPlease enter the port: \n"); 
scanf("%i", &info[*recCount].port); //pointer to the port address. 
printf("\nPlease enter data: \n"); 
scanf("%s", info[*recCount].data); //pointer to the data address. 

*recCount ++; //adding one to record count 

return *recCount; // returning the record count which will the be copied into records in main. 
} 

void listpackets(int records, struct packets *info) 
{ 
int i; 
for (i=0; i<records; i++){ 
    printf("\nSource address: %i\n", info[i].source); //Displays the source address. 
    printf("\nDestination address: %i\n", info[i].destination); //Displays the destination address. 
    printf("\nType: %i\n", info[i].type); //Displays the type. 
    printf("\nPort: %i\n", info[i].port); //displays the port. 
    printf("\nData: %s\n", info[i].data); //displays the data information. 
} 
} 

void save(int records, struct packets *info) 
{ 
FILE *savedfile; 
char filename[30] = { '\0'}; //this is where the file name will be stored. 
int i; 

printf("\nPlease enter a filename: \n"); 
scanf("%s", filename); 

if ((savedfile = fopen(filename, "w")) == NULL) 
{ 
    printf("\n%s could not be opened\n", filename); 
    exit(1); 
} 
else 
{ 
    for (i=0; i<records; i++) 
     fprintf(savedfile, "%i %i %i %i %s", info[i].source, info[i].destination, info[i].type, info[i].port, info[i].data); 
} 
fclose(savedfile); 
} 

我保存和listpacket函數崩潰時,我打電話給他們。這是工作較早,直到我介紹malloc到我的程序旁邊一些基本的輸入驗證。我認爲這可能是一個問題與指針。我的程序編譯沒有錯誤/警告,所以我堅持什麼問題可能是。隨時嘗試編譯編程,看看我的意思。任何幫助將不勝感激,因爲我正在努力解決這個問題。爲什麼我的功能會使程序崩潰?

+1

您是否嘗試過調試程序?這應該是第一步。 –

+0

編譯好沒有任何錯誤或警告,這就是爲什麼即時通訊努力瞭解問題是什麼。 – user3095526

回答

2

您正在使用malloc()爲單個struct packets分配空間。您稍後將您的info指針看作是這樣的結構的數組......您將超出您分配空間的邊界。

詳細圍繞一個潛在方法(將自動增加你的陣列):

// change the signature of addpacket(): 
int addpacket(int *, struct packets **); 

... 

// change how add packet gets called: 
    records = addpacket(&records, &info); 

// change addpacket(): 
int addpacket(int *recCount, struct packets **callerinfo) 
{ 
    ... 
    // grow the buffer by one record 
    *callerinfo = realloc(*callerinfo, (*recCount + 1) * sizeof (**callerinfo)); 
    struct packets *info = *callerinfo; // to avoid changing other code 
    ... no other changes, just the rest of your routine 
} 

這將接近,不徹底解決這個問題。

完整的方案,爲我工作:

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

struct packets 
{ 
int source, destination, type, port; 
char data[50]; 
}; 

int addpacket(int *, struct packets **); 
void listpackets(int , struct packets *); 
void save(int, struct packets *); 

int main() 
{ 
    struct packets *info; 
    char choice; 
    int records = 0; 

    info = malloc(sizeof(struct packets)); 

    do 
    { 
     puts("\n1. Add Packets\n");    //Menu with list of options. 
     puts("\n2. List all saved packets\n"); 
     puts("\n3. Save packets\n"); 
     puts("\n4. Clear all packet information\n"); 
     puts("\nx. Exit the programme\n"); 
     printf("\nPlease select your option: \n"); 
     scanf("%c", &choice);  //Reading the menu option entered. 

     if(choice == '\n')  //if the choice is the new line character read again. 
      scanf("%c", &choice); 

      switch (choice) 
      { 
      case '1': system("cls"); //Clears the screen 
         puts("\nYou have selected to Add packet information, follow on-screen instructions\n"); records = addpacket(&records, &info); //calls function "addpacket" and sents a copy of records and pointer to struct info. 
         break; 
      case '2': system("cls"); //clears the screen 
         puts("\nAll packet information will now be displayed on the screen\n"); listpackets(records, info); 
         break; 
      case '3': system("cls"); //clears the screen 
         puts("\nAll packet information will now be saved\n"); save(records, info); 
         break; 
      case '4': system("cls"); //clears the screen 
         puts("\nAll packet information will now be deleted\n"); 
         break; 
      case 'x': puts("\nThe proframme will now close, Goodbye!\n"); //closes the programme. 
         break; 
      default : puts("\nIncorrect option, please select from menu\n"); //used if none of the menu options have been selected. 
         break; 
      } 
     }while (choice != 'x'); //The programme will run until the "x" option is entered at the menu. 
    return 0; 
} 

int addpacket(int *recCount, struct packets **callerinfo) 
{ 
    int validation = 0; 
    int stringlength = 0; 
    int i = 0; 
    char datatest[50]; 

    *callerinfo = realloc(*callerinfo, (*recCount + 1) * sizeof (**callerinfo)); 
    struct packets *info = *callerinfo; // to avoid changing other code 

    do{ 
     printf("\nPlease enter the source address: \n"); 
     if (scanf("%i", &info[*recCount].source) == 1) 
     { 
      validation = 1; 
     } 
     else{ 
       validation = 0; 
       getchar(); 
       puts("\nThis is not a valid source address!\n"); 
      } 
    }while (validation != 1); 

    printf("\nPlease enter destination address: \n"); 
    scanf("%i", &info[*recCount].destination); //pointer to the destination address. 

    printf("\nPlease enter type: \n"); 
    scanf("%i", &info[*recCount].type); // pointer to the address of the type. 
    printf("\nPlease enter the port: \n"); 
    scanf("%i", &info[*recCount].port); //pointer to the port address. 
    printf("\nPlease enter data: \n"); 
    scanf("%s", info[*recCount].data); //pointer to the data address. 

    ++(*recCount); //adding one to record count 

    return *recCount; // returning the record count which will the be copied into records in main. 
} 

void listpackets(int records, struct packets *info) 
{ 
    int i; 
    for (i=0; i<records; i++){ 
     printf("\nSource address: %i\n", info[i].source); //Displays the source address. 
     printf("\nDestination address: %i\n", info[i].destination); //Displays the destination address. 
     printf("\nType: %i\n", info[i].type); //Displays the type. 
     printf("\nPort: %i\n", info[i].port); //displays the port. 
     printf("\nData: %s\n", info[i].data); //displays the data information. 
    } 
} 

void save(int records, struct packets *info) 
{ 
    FILE *savedfile; 
    char filename[30] = { '\0'}; //this is where the file name will be stored. 
    int i; 

    printf("\nPlease enter a filename: \n"); 
    scanf("%s", filename); 

    if ((savedfile = fopen(filename, "w")) == NULL) 
    { 
     printf("\n%s could not be opened\n", filename); 
     exit(1); 
    } 
    else 
    { 
     for (i=0; i<records; i++) 
      fprintf(savedfile, "%i %i %i %i %s\n", info[i].source, info[i].destination, info[i].type, info[i].port, info[i].data); 
    } 
    fclose(savedfile); 
} 
+0

那麼我該如何解決這個問題?我需要使用它,所以它的行爲,而不是一個數組,這就是爲什麼我第一次使用malloc函數。你可以給任何幫助編號非常感謝。 – user3095526

+0

如果_n_是你需要的數組元素的數量,'info = malloc(n * sizeof(struct packets));'會做。既然你事先不知道記錄的數量,你總是可以爲malloc留出足夠的空間用於某些默認數量的記錄(也許是一個),並且調用'realloc()'調用增長緩衝區 - 但這可能會導致性能問題如果你必須經常這樣做。同樣要在addpacket()中做到這一點,你需要傳遞信息的地址,以便addpacket()可以更新main()的信息。 – mah

+0

所以只是出於好奇,如果我要使用改變這個realloc()方法我將如何去呢?也可以調用者更改爲任何內容,還是必須保持原樣? – user3095526

相關問題