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

摩尔斯电码解码时3个空格丢失问题排查及C语言优化方案咨询

摩尔斯电码解码问题排查与优化方案

问题背景

正在完成一个学习用的摩尔斯电码解码任务,目标是将输入的摩尔斯电码解码为字符串,预期输出为"HEY JUDE",但当前输出为"H EYJ U D E"。核心问题是使用strtok分割令牌时,无法识别表示单词间隔的3个连续空格,导致单词间的空格丢失。

尝试过三种实现思路:

  • 逐个遍历原消息和词汇表字符匹配
  • 构建7状态的状态机
  • 分割输入为令牌后用strcmp匹配词汇表(认为此方案最优)

为解决strtok的问题,编写了find_space_positions函数,但该函数未按预期工作,现需要:

  1. 分析find_space_positions函数异常原因并修正
  2. 提供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函数问题分析与修正

问题分析

  1. 逻辑错位:token_number是strtok分割出的令牌序号,而space_counter统计的是原字符串中所有空格的总数,两者没有对应关系。strtok会将连续空格视为单个分隔符,导致无法通过令牌序号反向定位原字符串中的空格位置。
  2. 内存越界:当遍历到字符串最后一个字符时,i+1和i+2会访问超出字符串长度的内存,引发未定义行为。
  3. 返回值缺失:若循环结束未触发任何返回条件,函数无返回值,导致未定义行为。

修正思路

由于strtok已经丢失了连续空格的关键信息,基于它的find_space_positions思路从根本上不可行。正确的做法是放弃使用strtok,改为手动遍历字符串,直接识别字符分隔(1个空格)和单词分隔(3个连续空格)。


二、更优的C语言解码方案

核心思路

  1. 手动遍历输入字符串,收集摩尔斯字符的点/划,直到遇到空格
  2. 统计连续空格数量:1个空格表示字符分隔,3个空格表示单词分隔
  3. 每收集完一个摩尔斯字符,遍历词汇表匹配对应的ASCII字符
  4. 处理单词分隔时,在结果中添加空格

优化后代码

#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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:07:01