C语言 char型 二维数组问题 急!!!

From Admin
Begin2 - Unit1 - 扫雷

背景 Background
这里是TYVJ-begin2系列的第一道,欢迎您的到来。
这个系列主要是帮助NOIP普及组的朋友在赛场上获得一个较好的成绩设计的一个配套题库
UNIT1主要是针对一些模拟题、简单的数据结构(栈和队列)、以及简单的高精度训练
共10道

描述 Description
小菜二白在用电脑的过程中突然发现Windows还有自带的游戏这下可把二白乐坏了。。可是新的问题随之而来。。就是二白不会玩儿。这不他又迷上扫雷了。来找你帮忙了。。
二白已经知道了雷(用‘*’表示)的分布地点了,。可是他却不知道其余地方的数字代表这什么。细心的你给他解释道:“点开的数字是几,则说明该数字旁边的8个位置中有几个雷”。
现在已知一个雷的分布图,而你的任务就是把他的数字图形计算出来。
例:
地雷分布 数字分布
0*0*0 1*2*1
00000 11211
00000 00000
(注意,地雷分布中,不光是以0来表示无地雷,其他数字都可以表示无地雷)
下面的就看你了。。。

输入格式 Input Format
第一行 两个整数n,m分别表示行数和列数。(0<n<2000,0<m<2000)
第二行到第N+1 行
输入雷的排布图0表示空地。*表示雷

输出格式 Output Format
N行,
雷的数字排布图。

样例输入 Sample Input
3 5
0*0*0
00000
00000

样例输出 Sample Output
1*2*1
11211
00000

时间限制 Time Limitation
1s

注释 Hint
不要想的太多!

来源 Source
tyvj原创

以下想问一个问题:::

C语言中,定义char型,题目说是2000*2000【max】

但是。。。用char a[2000][2000];

系统会报错。。。

此题测试数据最后一个就是极其变态的。。。

于是我就只有80分。。。

Vijos compatible layer: 1.2 build 100204
Judge status: RuntimeError

VijosNT Judger: 1.2 build 100318

Compiler: G++
g++ -O2 -g -otest.exe test.cpp

Test #1: Accepted... 0ms
Test #2: Accepted... 0ms
Test #3: Accepted... 0ms
Test #4: Accepted... 78ms
Test #5: Runtime Error
C0000005
EXCEPTION_ACCESS_VIOLATION
Attempt to read 30303034
Traceback: test.cpp at line 13

Total score: 80, time usage: 78ms

求各位大牛::::

怎样才能使C中定义的char数组更多一些。。。。。

不要求多少,只要求能到2100*4200就行了。。。

或者此题有另种解法的。。。说一下。。。

谢各位神牛!!!!不尽感激!!!!
修改后代码:
main()
{
int n,m,i,j;
scanf("%d %d\n",&n,&m);
char **b,c;
b= (char **)malloc( (n+2) * sizeof(char) );
for( i = 0 ; i < n+2 ; i++ )
b[i] = (char *)malloc( (m+2) * sizeof(char) ); /*插入这个就行了*/
for(i=0;i<n+2;i++)
for(j=0;j<m+2;j++)
b[i][j]='0';
for(i=1;i<=n;i++)
{for(j=1;j<=m;j++)
{c=getchar();
if(c=='*')
{b[i][j]='*';
if(b[i-1][j-1]!='*') b[i-1][j-1]++;
if(b[i-1][j]!='*') b[i-1][j]++;
if(b[i+1][j-1]!='*') b[i+1][j-1]++;
if(b[i+1][j]!='*') b[i+1][j]++;
if(b[i-1][j+1]!='*') b[i-1][j+1]++;
if(b[i+1][j+1]!='*') b[i+1][j+1]++;
if(b[i][j-1]!='*') b[i][j-1]++;
if(b[i][j+1]!='*') b[i][j+1]++;
}
}
c=getchar();
}
for(i=1;i<=n;i++)
{for(j=1;j<=m;j++)
printf("%c",b[i][j]);
printf("\n");
}
}

20分。第一个点过了。后面全部
Runtime Error.....

