字符串解析问题: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#
(空行)
问题出在哪?
我帮你拆解下核心问题:
strtok的副作用坑到你了:strtok会直接修改原字符串,第一次调用strtok(src, note)时,它找到了非音符字符的"4"并返回指向它的指针o;但第二次调用strtok(src, octave)时,它会从字符串开头重新找非数字字符(也就是"A#"),然后把后面的"4"改成'\0'——这直接导致o指向的位置变成了空字符串,所以输出就成了空行。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
相关产品推荐
相关产品推荐

