c语言二维数组Word文档下载推荐.docx
《c语言二维数组Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《c语言二维数组Word文档下载推荐.docx(11页珍藏版)》请在冰豆网上搜索。
intarray[5][10];
这时形参数组只取实参数组的一部分,其余部分不起作用。
[原文结束]
大家可以看到,将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。
根据编译原理可知,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。
但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,这就难办了,编译器不能识别啊,怎么办呢?
不要着急,编译器虽然不能识别,但是我们完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随机的参数,例如:
voidFunc(intarray[3][10]);
voidFunc(intarray[][10]);
变为:
voidFunc(int**array,intRowSize,intLineSize);
在转变后的函数中,array[i][j]这样的式子是不对的(不信,大家可以试一下),因为编译器不能正确的为它寻址,所以我们需要模仿编译器的行为把array[i][j]手工转变为:
*((int*)array+LineSize*i+j);
即把二维数组当作一维数组来处理,这是比较容易理解的方式。
其它方式见下面总结的第二点。
数组作为形参的问题总结:
1一维数组作为函数形参
数组作为形参时,编译器通常只会检查数组形参关联的实参,检查的项目包括实参是不是指针、指针类型和数组元素的类型是否匹配,但不会检查数组的长度。
voidprint(int*a[])
voidprint(
int*a[10]
)
int*a
上面两个都是二级指针,下面一个是一级指针
在很多情况下,将数组形参直接定义为指针要比使用数组语法定义方便很多。
因为定义为指针后,函数可以借助于指针方便的操作数组元素。
数组以非引用类型的传递时,此时数组会自动转换为同类型的指针,即初始化为相应类型实参的副本。
调用函数时,函数实际操作的是指针的副本,而不会修改实参指针的值,但是可以通过指针改变数组元素的值。
2多维数组的传递
多维数组的元素本身就是数组。
对二维数组的处理可以采用将二维数组看作一维或者二维数组来处理,下面两个例子分别采用了这两种方法。
第3个例子有点不同,但实际上也是利用了一维数组作中间过渡处理。
例1将二维数组当作一维数组来处理:
//print_array和主函数中的循环printf实现了同样效果
#include<
stdio.h>
voidprint_array(int*p,intRowSize,intLineSize)
{
inti,j;
for(i=0;
i<
RowSize;
i++)
for(j=0;
j<
LineSize;
j++)
printf("
%d"
*(p+i*LineSize+j));
\n"
);
}
voidmain()
{
inti,j,a[3][3]={{1,0,0},{0,1,0},{0,0,1}};
print_array((int*)a,3,3);
for(i=0;
i<
3;
for(j=0;
j<
*(*(a+i)+j));
例2将二维数组依旧当作二维数组来处理
下面是一个字符串数组的参数传递程序,实现将字符串数组中的字符串按照从小到大的顺序进行排序:
//WordSort实现了对5个字符串的排序
#include"
stdio.h"
stdlib.h"
string.h"
voidWordSort(charp[][10],intRowSize)
intn=0,m;
chartemp[10];
for(n=0;
n<
RowSize;
n++)
for(m=n+1;
m<
m++)
if(strcmp(p[m],p[n])<
0)
strcpy(temp,p[n]);
strcpy(p[n],p[m]);
strcpy(p[m],temp);
5;
++n)
Insubfunction:
%s\n"
p[n]);
voidmain()
intk=0;
charword[5][10];
for(;
k<
++k)
scanf("
%s"
&
word[k]);
WordSort(word,5);
sortedword:
for(k=0;
k++)
Inmainfunction:
word[k]);
system("
pause"
例3用“行指针”传递参数
运行下面程序:
/************************************/
//二维数组作为形参的参数传递方式之一
voidprint_array_1(int(*a)[3],intRow_Size)
intj;
3*Row_Size;
(*a)[j]);
if(j%3==2)printf("
voidprint_array_2(int(*a)[3],intRow_Size)
Row_Size;
i++)
j++)
inti,j,value=0;
inta[4][3]={0};
4;
a[i][j]=value++;
print_array_1(a,4);
print_array_2(a,4);
}
这个程序中的两个函数实现了相同的功能:
打印数组元素。
这种方法可能容易使人迷惑:
int(*a)[3]是什么东西呢?
还得看强哥的书(P229-P230),上面这样写道(在本例中):
*a有3个元素,每个元素为整型。
也就是a所指向的对象是有3个整型元素的数组,即a是行指针。
再强调一遍int(*a)[3]中括号的作用,如果不明白它的重要性,请仔细对比本文章黄色背景的代码。
补充一点,用这个方法处理字符串数组(字符型二维数组),还是比较方便的:
用这样一个例子结束本文:
//打印数组内字符串(一行)
voidprint_string(char(*string)[20],intRow_Size)
inti;
string+i);
chara[6][20]={"
God"
"
bless"
you"
who"
help"
themselves"
};
print_string(a,6);
数组,指针
随笔-11
文章-0
评论-16
关于int*a;
int&
a;
*a;
int*&
a
上述的四条语句,前面两个很好理解,而后面两个,大部分C++初学者都会比较困惑,今天我也是查阅了一些资料以后才恍然大悟。
下面具体来说明一下:
inti;
int*a=&
i;
//这里a是一个指针,它指向变量i
int&
b=i;
//这里b是一个引用,它是变量i的引用,引用是什么?
它的本质是什么?
下面会具体讲述
int*&
c=a;
//这里c是一个引用,它是指针a的引用
*d;
//这里d是一个指针,它指向引用,但引用不是实体,所以这是错误的
数组和指针参数是如何被编译器修改的?
“数组名被改写成一个指针参数”规则并不是递归定义的。
数组的数组会被改写成“数组的指针”,而不是“指针的指针”:
实参
所匹配的形参
数组的数组
charc[8][10];
char(*)[10];
数组指针
指针数组
char*c[10];
char**c;
指针的指针
数组指针(行指针)
char(*c)[10];
char(*c)[10];
不改变
指针的指针
char**c;
#include"
stdafx.h"
#include<
iostream>
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
intarr1[3];
intarr2[3];
intarr3[3];
int*ptr;
//ptr1是一个指向int[3]的指针,即ptr的类型和&
arr1的类型是一样的,注意:
arr1指向的内存区域定长
intptr1[3][3]={{1,2,3},{1,2,3},{1,2,3}};
//ptr2是一个指向int*的指针,即ptr2的类型和&
ptr是一样的,注意:
ptr指向的内存区域不定长
int*ptr2[3]={arr1,arr2,arr3};
//ptr3是一个指向int[3]的指针,即ptr3的类型和&
int(*ptr3)[3]=&
arr1;
ptr3=ptr1;
//没错,他们的类型相同
//ptr3=ptr2;
//error无法从“int*[3]”转换为“int(*)[3]
//ptr4是一个指向int*的指针,即ptr4的类型和&
int**ptr4;
//ptr4=&
//error无法从“int(*)[3]”转换为“int**
ptr4=ptr2;
//ptr4=ptr3;
//error无法从“int(*)[3]”转换为“int**
return0;
}
n个人的生日不重复的概率是P=N!
/(N^n*(N-n)!
),其中N=365,一年的天数。
根据这个公式就可以解决第一问;
写程序模拟:
for(intm=0;
要统计几次;
{
for(inti=0;
人数;
生日[i]=rand()*N+1;
//产生1-365的数
//判断生日数组里的数是否重复
记录不重复的次数
最后,不重复的次数除以要统计的次数就是计算机模拟生日不重复的概率。
以上是方法,代码就自己写吧,不难写
importjava.util.HashSet;
importjava.util.Set;
publicclassIsRepeated{
publicstaticvoidmain(String[]arg){
System.out.println(isRepeated2(newint[]{1,2,3,4,5,5}));
publicstaticbooleanisRepeated(int[]nums){
booleanflag=false;
for(inti=0;
i<
nums.length;
i++){
for(intj=i+1;
j<
j++){
if(nums[i]==nums[j]){
flag=true;
break;
returnflag;
publicstaticbooleanisRepeated2(int[]nums){
Set<
Integer>
set=newHashSet<
();
for(inti=0;
if(!
set.add(nums[i])){
hao192012-01-09
1、c++中也可以用printf格式输出。
2、包含了iomanip头文件,cout也能格式输出。
具体看:
iomanip>
这里面iomanip的作用比较多:
主要是对cin,cout之类的一些操纵运算子,比如setfill,setw,setbase,setprecision等等。
它是I/O流控制头文件,就像C里面的格式化输出一样.以下是一些常见的控制函数的:
dec置基数为10相当于"
%d"
hex置基数为16相当于"
%X"
oct置基数为8相当于"
%o"
//作用永久
sample:
cout<
<
12<
hex<
oct<
12;
output12c1414
setprecision(n)设显示小数精度为n位//作用永久
setf(ios:
fixed);
setprecision
(2)<
2.345<
endl;
ouput2.34//注意先用setf(ios:
:
否则结果自己测试下
setw(n)设域宽为n个字符//作用临时
这个控制符的意思是保证输出宽度为n。
如:
cout<
setw(3)<
1<
10<
100;
输出结果为
110100(默认是右对齐)当输出长度大于3时(<
1000),setw(3)不起作用。
setfill(c)设填充字符为c
setioflags(ios:
fixed)固定的浮点显示
scientific)指数表示
samplecout<
setiosflags(ios:
fixed)<
output2.34
setiosflags(ios:
left)左对齐
right)右对齐
skipws)忽略前导空白
uppercase)16进制数大写输出
lowercase)16进制小写输出
showpoint)强制显示小数点
showpos)强制显示符号
cout<
uppercase)<
15<
outputCF
setioflags(ios:
showpoint)<
x<
若floatx=1,则output1.000000不使用直接输出1
showpos)<
output+1
classFenShu
public:
FenShu(intFen_Zi=1,intFen_Mu=1);
voidadd(constFenShu&
a);
voidshow();
intFenzi(){returnFenZi;
intFenmu(){returnFenMu;
intGCD(intFenZi,intFenMu);
friendFenShuoperator+(FenShu&
a,const