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

C语言调用strcmp()比较输入与字符串数组时输出异常排查

问题场景

开发基于C语言的大调音阶生成程序(音阶间隔规则为WS,WS,HS,WS,WS,WS)时,需要使用strcmp()函数将用户输入的音名字符数组,与存储12个标准音名的字符串数组做比对,获取匹配项的索引以应用音阶生成公式。原有实现代码如下:

/*This is a program to generate notes of major scale in C programing given WS,WS,HS,WS,WS,WS */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(){

    int i = 0; 
    int totalIntervals = 11;
    
    char *notes[12] = {"A", "A#", "B", "C","C#","D","D#","E","F","F#","G","G#"};
    char pickedNote[2] ;
    
    for(i=0;i<12;++i){
        printf("Your notes are  %s\n",notes[i]);
    }
    
    printf("Please type in a note\n");
    scanf("%s",pickedNote);
    printf("Your note is %s\n",pickedNote);

    for(i=0;i<12;++i)
    {
        int truth = strcmp(pickedNote,&notes[i]);
        printf("%d\n",&truth);
    }

    return 0;
}
异常现象

预期用户输入A时,strcmp返回值在匹配索引位置为0,其余位置为非0值,对应输出形态为:

Your note is A
1
0
0
0
0
0
0
0
0
0
0
0   

实际运行时所有比对结果输出均为异常随机整数值(如-1614868988),实际输出如下:

Your note is A
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988
-1614868988   
问题根因

代码存在3个直接触发异常的错误,另有1个潜在内存风险:

  • strcmp参数类型不匹配:notes是char*类型数组,notes[i]本身就是指向音名字符串的指针,符合strcmp要求的const char*入参类型;代码写&notes[i]取的是数组元素这个指针变量的栈内存地址,类型为char**,传入strcmp后会读取非法内存,返回值完全不可预期。
  • printf传参错误:要打印truth变量存储的strcmp返回值,直接传入变量名truth即可;代码写&truth传的是truth变量在栈上的内存地址,所以打印出来的是随机的栈地址值,和字符串比对结果没有任何关系。
  • 输入缓冲区长度不足:音名最长为2个有效字符(如A#),加上C语言字符串必须的末尾结束符\0,缓冲区至少需要3字节;原有代码定义char pickedNote[2],输入带#的音名时会直接发生缓冲区溢出,破坏栈内存数据。
  • 输入无长度限制:scanf("%s")没有做输入长度截断,用户输入过长内容时会直接造成内存越界。
修正后可运行代码
/*This is a program to generate notes of major scale in C programing given WS,WS,HS,WS,WS,WS */

#include <stdio.h>
#include <string.h>
int main(){
    int i = 0; 
    // 大调音阶间隔:全全半全全全半,对应步长2,2,1,2,2,2,1
    int majorSteps[] = {2,2,1,2,2,2,1};
    char *notes[12] = {"A", "A#", "B", "C","C#","D","D#","E","F","F#","G","G#"};
    // 缓冲区留足长度,scanf限制最多读2个有效字符,避免溢出
    char pickedNote[3] ;
    int rootIndex = -1;
    
    for(i=0;i<12;++i){
        printf("可选音名: %s\n",notes[i]);
    }
    
    printf("请输入起始音名: ");
    scanf("%2s",pickedNote);
    printf("你选择的主音是 %s\n",pickedNote);

    // 查找匹配的主音索引
    for(i=0;i<12;++i)
    {
        int cmpRes = strcmp(pickedNote, notes[i]);
        if(cmpRes == 0){
            rootIndex = i;
            break;
        }
    }

    if(rootIndex == -1){
        printf("输入的音名无效\n");
        return 1;
    }

    // 生成大调音阶
    printf("对应大调音阶为: ");
    int current = rootIndex;
    printf("%s ", notes[current]);
    for(i=0;i<7;++i){
        current = (current + majorSteps[i]) % 12;
        printf("%s ", notes[current]);
    }
    printf("\n");

    return 0;
}

内容的提问来源于stack exchange,提问作者Rudy F.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:57:18