正装可以穿牛仔裤吗:c 数组 字符串

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 17:30:51
C语言速成手册(三):数组、字符串、结构 Program Impossible | 2007-06-08 2:03| 14 Comments | 本文内容遵从CC版权协议 转载请注明出自matrix67.com

一维数组的定义、初始化和使用
定义一个一维数组的格式如下:
类型 数组名[数组大小];
数组的下标范围总是从0开始(因此下标最大为数组大小减一)。下面一行语句定义了一个大小为10的长整型数组:
long value[10];
这相当于下面的Pascal语句:
var value:array[0..9]of longint;
C语言的数组范围左端点不能自定义,它的数组下标只能从0开始。

下面几种方式可以在定义数组的同时进行初始化:
long value[10] = { 0, 8, 2, 0, 3 } ;
long value[10] = { [1]=8, [2]=2, [4]=3 } ;
上面两个语句是等价的。其中前一种方法依次对数组的前5个数进行初始赋值,后一种方法仅对数组的其中三个位置进行初始化。初始化中没有涉及到的下标所对应的数值自动被设为0。
C语言允许数组的大小为一个变量,但这样的数组在定义时不能像上面一样进行初始化。
这种初始化方法只在定义数组时用,不能用于程序中的赋值。数组之间也不能直接赋值,你不能把数组a整个赋值给数组b。

程序中使用数组的方法和Pascal一样。下面的程序将输出1000以内的素数:
#include
#include
int main()
{
bool isPrime[1000];
int i,j;

for(i=2;i<1000;i=i+1)
isPrime[i]=true;

for(i=2;i<1000;i=i+1)
{
if (isPrime[i])
{
printf("%d ",i);
for(j=2*i;j<1000;j=j+i)
isPrime[j]=false;
}
}

return 0;
}

