-1

私はSongと呼ばれる構造体を持つこの割り当てを持っています。この構造体では、ソング構造体を持つ配列への動的割り当てを行っています。C - 動的割り当ては既存のデータを上書きしますか?

私は構造体の配列に別のソングを追加しようとしているときにこの問題が発生します。 ケース4を使用して別のソングを配列に追加すると、struct Songの変数の値がゴミの値に変更されます。なぜそれがそうするのか分かりません。予想される結果は、配列が展開してソングにソングを追加することです。 ケース4を使用した後にaSongアレイを印刷すると、トラブルが始まる場所です。

コンパイルエラーは発生しません。プログラムはちょうどゴミ値を表示します。

#pragma warning(disable : 4996) 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include "lab3.h" 

//Global variables 
struct Song *aSong; 
int howMany = 0; 

int menu(struct Song *songs) { 

    int answer = 0; 

    printf("Choose from the menu: \n"); 
    printf("1. Song menu.\n"); 
    printf("2. Exit\n"); 
    scanf("%d", &answer); 

    switch (answer) 
    { 
    case 1: 

     printf("Choose from the menu: \n"); 
     printf("1. Add song. \n"); 
     printf("2. Randomize list.\n"); 
     printf("3. Print list.\n"); 
     printf("4. Add another song.\n"); 
     printf("5. Go back\n"); 
     scanf("%d", &answer); 

     switch (answer) 
     { 

     case 1: 
      printf("How many songs would you like to add right now?: \n"); 
      scanf("%d", &howMany); 
      getchar(); 

      aSong = (struct Song *) malloc((sizeof(struct Song) * howMany)); 

      for (int i = 0; i < howMany; i++) { 
       //Adds songs to the array. Depends on how many the user wants to add 
       printf("Enter a songname: \n"); 
       fgets(aSong[i].titel, SIZE, stdin); 
       fflush(stdin); 
       getchar(); 
       printf("Enter the artist/band: \n"); 
       fgets(aSong[i].artist, SIZE, stdin); 
       fflush(stdin); 
       getchar(); 
       printf("Enter which year the song was released: \n"); 
       scanf("%d", &aSong[i].releaseD); 
       fflush(stdin); 
       getchar(); 
      } 
      printf("Music added!\n"); 
      getchar(); 
      menu(&songs); 
      break; 

     case 3: 
      printf("-------------------------------\n"); 
      printf("Songs stored: \n"); 
      //Prints the songs 
      for (int i = 0; i < howMany; i++) { 
       printf("\nSong titel: %s Band/Artist: %s Release year: %d\n", aSong[i].titel, aSong[i].artist, aSong[i].releaseD); 
      } 
      printf("-------------------------------\n"); 
      menu(&songs); 
      getchar(); 
      break; 

     case 4: 
      //Add another song to the array 
      printf("Add another song: \n"); 
      struct Song* tmp = (struct Song*)malloc((howMany + 1) * sizeof(struct Song)); 

      //Change the array by increasing the nr of slots 
      for (int i = 0; i < howMany; i++) { 
       tmp[i] = aSong[i]; 
      } 

      //Redirect the pointers so it points to the correct array 
      free(aSong); 
      aSong = tmp; 
      tmp = NULL; 

      printf("Enter song name: \n"); 
      fgets(aSong[howMany].titel, SIZE, stdin); 
      getchar(); 
      printf("Enter band/artist name: \n"); 
      fgets(aSong[howMany].artist, SIZE, stdin); 
      getchar(); 
      printf("Enter the year when the song was released:\n"); 
      //scanf(" %d", &aSong[howMany].releaseD); 
      fgets(aSong[howMany].artist, SIZE, stdin); 
      getchar(); 
      printf("Song added!"); 
      printf("-------------------"); 

      howMany++; 
      free(aSong); 
      menu(&songs); 
      break; 

     case 5: 
      printf("Exit."); 
      menu(&songs); 
      break; 
     } 
    case 2: 
     return 0; 
     break; 
    } 
} 

私のmain.cファイルのみメニュー(&曲)関数を呼び出します。ここでは

コードは(私はそれではなく、機能のコードを入れて良く見えるようにすることができます知っている)です。

私は、ユーザーが何をしたいかを選択できるメニューシステムを使用しています。システムの 基本的な使用は、このように書き:

* You enter the "Add song" menu. 
* You choose how many songs you would like to enter 
* The user adds the info of the song 
* User prints the stored songs with case 3 
* User wants to add another song to the array with case 4 
* User enters data again to add another song (YOU CAN'T ADD SONGS AGAIN WITH CASE 1, YOU HAVE TO USE CASE 4) 
* User wants to print the songs again with the print case 3 
* Program prints out trash values and the old songs that printed out nicely before are now trash also. 

私は私が間違っているのかを理解するように見える傾けます。誰かが私を教えてください。

構造体とlab3.hファイル:

#ifndef LAB3_H 
#define LAB3_H 
#define SIZE 80 

struct Song 
{ 
    char titel[SIZE]; 
    char artist[SIZE]; 
    int releaseD; 
}; 
int menu(struct Song *songs); 

#endif // !LAB3_H 

EDIT

(main.cので、私は_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF持っています| _CRTDBG_LEAK_CHECK_DF)を、メモリリークを見つけるために。)

+0

再帰呼び出しで再帰呼び出しを行います。簡単でトレースしやすいループではないのはなぜですか? – StoryTeller

+3

さらに必要[mcve]。 – melpomene

+0

私はコードが改善できることは知っていますが、私はまだプログラミングの "学習"の期間にいます。スイッチケースのコードを意味しますか? – Lsm

答えて

1

ケース4の終わりにコールフリー(aSong)があるため、メニューの再帰呼び出しで配列の内容が失われます。お役に立てれば。

+0

ケース4の空き(aSong)を削除することで、バンド/アーティスト名を出力できました。まだタイトルがなく、releaseDにゴミ箱があります。これは私が思う正しい方向です! – Lsm

関連する問題