四楼的观点有错误。动态数组能够分配的内存显然比静态数组大很多。
可以用动态数组,我的想法是用结构体,如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct st{
char *s;
}st;
void main(void)
{
int i;
st *p = (st *)malloc( 2200 * sizeof(st) );
// p为数组的指针,也可以改成不用结构,不过哪样看起来就有些乱了
// char **p= (char **)malloc( 2200* sizeof(char));
// 其内容是分配大小为2200*siseof(st)大小的空间,也就是2200*2
// 结构中仅有一个指针,大小为2字节
for(i = 0 ; i < 2200 ; i++)
p[i].s = (char *)malloc( 4000 * sizeof(char));
//这里相应的改成p[i]=(char *)malloc(4000*sizeof(char));
//内容相同。可以看看下面对malloc的解释
printf("内存分配成功!\n");
}
这个部分在VC6.0中能够正确运行,希望能够解决你的问题。
这个malloc就是动态分配内存,具体的用法为
原型:extern void *malloc(unsigned int num_bytes);
头文件:在TC2.0中可以用malloc.h或 alloc.h (注意:alloc.h 与 malloc.h 的内容是完全一致的),而在Visual C++6.0中可以用malloc.h或者stdlib.h。
功能:分配长度为num_bytes字节的内存块
返回值:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
说明:关于该函数的原型,在旧的版本中malloc返回的是char型指针,新的ANSI C标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
main()
{ int n,m,i,j;
scanf("%d %d\n",&n,&m);
char **b,c;
b= (char **)malloc( n * sizeof(char) );
for( i = 0 ; i < n ; i++ )
b[i] = (char *)malloc( m * sizeof(char) ); /*插入这个就行了*/
for(i=0;i<n+2;i++)
for(j=0;j<m+2;j++)
b[i][j]='0';
for(i=1;i<=n;i++)
{for(j=1;j<=m;j++)
{c=getchar();
if(c=='*')
{b[i][j]='*';
if(b[i-1][j-1]!='*') b[i-1][j-1]++;
if(b[i-1][j]!='*') b[i-1][j]++;
if(b[i+1][j-1]!='*') b[i+1][j-1]++;
if(b[i+1][j]!='*') b[i+1][j]++;
if(b[i-1][j+1]!='*') b[i-1][j+1]++;
if(b[i+1][j+1]!='*') b[i+1][j+1]++;
if(b[i][j-1]!='*') b[i][j-1]++;
if(b[i][j+1]!='*') b[i][j+1]++;
}
}
c=getchar();
}
for(i=1;i<=n;i++)
{for(j=1;j<=m;j++)
printf("%c",b[i][j]);
printf("\n");
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-08-06
123L的都不对。你们想想,如果静态数组不行,动态的应该也不行,因为都是线性数组,这么大的数据量,内存不足是很随意就出现的,而且不安全。你可以试试看用链式的数组,也就是说,你可以创建一维数组的链表,这样每次要2000个数据,然后一个next域,结构如下:

struct MineMap
{
char Line[2000];
struct MineMap * next;
}

然后你只需要创建这个数据结构的对象2000个(用循环),然后用next域把他们链接起来就OK了,懂了么?

我的思想有误?你们都搞清楚顺序表为什么比链式表容易开辟失败了么?我说的做法也要malloc,也是在堆上用内存。看清楚在说
第2个回答  2010-08-08
各位说的 我就不明白了 在main函数外面定义 只要数组总容量不超过0x7fffffff就可以了 我随便定义了一个 char a[25000][25000];
在main函数里面受堆栈的限制好像开到很小的 具体多少忘了本回答被提问者采纳
第3个回答  2010-08-06
回答者: MCG890414
的说法也太夸张了,虽然说2000个2000元素在理论上比2000*2000个连续元素
更容易分配到,
但如果说内存分配沦落到计算内存碎片的地步的话,那就应该自己做内存分配机制,或者说直接转成外存来实现

对于一般程序来说 XP默认的4G寻址空间已经足够,不用考虑那么多

---------------------
int *p = (int*)malloc( 2000*2000);

(x,y) = p[y*2000+x];

c++里更方便一点

int (*p)[2000] = new int[2000][2000]
(x,y) = p[x][y];

---------------------------

一般思路是到空地查找八向的雷,得到数字
但由于雷的数量要远远小于空地的数据

所以应该反过来,把雷的八向空地加一
第4个回答  2010-08-06
你的代码:
scanf("%d %d\n",&n,&m);
char b[n+2][m+2],c;
编译时不可能通过。

如果静态定义方式下内存不足,只有动态申请,别无它法。