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

字符串解析问题:A#4解析后八度值输出为空?求错误分析与方案

问题:音符与八度解析时八度值为空的问题

我需要将字符串解析为音符(note)和八度(octave)。例如输入"A#4"时,需将(A#)存入char* n,(4)存入char* o。但运行代码后,八度值输出为空行,仅显示A#。

我的代码如下:

#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main() {
 string src = get_string();
 char *n;
 char *o;
 char *note = "ABCDEFG#b";
 char *octave = "12345678";
 o = strtok(src, note);
 n = strtok(src, octave);
 printf("%s\n", n);
 printf("%s\n", o);
}

输出结果:

A#
(空行)


问题出在哪?

我帮你拆解下核心问题:

  1. strtok的副作用坑到你了:strtok会直接修改原字符串,第一次调用strtok(src, note)时,它找到了非音符字符的"4"并返回指向它的指针o;但第二次调用strtok(src, octave)时,它会从字符串开头重新找非数字字符(也就是"A#"),然后把后面的"4"改成'\0'——这直接导致o指向的位置变成了空字符串,所以输出就成了空行。
  2. strtok的调用逻辑错了:第二次调用你传了src,相当于重新初始化分割流程,而不是继续分割同一个字符串;而且你用音符字符当分隔符提取八度的思路,本身就容易因为strtok的特性出问题。

怎么解决?

给你三种靠谱的方案,按需选择:

方案1:最简单的strtok正确用法

先提取音符,再用NULL继续分割拿八度,这样不会破坏之前的指针:

#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main() {
    string src = get_string();
    char *n;
    char *o;
    // 只用数字当分隔符就行
    char *octave_chars = "12345678";

    // 第一次分割:提取非数字的音符部分
    n = strtok(src, octave_chars);
    // 第二次分割:传NULL继续,提取剩下的数字八度
    o = strtok(NULL, octave_chars);

    printf("%s\n", n);
    printf("%s\n", o);
}

方案2:手动遍历分割(更安全,能处理错误)

如果不想依赖strtok的修改特性,可以手动找数字的位置,然后分割,还能处理输入没数字的情况:

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

int main() {
    string src = get_string();
    char *n;
    char *o;
    int len = strlen(src);
    int split_idx = -1;

    // 遍历找到第一个数字的位置
    for (int i = 0; i < len; i++) {
        if (isdigit(src[i])) {
            split_idx = i;
            break;
        }
    }

    // 处理输入错误的情况
    if (split_idx == -1) {
        printf("输入格式不对,缺少八度数字哦\n");
        return 1;
    }

    // 给音符分配内存并复制
    n = malloc(split_idx + 1);
    strncpy(n, src, split_idx);
    n[split_idx] = '\0'; // 手动加结束符

    // 八度直接指向原字符串的数字部分
    o = src + split_idx;

    printf("%s\n", n);
    printf("%s\n", o);

    free(n); // 记得释放内存
    return 0;
}

方案3:利用字符串偏移快速分割

这个方法最简洁,依赖strtok修改原字符串的特性,直接通过音符长度偏移找到八度:

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main() {
    string src = get_string();
    char *n;
    char *o;
    char *octave_chars = "12345678";

    // 提取音符部分,strtok会把第一个数字改成'\0'
    n = strtok(src, octave_chars);
    // 音符长度之后就是八度的起始位置
    o = src + strlen(n);

    printf("%s\n", n);
    printf("%s\n", o);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:36:06