C语言中将字符串内整数存入数组时遇调试断言失败问题求助
解决Visual Studio中"Debug Assertion Failed!"错误及代码修正
代码中的核心错误点
- 结构体定义错误:
const char* gradeType[20];是指针数组,但成绩类型是单个字符串(如Quiz),应该改为char gradeType[20];,否则存储时会出现类型不匹配,引发内存访问错误。 - 成绩数量计算逻辑错误:原循环条件
i <= str[i]完全不符合字符串遍历规则,应该遍历到字符串结束符'\0';输入中的空格数即为成绩的数量(成绩类型后每个成绩前有一个空格),无需额外调整。 - sscanf_s参数错误:原代码中
grades.gradeType是指针数组,与%s格式符要求的字符缓冲区不匹配,修正结构体后需保证传入正确的缓冲区地址和大小。 - 成绩数组存储的致命问题:
- 循环条件错误:
sizeof(grades.a_Nums)返回数组总字节数(80),应该循环grades.numValues次(最多不超过20)。 - sscanf_s的参数错误:
%d需要传入int变量的地址,即&grades.a_Nums[i],直接传数组元素会把数值当作内存地址,触发断言失败。 - 未处理
strchr返回NULL的情况:当找不到下一个空格时(比如最后一个成绩后没有空格),ptr为NULL,此时ptr +1会访问非法内存,必须提前判断。
- 循环条件错误:
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct gradeData { int a_Nums[20]; int numValues; char gradeType[20]; // 改为字符数组存储单个成绩类型 }; int main() { struct gradeData grades = {0}; // 初始化所有成员为0 char str[50]; printf("Enter a student's grade type and grades (e.g. Quiz 41 20 90 81):\n"); fgets(str, 50, stdin); // 去除fgets读取的换行符(如果存在) size_t len = strlen(str); if (len > 0 && str[len - 1] == '\n') { str[len - 1] = '\0'; } // 计算成绩数量(空格数即为成绩个数) grades.numValues = 0; for (int i = 0; str[i] != '\0'; i++) { if (str[i] == ' ') { grades.numValues++; } } // 限制成绩数量不超过数组最大容量20 if (grades.numValues > 20) { grades.numValues = 20; } // 存储成绩类型 sscanf_s(str, "%s", grades.gradeType, (unsigned)_countof(grades.gradeType)); // 存储成绩到数组 char* ptr = str; for (int i = 0; i < grades.numValues; i++) { // 找到下一个空格 ptr = strchr(ptr, ' '); if (ptr == NULL) { break; // 提前结束,避免非法访问 } // 从空格后读取整数 sscanf_s(ptr + 1, "%d", &grades.a_Nums[i]); // 移动指针到当前空格位置,下次循环找下一个 ptr++; } // 测试输出,验证存储结果 printf("Grade Type: %s\n", grades.gradeType); printf("Number of Grades: %d\n", grades.numValues); printf("Grades: "); for (int i = 0; i < grades.numValues; i++) { printf("%d ", grades.a_Nums[i]); } printf("\n"); return 0; }
额外说明
- 加入了换行符处理:
fgets会读取输入末尾的换行符,提前替换为'\0'避免后续处理出错。 - 增加了成绩数量的上限限制:防止输入超过数组容量20导致越界。
- 加入测试输出:方便验证结构体中存储的数据是否正确。
内容的提问来源于stack exchange,提问作者pop
相关产品推荐
相关产品推荐