当一维数组作为函数参数时,数组大小可以不写,以适应不同长度的数组。通常你还需要另一个参数告诉函数你的数组有多大。下面这个函数返回数组中的最大值:
long maxValue ( long length, long array[] )
{
long i, max = 0;
for ( i=0; iif (array[i]>max) max = array[i];
return max;
}

下面的代码合法地调用了上面的函数。
long a[5] = { 1, 5, 7, 3, 4 };
printf( "%d" , maxValue( 5,a ) );



C语言中的字符串
C语言也使用字符数组作为字符串。定义一个char a[20],就相当于定义了一个长度不超过20的字符串。Pascal中使用a[0]记录字符串的长度,字符串内容从a[1]开始;但C语言并不直接记录字符串长度,a[0]表示字符串的第一个字符,最后以ASCII码0(或写成字符'\0')标记字符串结尾。你可以直接将一个字符串赋给字符数组,也可以在printf中使用%s标识输出一个字符数组。记住,a[2]表示字符串中的第三个字符,因为C的数组下标是从0开始的。
观察下列代码:
int i;
char a[20]="matrix67.com";

for (i=0;i<20;i=i+1)
printf("%d ",a[i]);
printf("\n%c\n",a[2]);
printf("%s\n",a);
printf("%16s\n",a);
printf("%.8s\n",a);
printf("%16.8s\n",a);

程序的输出为:
109 97 116 114 105 120 54 55 46 99 111 109 0 0 0 0 0 0 0 0
t
matrix67.com
matrix67.com
matrix67
matrix67

== 或 + 等运算符对字符串无效。

下面的函数返回字符串的字符数:
int stringLength( char a[] )
{
int count=0;
while ( a[count] )
count=count+1;
return count;
}


赋值时,如果字符串太长了,有两种方法可以让你分行写。一是在行末加一个反斜杠表示和下一行相连,二是每一行都用双引号注明(编译器会自动把它连接起来)。下面两个代码是等价的。注意第一个代码中的第二行必须顶格写,否则第二行前面的空格也要算进字符串里。
char blogTitle[100]="Matrix67: My Blog - 50% Informatics, 50% \
Mathematics, and 50% Imagination";

char blogTitle[100]="Matrix67: My Blog - 50% Informatics, 50% "
"Mathematics, and 50% Imagination";


和数组一样,对字符串的赋值只能在定义时使用,程序中不能这样做。


多维数组的定义、初始化和使用
定义一个多维数组的格式如下:
类型 数组名[大小1][大小2]...[大小n];
例如,下面这个语句定义了一个三维数组:
int matrix[100][100][2];
同样地,每一维的大小都是从0开始算的。因此上面的语句相当于Pascal中的:
var matrix:array[0..99][0.99][0..1]of integer;

多维数组的初始化和一维数组类似。例如,我们经常需要定义方向常量:
const int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
这还可以直接写成:
const int dir[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
多维数组的初始化同样是未定义者自动填零,因此还可以写成:
const int dir[4][2] = { [0][0]=1, [1][1]=1, [2][0]=-1, [3][1]=-1 };

程序中使用多维数组时必须用多个方括号,即dir[2][1]不能写成dir[2,1]。

当多维数组作为函数的参数时,只有第一维的大小可以不写。因此,下面的三个函数中前两个是合法的,第三个是不合法的。
long function_1( int m, int n, long a[20][20] );
long function_2( int m, int n, long a[][20] );
long function_3( int m, int n, long a[][] );

为了让参数仍然适用于各种大小的数组,C语言允许这样定义函数:
long function_4( int m, int n, long[m][n] );
例如,下面的函数递归地计算行列式:
long determinant( int n, long a[n][n] )
{
if (n==1) return(a[0][0]);

int i,j,k;
long ans = 0;
long sub[n-1][n-1];

for ( i=0; i{
for ( j=1; j{
for ( k=0; ksub[j-1][k]=a[j][k];
for ( k=i+1; ksub[j-1][k-1]=a[j][k];
}
ans = ans + (1-i%2*2)*a[0][i]*determinant(n-1, sub);
}
return ans;
}

下面的代码片段正确地调用了上面的函数:
long a[4][4]={
{ 1, 4, -1, 4 },
{ 2, 1, 4, 3 },
{ 4, 2, 3, 11 },
{ 3, 0, 9, 2 }
};
printf( "%d" , determinant(4,a) );


结构的定义、初始化和使用
Pascal中的记录类型在C语言中叫做“结构”。定义一个结构的方式如下:
struct 结构名
{
在此定义若干变量(域)
};

注意花括号后面需要有一个分号。下面定义一个date结构:
struct date
{
int year;
short month,day;
};

这样你就获得了一个名为struct date的类型名。和变量的定义一样,一个结构的定义只能供当前函数(的当前语句块)中后面的部分使用。因此通常把结构的定义放在所有函数的前面作为一个全局的定义。之后,你便可以写这样的语句:
struct date today;

结构的使用方法同Pascal的记录类型一样。例如,下面的函数用于计算某一天是星期几(Zeller公式):
int zeller( struct date t )
{
if (t.month<3)
{
t.year = t.year - 1;
t.month = t.month + 12;
}
int c = t.year / 100;
int y = t.year % 100;
int ans = ( c/4 - 2*c + y + y/4 + (26*(t.month+1))/10 + t.day - 1 ) % 7;

if (ans>0) return ans;
else return ans+7;
}


给一个结构赋初始值和数组的初始化差不多。下面两个语句是等价的:
struct date myBirthday = { 1988, 5, 16 };
struct date myBirthday = { .year=1988, .month=5, .day=16 };
这种方法也可以用于程序中的赋值操作,但需要加上一个类型转换(见这里的“名词动用”一节)。例如,下面三个代码片段都是等价的:
myBirthday.year = 1988;
myBirthday.month = 5;
myBirthday.day = 16;

myBirthday = (struct date){ .year=1988, .month=5, .day=16 };
myBirthday = (struct date){ 1988, 5, 16 };
下面的语句调用了zeller函数,输出自1583年来的每个13日都是星期几。和本文无关的问题:有人知道为什么我从1583年开始算么?
int y,m;
for ( y=1583; y<=2000; y=y+1)
for ( m=1; m<=12; m=m+1 )
printf( "%d ", zeller( (struct date){y,m,13} ) );


Matrix67原创
转贴请注明出处