C语言多维数组初始化与输出异常问题求助
C语言多维数组越界与字符串溢出问题修复
问题描述
我明明将数组初始化为[length*2][length/2+1][3],但实际运行起来像是[length*2][4][????]。这显然是C语言新手错误,但我找不到原因。当largo=6时,程序应输出每个arr[][]位置存储的数据,但仅显示7个中的4个,且旧数据未被清除,而是被拼接成类似"1/22/1"的形式。补充信息:若将valoresPosiblesFinal[largo*2-1][(largo/2)+1][3]的最后一个维度设为4(我以为是终止符问题),程序直接在此处停止。
原始代码
#include <stdio.h> void dosDados(){ int largo; //max length of the dice. it's used to calculate the length of the arrays int min = 2; //minor value posible char auxRes[4]; //I don't even use it anymore printf("Ingrese el largo de los dados: "); scanf("%d",&largo); char valoresPosiblesFinal[largo*2-1][(largo/2)+1][3];//array where the sets n/n are stored int auxArr[largo+2]; //array to know how many elements are there in each set (ie: if I saved 1/2 I don't want to overflow it with 2/1) for(int i = 0; i < largo-1; i++){ auxArr[i] = 0; } //inialice the array auxArr to avoid erratic behavior for(int i = 1; i <= largo; i++){ //loop to emulate the firt dice for(int j = 1; j <= largo; j++){ //loop to emulate the second dice if((i+j >= min) && (i+j<=largo+largo)){ //Used to know if i+j is within the posible values sprintf(valoresPosiblesFinal[i+j][auxArr[i+j]],"%d/%d",i,j); //I declare that the value of valoresPosiblesFinal is "%d/%d" auxArr[i+j]++; } } } for(int i = 0; i < largo*2-1; i++){ for(int j = 0; j< largo/2+1;j++){ printf("[ %s ]",valoresPosiblesFinal[i][j]); } printf("\n"); } } int main(){ dosDados(); }
问题根源与修复步骤
1. 字符串溢出导致内存污染
"%d/%d"格式的字符串(比如"6/6")需要4个字节存储:数字+斜杠+数字+\0字符串终止符。你定义的第三维度是3,刚好缺少1个字节,导致sprintf写入时越界,覆盖相邻内存区域,出现"1/22/1"这种拼接错误。
修复:把数组第三维度改为4:
char valoresPosiblesFinal[largo*2+1][(largo/2)+1][4];
2. 数组索引越界与未初始化
- auxArr初始化不完整:你只初始化了
auxArr[0]到auxArr[largo-2],但i+j的范围是2到2*largo,对应auxArr[2]到auxArr[2*largo],这些位置的初始值是随机垃圾值,导致sprintf写入到错误位置,甚至破坏栈内存。
修复:初始化auxArr的所有用到的索引:int auxArr[largo*2 + 1]; // 扩大数组容量到能容纳最大索引2*largo for(int i = 0; i <= largo*2; i++){ auxArr[i] = 0; } - 第一维度容量不足:
valoresPosiblesFinal的第一维度是largo*2-1,但i+j的最大值是2*largo,索引超出数组范围(数组最大索引为largo*2-2),导致越界写内存。
修复:把第一维度改为largo*2+1,确保能容纳所有i+j的结果:char valoresPosiblesFinal[largo*2+1][(largo/2)+1][4];
3. 输出循环范围错误
输出循环从i=0开始,而i+j的最小值是2,前两个位置的内容是未初始化的垃圾值;同时遍历整个largo/2+1个位置,会输出未使用的空元素。
修复:从i=2开始输出,只遍历每个i下的有效元素(数量为auxArr[i]):
for(int i = 2; i <= largo*2; i++){ for(int j = 0; j < auxArr[i]; j++){ printf("[ %s ]", valoresPosiblesFinal[i][j]); } printf("\n"); }
修复后的完整代码
#include <stdio.h> void dosDados(){ int largo; int min = 2; printf("Ingrese el largo de los dados: "); scanf("%d",&largo); // 修正数组维度,确保容纳字符串终止符和所有索引 char valoresPosiblesFinal[largo*2+1][(largo/2)+1][4]; int auxArr[largo*2 + 1]; // 初始化所有用到的auxArr元素 for(int i = 0; i <= largo*2; i++){ auxArr[i] = 0; } for(int i = 1; i <= largo; i++){ for(int j = 1; j <= largo; j++){ int sum = i + j; if(sum >= min && sum <= largo*2){ sprintf(valoresPosiblesFinal[sum][auxArr[sum]],"%d/%d",i,j); auxArr[sum]++; } } } // 只输出有效元素 for(int i = 2; i <= largo*2; i++){ printf("Suma %d: ", i); for(int j = 0; j < auxArr[i]; j++){ printf("[ %s ]", valoresPosiblesFinal[i][j]); } printf("\n"); } } int main(){ dosDados(); }
内容的提问来源于stack exchange,提问作者Julian.gxnzalez
相关产品推荐
相关产品推荐

