如何避免strcmp与NULL比较?C语言程序段错误求助
问题分析与修复
导致段错误的核心原因
你的程序出现段错误不止是strcmp的问题,主要有以下几个关键错误:
1. 字符串常量不可修改
你把marca和aux指向了字符串常量" ":
marca=" "; aux=" ";
字符串常量存在只读内存区域,后续用scanf("%s",marca)或者strcpy(marca, aux)修改它们的内容,会直接触发内存访问错误,导致段错误。
2. strcmp传入NULL指针
你的marcas数组初始化时用了'\0',对于char*类型的数组元素,'\0'会被解析为NULL指针(字符'\0'的ASCII值是0,和空指针的地址值一致)。当循环遍历到这些NULL元素时,strcmp(marcas[i], marca)把NULL作为参数传入,而strcmp要求两个参数都是指向有效C字符串的指针,传入NULL会直接触发段错误。
3. 错误修改字符串常量
marcas前5个元素指向字符串常量,你直接用strcpy(marcas[i], marca)修改这些常量的内容,同样会触发只读内存的访问错误。
修复后的代码
调整内存分配方式,给marca和aux分配可写空间,同时修正marcas的初始化和插入逻辑:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main () { // 用NULL明确表示空指针,替代原代码的'\0' char *marcas[7] = {"Alfa Romeo", "Fiat", "Ford", "Lancia", "Renault", NULL, NULL}; // 分配可写缓冲区存储输入和临时数据 char marca[50], aux[50]; int i; int cont=5; for(i=0;i<cont;i++) printf("%s\n",marcas[i]); while (cont<7){ printf("Ingrese la marca que desee agregar a la lista.\n"); // 限制输入长度,避免缓冲区溢出 scanf("%49s", marca); printf("Gracias. Ud. quiere agregar la marca: %s.\n", marca); i=0; // 先检查marcas[i]非空,再调用strcmp while(i < cont && marcas[i] != NULL && strcmp(marcas[i], marca) < 0){ i++; printf("Moviendo puntero.\n"); } printf("Termine de mover.\n"); if (i < cont){ // 从后往前移动元素,避免数据覆盖 for(int j = cont; j > i; j--){ marcas[j] = marcas[j-1]; } } // 为新品牌分配内存并拷贝内容 marcas[i] = malloc(strlen(marca) + 1); strcpy(marcas[i], marca); cont++; printf("%s tiene que ir en la posicion %d\n", marca, i); for(i=0;i<cont;i++) printf("%s\n", marcas[i]); printf("La marca ingresada última a la lista:%s\n", marca); } for(i=0;i<7;i++){ if(marcas[i] != NULL) printf("%s\n", marcas[i]); } // 释放动态分配的内存,避免内存泄漏 for(i=0;i<7;i++){ if(marcas[i] != NULL) free(marcas[i]); } return 0; }
如何避免strcmp与NULL比较
要彻底避免这种问题,需要在调用strcmp前先检查参数有效性:
- 每次调用
strcmp(a, b)前,先判断a != NULL且b != NULL - 如果其中一个是NULL,单独处理(比如把NULL视为小于任何有效字符串,或者直接报错)
可以封装一个安全的字符串比较函数:
int safe_strcmp(const char *a, const char *b) { if (a == NULL && b == NULL) return 0; if (a == NULL) return -1; // NULL视为比任何字符串小 if (b == NULL) return 1; return strcmp(a, b); }
之后用safe_strcmp替代原生strcmp,就不会因为传入NULL触发段错误了。
内容的提问来源于stack exchange,提问作者Andrea Graf
相关产品推荐
相关产品推荐

