这是我的C ++程序,它接受一个2D数组a[m][n]
。如果元素a[i][j]
为零,则将所有ith
行和jth
列元素设置为零。
这是代码示例:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class SetZero{
public:
static void setZero(int **, int , int);
};
void SetZero::setZero(int ** a, int m, int n){
int i, j, k;
int ** b = new int *[m]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i][j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i][j] == 0 && b[i][j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
for(k = 0; k < m; k++){
a[k][j] = 0;
b[k][j] = 0;
}
j = n;//break. next row loop.
}
for(int i = 0; i < m; i++)
delete[] b[i];
delete[] b;
}
int main(){
int a[4][5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i][j] = rand() % 100;
cout << a[i][j] << " ";
}
cout << endl;
}
SetZero::setZero((int **)a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
环境:WIN8 Visual Studio 2012。
修改
程序可以编译但无法正常执行。它会在达到if(a[i][j] == 0 && b[i][j]){
错误消息是:
CCLC.exe中0x012875DD处的未处理异常:0xC0000005:Access 违规读取位置0x0000004B。
答案 0 :(得分:2)
SetZero::setZero((int **)a, 4, 5)
a
不是一个指针数组,它只是一个二维数组。
注意访问冲突是如何读取地址0x0000004B的?这是75,一个0到99之间的数字:)因为你正在处理一个二维数组(它只是一个一维数组,有一个简洁的访问方式)作为一个数组数组,它采取你的一个值array(75)是子数组的地址,然后尝试读取地址为75(或0x0000004B)的不存在的数组
我建议你'压扁'你的阵列并将它们作为一维数组使用,我觉得这个数组更简单:
void SetZero::setZero(int * a, int m, int n){
int i, j, k;
int * b = new int [m*n]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i*n+j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i*n+j] == 0 && b[i*n+j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i*n+k] = 0;//but there is NO dump here. Weird!
b[i*n+k] = 0;
}
for(k = 0; k < m; k++){
a[k*n+j] = 0;
b[k*n+j] = 0;
}
j = n;//break. next row loop.
}
delete[] b;
}
int main(){
int a[4*5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i*5+j] = rand() % 100;
cout << a[i*5+j] << " ";
}
cout << endl;
}
SetZero::setZero(a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i*5+j] << " ";
cout << endl;
}
return 0;
}
答案 1 :(得分:1)
关于SetZero()的一个建议。有一个名为memset()的函数,它允许您在给定起始指针和范围的情况下将所有字节设置为特定值。此功能可以使您的SetZero()功能更清晰:
void * memset ( void * ptr, int value, size_t num );
填充内存块。将num
指向的内存块的第一个ptr
字节设置为指定的value
(解释为unsigned char)。
的参数强> 的
例如,您的程序中的以下代码块:
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
可以通过memset
以更清洁的方式实现:
memset(a[i], 0, n * sizeof(int));
memset(b[i], 0, n * sizeof(int));