我正在尝试解决最近在我朋友的大学考试中出现的以下问题(现在考试已经结束并发布了论文)
开发一个 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 sec\n", 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;
}
当我运行它时,出现分段错误。使用我的调试器,它似乎在第一次运行
realloc()
时发生,当add()
尝试调整新歌曲标题时。发生了什么事,我该如何解决?
另外,我该如何调试这样的东西?
relloc()
用于调整动态内存的大小。最简单的修复是只允许全局变量的默认 0 初始化。
将
realloc()
的返回值赋给一个临时值,否则如果 realloc()
失败,您将泄漏内存。
第一个
realloc()
中使用的变量不正确name_of_song
当你的意思是names_of_songs
.
使用符号常量而不是常量值。在堆栈上分配内存时需要前者,否则它们将成为 VLA。
起始位置的
+ 1
错了
删除了每个
display()
之后的add()
,因为它让我感到困惑。
(不固定)对于
names_of_songs
,考虑使用字符指针数组(即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 failed\n");
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)] = '\0';
int *tmp2 = realloc(durations, sizeof *tmp2 * (number_of_songs + 1));
if(!tmp2) {
printf("malloc failed\n");
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 sec\n",
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