我想解决下面这个问题,这个问题最近出现在我朋友的大学考试中(现在考试结束了,试卷也发了)
开发一个C程序来管理歌曲的播放列表,其中每首歌曲都有一个标题和持续时间(以秒为单位)。使用两个独立的动态分配数组来存储标题和持续时间。实现用户定义的函数,使用指针算术来添加、删除、更新和显示播放列表信息。(10分)
我做了以下尝试:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const size_t MAX_NAME_LENGTH = 20;
size_t number_of_songs = 0;
char* names_of_songs;
int* durations;
void add(char* name_of_song, int duration) {
number_of_songs++;
names_of_songs = realloc(name_of_song, MAX_NAME_LENGTH * number_of_songs);
durations = realloc(durations, number_of_songs * sizeof(int));
int start_location = ((number_of_songs - 1) * MAX_NAME_LENGTH) + 1;
char* name_location = &name_of_song[start_location];
strncpy(name_location, name_of_song, MAX_NAME_LENGTH);
names_of_songs[start_location + strlen(name_of_song) + 1] = 0;
durations[number_of_songs - 1] = duration;
}
void display() {
for (size_t i = 0; i < number_of_songs; i++) {
int position_in_name = 0;
int start_location = (i * MAX_NAME_LENGTH) + 1;
char character = 1;
printf("Name: ");
while (character != 0) {
character = names_of_songs[start_location++];
printf("%c", character);
}
printf(", Duration: %d secn", durations[i]);
}
}
int main(int argc, char const *argv[]) {
names_of_songs = malloc(1);
durations = malloc(1);
display();
add("Something", 2);
display();
add("Something else", 32);
display();
add("boring song", 4);
display();
free(names_of_songs);
free(durations);
return 0;
}
当我运行它时,我得到一个分段错误。使用我的调试器,当add()
试图调整新歌标题时,似乎第一次运行realloc()
时会发生这种情况。发生了什么,我该如何解决?
另外,我如何调试这样的东西?
-
relloc()
用于调整动态内存大小。最简单的解决方法就是允许全局变量初始化默认值为0。 -
将
realloc()
的返回值分配给临时值,否则如果realloc()
失败,将会泄漏内存。 -
当你指的是
names_of_songs
时,在第一个realloc()
name_of_song
中使用了不正确的变量。 -
使用符号常量代替const值。在堆栈上分配内存时需要前者,否则它们将成为vla。
-
+ 1
的起始位置错误 -
在每个
add()
之后删除display()
,因为它令人困惑(对我来说)。 -
(不固定)对于
names_of_songs
考虑使用char指针数组(即char **names_of_songs
):names_of_songs[number_of_songs] = strndup(name_of_songs, MAX_NAME_LENGTH)
这更容易,你没有浪费空间。 -
(未修复)如果你真的想使用char数组,考虑用指向char数组的指针
(*p)[MAX_NAME_LENGTH]
索引它,以便编译器为你缩放指针。 -
display()
:只打印字符串而不是单独打印每个字符更容易。然后,您可以将所有printf()
调用合并为一个。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 20
size_t number_of_songs;
char* names_of_songs;
int* durations;
void add(char* name_of_song, int duration) {
char *tmp = realloc(names_of_songs, MAX_NAME_LENGTH * (number_of_songs + 1));
if(!tmp) {
printf("malloc failedn");
return;
}
names_of_songs = tmp;
strncpy(names_of_songs + number_of_songs * MAX_NAME_LENGTH, name_of_song, MAX_NAME_LENGTH);
names_of_songs[number_of_songs * MAX_NAME_LENGTH + strlen(name_of_song)] = ' ';
int *tmp2 = realloc(durations, sizeof *tmp2 * (number_of_songs + 1));
if(!tmp2) {
printf("malloc failedn");
return;
}
durations = tmp2;
durations[number_of_songs] = duration;
number_of_songs++;
}
void display() {
for (size_t i = 0; i < number_of_songs; i++)
printf("Name: %s, Duration %d secn",
names_of_songs + i * MAX_NAME_LENGTH,
durations[i]
);
}
int main() {
add("Something", 2);
add("Something else", 32);
add("boring song", 4);
display();
free(names_of_songs);
free(durations);
}
示例输出:
Name: Something, Duration: 2 sec
Name: Something else, Duration: 32 sec
Name: boring song, Duration: 4 sec