You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言链表歌曲播放列表:PLAY命令无法触发print_list打印问题求助

问题分析与修复:链表播放列表PLAY命令无法打印内容

问题根源

main函数的循环逻辑存在错误:当输入PLAY命令时,程序直接打印总时长后就执行break终止循环,完全跳过了调用execute_cmd的步骤,导致PLAY分支里的print_list函数从未被触发。

修复方案

调整main函数中PLAY命令的处理顺序,先执行命令逻辑再处理其他操作,同时根据需求决定是否终止程序:

  • 如果希望打印播放列表后程序继续运行,移除break语句;
  • 如果需要打印后退出,确保先调用execute_cmd再执行break。

另外补充一个潜在问题的修复:REMOVE命令处理时,未检查歌曲是否存在就直接减去时长,会导致总时长计算错误,需要增加存在性判断。

修复后的完整代码

#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, ",");
      i++;
    }
    strcpy(song->name, data[1]);
    return REMOVE;
  }

  // Check if the input command starts with "ADDBEG" or "ADDEND"
  if (input[0] == 'A') {
    while (token != NULL && i < 3) {
      data[i] = 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);
    
    // 先执行所有命令逻辑,包括PLAY
    execute_cmd(command, &head, &song);

    // 总时长计算放在命令执行后,确保操作有效
    if (command == ADDBEG || command == ADDEND) {
      if (!already_present(&head, &song)){
          total_time += atoi(song.time);
      }
    } 
    if (command == REMOVE) {
      // 移除前检查歌曲是否存在,避免错误扣减时长
      if (already_present(&head, &song)) {
          total_time -= atoi(song.time);
      }
    }

    // PLAY命令处理:打印总时长,不终止程序(如需终止可添加break)
    if (command == PLAY) {
      printf("total time: %d\n", total_time);
      // 如果需要输入PLAY后退出,取消下面的注释
      // break;
    }
  }
  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;
}

额外说明

  • 调整了命令执行顺序,确保所有命令(包括PLAY)都能触发execute_cmd中的逻辑;
  • 修复了REMOVE命令的时长计算bug,只有歌曲存在时才扣减时长;
  • 移除了原split_input中多余的printf调试语句,避免干扰正常输出;
  • 保留了PLAY后是否终止程序的可选逻辑,可根据需求调整。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:33:11