摩尔斯电码解码时3个空格丢失问题排查及C语言优化方案咨询
摩尔斯电码解码问题排查与优化方案
问题背景
正在完成一个学习用的摩尔斯电码解码任务,目标是将输入的摩尔斯电码解码为字符串,预期输出为"HEY JUDE",但当前输出为"H EYJ U D E"。核心问题是使用strtok分割令牌时,无法识别表示单词间隔的3个连续空格,导致单词间的空格丢失。
尝试过三种实现思路:
- 逐个遍历原消息和词汇表字符匹配
- 构建7状态的状态机
- 分割输入为令牌后用
strcmp匹配词汇表(认为此方案最优)
为解决strtok的问题,编写了find_space_positions函数,但该函数未按预期工作,现需要:
- 分析
find_space_positions函数异常原因并修正 - 提供C语言中摩尔斯电码解码的更优方案
原代码
#include <stdlib.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include<stdio.h> const char *morse[55] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", ".-.-.-", "--..--", "..--..", ".----.", "-.-.--", "-..-.", "-.--.", "-.--.-", ".-...", "---...", "-.-.-.", "-...-", ".-.-.", "-....-", "..--.-", ".-..-.", "...-..-.", ".--.-.", "...---..."}; const char *ascii[55] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", ",", "?", "'", "!", "/", "(", ")", "&", ":", ";", "=", "+", "-", "_", "\"", "$", "@", "SOS"}; char input[] = ".... . -.-- .--- ..- -.. ."; static uint16_t msg_iter = 0; static uint16_t voc_word_iter = 0; static uint16_t voc_word_chr_iter = 0; static uint16_t iter = 0; static char buf[20] = ""; bool find_space_positions (const char* morse_code, uint16_t token_counter, uint16_t len ) { uint16_t space_counter = 0; for (uint16_t i = 0; i <len; i++){ printf("%c\n", morse_code[i]); if (morse_code[i] == ' ') { space_counter++; printf("%d+++ \n", space_counter); } else if (space_counter == token_counter) { if (morse_code[i + 1] == ' ' && morse_code[i + 2] == ' ') { return true; } else { return false; } } } } void decode_morse(const char *morse_code) { uint16_t input_len = strlen(morse_code); char *word = strtok(morse_code, " "); uint16_t token_number = 1; while (word != NULL) { for (int voc_word_iter = 0; voc_word_iter < 55; voc_word_iter++) { if (strcmp(word, morse[voc_word_iter]) == 0) { if (find_space_positions(input,token_number, input_len )) { buf[iter] = ' '; iter++; } buf[iter] = *ascii[voc_word_iter]; iter++; break; } } word = strtok(NULL, " "); token_number++; } printf("%s\n", buf); } int main () { decode_morse(input); return 777; }
一、find_space_positions函数问题分析与修正
问题分析
- 逻辑错位:
token_number是strtok分割出的令牌序号,而space_counter统计的是原字符串中所有空格的总数,两者没有对应关系。strtok会将连续空格视为单个分隔符,导致无法通过令牌序号反向定位原字符串中的空格位置。 - 内存越界:当遍历到字符串最后一个字符时,
i+1和i+2会访问超出字符串长度的内存,引发未定义行为。 - 返回值缺失:若循环结束未触发任何返回条件,函数无返回值,导致未定义行为。
修正思路
由于strtok已经丢失了连续空格的关键信息,基于它的find_space_positions思路从根本上不可行。正确的做法是放弃使用strtok,改为手动遍历字符串,直接识别字符分隔(1个空格)和单词分隔(3个连续空格)。
二、更优的C语言解码方案
核心思路
- 手动遍历输入字符串,收集摩尔斯字符的点/划,直到遇到空格
- 统计连续空格数量:1个空格表示字符分隔,3个空格表示单词分隔
- 每收集完一个摩尔斯字符,遍历词汇表匹配对应的ASCII字符
- 处理单词分隔时,在结果中添加空格
优化后代码
#include <stdio.h> #include <string.h> // 摩尔斯码与ASCII映射表 const char *morse_codes[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", ".-.-.-", "--..--", "..--..", ".----.", "-.-.--", "-..-.", "-.--.", "-.--.-", ".-...", "---...", "-.-.-.", "-...-", ".-.-.", "-....-", "..--.-", ".-..-.", "...-..-.", ".--.-.", "...---..."}; const char *ascii_chars[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", ",", "?", "'", "!", "/", "(", ")", "&", ":", ";", "=", "+", "-", "_", "\"", "$", "@", "SOS"}; #define MORSE_COUNT (sizeof(morse_codes)/sizeof(morse_codes[0])) // 匹配摩尔斯码到ASCII字符 const char* match_morse(const char *code) { for (int i = 0; i < MORSE_COUNT; i++) { if (strcmp(code, morse_codes[i]) == 0) { return ascii_chars[i]; } } return "?"; // 匹配失败返回占位符 } void decode_morse(const char *input, char *output) { char current_code[10] = {0}; int code_idx = 0; int space_count = 0; int out_idx = 0; while (*input != '\0') { if (*input == ' ') { space_count++; // 处理字符分隔(1个空格) if (space_count == 1 && code_idx > 0) { strcpy(output + out_idx, match_morse(current_code)); out_idx += strlen(match_morse(current_code)); code_idx = 0; memset(current_code, 0, sizeof(current_code)); } // 处理单词分隔(3个连续空格) else if (space_count == 3) { output[out_idx++] = ' '; space_count = 0; // 重置空格计数 } } else { // 收集摩尔斯码字符 if (space_count > 0) { space_count = 0; // 遇到非空格字符,重置空格计数 } if (code_idx < sizeof(current_code)-1) { current_code[code_idx++] = *input; } } input++; } // 处理最后一个摩尔斯码 if (code_idx > 0) { strcpy(output + out_idx, match_morse(current_code)); } } int main() { char input[] = ".... . -.-- .--- ..- -.. ."; char output[50] = {0}; decode_morse(input, output); printf("解码结果:%s\n", output); // 输出 HEY JUDE return 0; }
方案优势
- 直接保留原字符串的空格信息,无需依赖
strtok,避免了连续空格丢失的问题 - 逻辑清晰,逐字符处理的方式更易调试和维护
- 适配所有合法摩尔斯码的解码需求,包括特殊符号
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

