【问题标题】:C - Dynamic allocation overwriting existing data?C - 动态分配覆盖现有数据?
【发布时间】:2017-01-29 12:48:42
【问题描述】:

所以我有这个任务,我有一个名为 Song 的结构。使用这个结构,我正在使用 Song 结构对数组进行动态分配。

所以当我尝试将另一首歌曲添加到我的结构中的数组时,我遇到了这个问题。 当使用案例 4 将另一首歌曲添加到数组中时,它会将 struct Song 中的变量值更改为垃圾值。我不确定它为什么会这样。预期的结果应该是数组扩展并将歌曲添加到 aSong。 使用案例 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 文件只调用 menu(&songs) 函数。

我正在使用允许用户选择他们想要做什么的菜单系统。 该系统的基本使用如下:

 * 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

编辑

(在 main.c 中,我确实有 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 来查找内存泄漏。)

【问题讨论】:

  • 您在递归调用上进行递归调用。为什么不是一个简单、易于跟踪的循环?
  • 我知道代码可以改进,但我仍处于编程的“学习”阶段。你是说 switch-case 代码吧?
  • @Lsm 您可能想再次阅读该链接。
  • fflush() 仅为输出流定义,fflush(stdin) 调用未定义的行为

标签: c visual-studio-2015 variable-assignment dynamic-allocation


【解决方案1】:

case 4 的最后有一个调用 free(aSong),所以在 menu 的递归调用中,数组的内容就丢失了。希望这会有所帮助。

【讨论】:

  • 通过删除案例 4(底部)中的免费(aSong),我能够打印出乐队/艺术家的姓名。仍然没有标题,并且 releaseD 得到了垃圾值。我认为这是正确的方向!
猜你喜欢
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 2020-05-27
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 2015-10-20
  • 2018-06-08
相关资源
最近更新 更多