我有一个代码,我正在尝试做一些歌曲的播放列表。它们将位于通过链接列表连接的结构上,其中包含歌曲名称和时间。 在程序中,有一个执行命令的函数(可以在开始/结束时添加、删除或播放)。当执行 play 命令时,它应该调用函数 print_list,但显然它没有被调用,并且列表也没有被打印。
我尝试在 main 函数中写入 print_list 的内容,检查 PLAY 是否获取其值 2,以便execute_cmd 正确调用 print_lists。尽管如此,它并没有打印链接列表的内容。
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum commands { ADDBEG, ADDEND, PLAY, REMOVE, INVALID } command_t;
typedef struct song_s {
char name[99];
char time[20];
struct song_s *next;
} song_t;
void insert_end(song_t **p, song_t *entry);
void insert_begin(song_t **p, song_t *entry);
void remove_song(song_t **p, song_t *entry);
void execute_cmd(command_t command, song_t **head, song_t *entry);
bool already_present(song_t **p, song_t *new_song);
void print_list(song_t *p);
command_t split_input(char *input, song_t *song) {
command_t command = INVALID;
int len = strlen(input);
// Remove the newline character, if present
if (input[len - 1] == '\n') {
input[len - 1] = '\0';
}
// Check if the input command is "PLAY"
if (strcmp(input, "PLAY") == 0) {
return PLAY;
}
char *token = strtok(input, ",");
char *data[3];
int i = 0;
// Check if the input command starts with "REMOVE,"
if (input[0] == 'R') {
while (token != NULL && i < 2) {
data[i] = token;
token = strtok(NULL, ",");
printf("%s", data[i]);
i++;
}
return REMOVE;
}
// Check if the input command starts with "ADDBEG" or "ADDEND"
if (input[0] == 'A') {
while (token != NULL && i < 3) {
data[i] = token;
printf("%s\n", token);
token = strtok(NULL, ",");
i++;
}
}
// Set the command based on the input data
if (strcmp(data[0], "ADDBEG") == 0) {
command = ADDBEG;
} else if (strcmp(data[0], "ADDEND") == 0) {
command = ADDEND;
}
// Copy song data if available
if (data[1] != NULL)
strcpy(song->name, data[1]);
if (data[2] != NULL)
strcpy(song->time, data[2]);
return command;
}
int main(void) {
char input[100];
song_t song;
song_t *head = NULL;
int total_time = 0;
command_t command;
while (1) {
printf("input: ");
fgets(input, 100, stdin);
command = split_input(input, &song);
if (command == PLAY) {
printf("total time: %d\n", total_time);
break;
}
// Total time calculation
if (command == ADDBEG || command == ADDEND) {
if (!already_present(&head, &song)){
total_time += atoi(song.time);
}
}
if (command == REMOVE) {
total_time -= atoi(song.time);
}
// Execution based on command
execute_cmd(command, &head, &song);
}
return 0;
}
void insert_end(song_t **p, song_t *entry) {
song_t *q = (song_t *)malloc(sizeof(song_t));
memcpy(q, entry, sizeof(song_t));
q->next = NULL;
song_t *aux;
if (*p == NULL)
*p = q;
else {
aux = *p;
while (aux->next != NULL)
aux = aux->next;
aux->next = q;
}
}
void insert_begin(song_t **p, song_t *entry) {
song_t *q = (song_t *)malloc(sizeof(song_t));
memcpy(q, entry, sizeof(song_t));
q->next = *p;
*p = q;
}
void remove_song(song_t **p, song_t *entry) {
song_t *q = *p;
if (q == NULL)
return; // empty list
if (strcmp(q->name, entry->name) == 0) {
*p = q->next;
free(q);
return;
}
while (q->next != NULL) {
if (strcmp(q->next->name, entry->name) == 0)
break;
q = q->next;
}
if (q->next == NULL)
return; // value not found
song_t *tmp = q->next;
q->next = tmp->next;
free(tmp);
}
void print_list(song_t *p) {
while (p != NULL) {
printf("Song Name: %s, Time: %s\n", p->name, p->time);
p = p->next;
}
}
void execute_cmd(command_t command, song_t **head, song_t *new_song) {
// Call the appropriate function based on the command
if (command == ADDBEG) {
insert_begin(head, new_song);
} else if (command == ADDEND) {
insert_end(head, new_song);
} else if (command == REMOVE) {
remove_song(head, new_song);
} else if (command == PLAY) {
print_list(*head);
} else {
printf("Invalid command\n");
}
}
// Check if the song is already in the playlist
bool already_present(song_t **p, song_t *new_song) {
song_t *q = *p;
while (q != NULL) {
if (strcmp(q->name, new_song->name) == 0) {
return true;
}
q = q->next;
}
return false;
}
split_input()
对我而言,输入=“10”时出现段错误,因为 song
或 data
均未初始化,如果它们不指向字符串,则对 strcmp()
的调用是未定义的行为。
split_input()
printf("%s\n", token)
上的段错误 如果 input[0] == 'A'
并且该行的其余部分不包含 2 个逗号,或者如果 `input[0] == 'R' 并且留置权的其余部分不包含逗号。
main()
中断将终止 while
循环,因此 execute_cmd()
永远不会运行:
if (command == PLAY) {
printf("total time: %d\n", total_time);
break;
}
这是修改后的程序:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum commands { ADDBEG, ADDEND, PLAY, REMOVE, INVALID } command_t;
typedef struct song_s {
char name[99];
char time[20];
struct song_s *next;
} song_t;
void insert_end(song_t **p, song_t *entry);
void insert_begin(song_t **p, song_t *entry);
void remove_song(song_t **p, song_t *entry);
void execute_cmd(command_t command, song_t **head, song_t *entry);
bool already_present(song_t **p, song_t *new_song);
void print_list(song_t *p);
command_t split_input(char *input, song_t *song) {
command_t command = INVALID;
int len = strlen(input);
if (input[len - 1] == '\n') {
input[len - 1] = '\0';
}
if (!strcmp(input, "PLAY")) {
return PLAY;
}
char *token = strtok(input, ",");
char *data[3];
if (input[0] == 'A') {
for(int i = 0; token && i < 3; i++) {
data[i] = token;
token = strtok(NULL, ",");
}
}
if (input[0] == 'R') {
for(int i = 0; token && i < 2; i++) {
data[i] = token;
token = strtok(NULL, ",");
}
return REMOVE;
}
if (!strcmp(data[0], "ADDBEG")) {
command = ADDBEG;
} else if (!strcmp(data[0], "ADDEND")) {
command = ADDEND;
}
if (data[1]) strcpy(song->name, data[1]);
if (data[2]) strcpy(song->time, data[2]);
return command;
}
int main(void) {
char input[100];
song_t *head = NULL;
int total_time = 0;
command_t command;
while (1) {
printf("input: ");
fgets(input, 100, stdin);
song_t song = {0};
command = split_input(input, &song);
if (command == PLAY)
printf("total time: %d\n", total_time);
else if (command == ADDBEG || command == ADDEND) {
if (!already_present(&head, &song)){
total_time += atoi(song.time);
}
}
else if (command == REMOVE) {
total_time -= atoi(song.time);
}
execute_cmd(command, &head, &song);
}
return 0;
}
void insert_end(song_t **p, song_t *entry) {
song_t *q = malloc(sizeof(song_t));
memcpy(q, entry, sizeof(song_t));
q->next = NULL;
song_t *aux;
if (*p == NULL)
*p = q;
else {
aux = *p;
while (aux->next != NULL)
aux = aux->next;
aux->next = q;
}
}
void insert_begin(song_t **p, song_t *entry) {
song_t *q = malloc(sizeof *q);
memcpy(q, entry, sizeof *q);
q->next = *p;
*p = q;
}
void remove_song(song_t **p, song_t *entry) {
song_t *q = *p;
if (!q)
return; // empty list
if (strcmp(q->name, entry->name) == 0) {
*p = q->next;
free(q);
return;
}
while (q->next) {
if (strcmp(q->next->name, entry->name) == 0)
break;
q = q->next;
}
if (!q->next)
return; // value not found
song_t *tmp = q->next;
q->next = tmp->next;
free(tmp);
}
void print_list(song_t *p) {
while (p != NULL) {
printf("Song Name: %s, Time: %s\n", p->name, p->time);
p = p->next;
}
}
void execute_cmd(command_t command, song_t **head, song_t *new_song) {
if (command == ADDBEG) {
insert_begin(head, new_song);
} else if (command == ADDEND) {
insert_end(head, new_song);
} else if (command == REMOVE) {
remove_song(head, new_song);
} else if (command == PLAY) {
print_list(*head);
} else {
printf("Invalid command\n");
}
}
// Check if the song is already in the playlist
bool already_present(song_t **p, song_t *new_song) {
song_t *q = *p;
while (q != NULL) {
if (!strcmp(q->name, new_song->name))
return true;
q = q->next;
}
return false;
}
和示例会话:
input: ADDBEG,a,1
input: PLAY
total time: 1
Song Name: a, Time: 1
input:
ctrl-c 将终止程序,或者您可以添加退出命令。