2001 上半年程序员考试真题及答案-下午卷
试题一
阅读下列程序或函数说明和 C 代码,将应填入__(n)__处的字句写在答题纸的对应栏
内。
[函数 1.1 说明]
函数 strcmp ()是比较两个字符串 s 和 t 的大小。若 s < t 函数返回负数;若 s = t
函数返回 0;若 s > t,函数返回正数。
[函数 1.1]
int strcmp (char *s,char *t)
{ while ( *s && *t && __(1)__){
s++;t++ ;
}
return __(2)__;
}
[程序 1.2 说明]
在 n 行 n 列的矩阵中,每行都有最大的数,本程序求这 n 个最大数中的最小一个
[程序 1.2]
#include〈stdio.h〉
#define N 100int a[N][N];
void main()
{ int row ,col ,max ,min ,n;
/*输入合法 n (〈100 ),和输入 m ×n 个整数到数组 a 的代码略*/
for ( row = 0;row < n;row++) {
for ( max = a[row][0],col = l ;col < n;col++)
if (__(3)__) max = a[row][col];
if (__(4)__) min = max;
else if(__(5)__) min = max;
}
printf ("The min of max numbers is %d\n",min);
}
试题二
阅读下列程序说明和 C 代码,将应填入__(n)__处的字句写在答题纸的对应栏内。
[程序 2 说明]
本程序中的函数 first_insert() 的功能是在已知链表的首表元之前插入一个指定
值的表元;函数 reverse_copy() 的功能是按已知链表复制出一个新链表,但新链表的表元
链接顺序与已知链表的表元链接顺序相反;函数 print_link() 用来输出链表中各表元的值;
函数 free_link()用来释放链表全部表元空间。
[程序 2〕
#include〈stdip.h〉
#include〈malloc.h〉
typedef struct node{ int val;
struct node *next;} NODE;
void first_insert( NODE **p,int v)
{ NODE *q = (NODE *) malloc( sizeof(NODE));
q -> va1 = v;__(1)__; *p = __(2)__;
}
NODE *reverse_copy(NODE *p)
{ NODE *u;
for( u = NULL ; p ; p = p ->next ) first_insert(__(3)__);
return u;
}
void print_link( NODE *p )
{ for( ;__(4)__) printf ("%d\t" , p -> val);
printf("\n");
void free_link(NODE*p)
{ NODE *u;
while( p != NULL){ u=p-〉next;free( p );__(5)__;}
}
void main()
{ NODE *link1 , *link2;
int i ;linkl = NULL ;
for( i = 1;i <= 10 ; i++ )
first insert( &link1,i );
link2 = revere_ copy(link1);
print_link(link1);freeJink(linkl);
print_link(link2);free_link(link2);
}
试题三
阅读下列程序说明和 C 代码,将应填入__(n)__处的字句写在答题纸的对应栏内。
[程序 3 说明]
本程序从若干个原始文件合并成的合并文件中恢复出其中一个或全部原始文件。所有
文件均作为二进制文件进行处理。合并文件中先顺序存储各原始文件,然后顺序存储各原始
文件的控制信息,即文件名、文件长度和在合并文件中的位置(偏移量)。其结构为:
typedef stmct{char fnme[256];/*原始文件名*/
long length;/*原始文件长度(字节数)*/
long offset;/*原始文件在合并文件中的位置(偏移量)*/
}FileInfo;
在合并文件最后存储如下一个特殊的标志信息作为合并文件的结束标记:
F11ek1fo EndF1ag={"Combined File".0,_offset};
其中_offset 是第一个原始文件的控制信息在合并文件中的位置(偏移量)。
启动本程序的命令行的格式是:
程序名
合并文件名[原始文件名]
如果不指定原始文件名,默认恢复合并文件中的所有原始文件。
程序中涉及的部分文件操作的库函数简要说明如下:
int fread(void *buffer,int size,int count,FILE *fbin):从二进制文件流 fbin 中
读取 count 块长度为 size 字节的数据块到 buffer 指向的存储区。返回值为实际读取的数据
块数。
int fwrite(void *buffer,int size,int count,FILE *fbin):各参数和返回值的意
义与 fread 相同,但对文件进行写操作。
int fseek(FILE *fbin,long offset,int position): 将文件流 fbin 的读/写位置
以 position 为基准移动 offset 字节。position 的值可以是 SEEK_SET(文件
头),SEEK_CUR(当前位置),SEEK_END(文件尾);offset 为正表示向文件尾方向移动,为负表
示向文件头方向移动,为零表示到基准位置。
long ftell(FILE *fbin): 返回文件流 fbin 的当前读/写位置(相对于文件头的偏移
量)。上述偏移量均以字节为单位,即偏移字节数。
[程序 3]
#include〈stdio.h〉
#include〈string.h〉
typedef struct{char fname[256];long length;long offset;}
}FileInfo;
void copyfile( FILE *fin, FILE *fout, int fsiz)
{ char buf[1024]; int siz = 1024 ;
while(fsiz != 0) { /*每次复制 siz 个字节,直至复制完 fsiz 个字节*/
if ( siz > fsiz) __(1)__ ;
fread( buf , 1 , siz , fin ) ; fwrite( buf , 1 , siz , fout );
fsiz = __(2)__;
}
}
int dofile( FILE *fin , FileInfo *inp )
{ long offset ;
FILE *fout ;
if ( ( fout = fopen( inp -〉fname , "wb" ) ) = NULL) {
printf ( "创建文件错误: %s\n" , inp -〉fname );
return 1 ;
}
offset = __(3)__ ; /*保留合并文件读/写位置*/
fseek( __(4)__) ; /*定位于被恢复文件首*/
copyfile( fin , fout , inp -〉length ) ;
fclose( fout ) ;
printf( "\n---文件名: %\n 文件长: %1d.\n " , inp -〉fname , inp -〉
length );
}
__(5)__;
return 0 ;
/*恢复合并文件读/写位置*/
int main( int argc ,char *argv[ ] )
{ FileInfo finfo ;
char fname[256] ; FILE *fcmbn;
if (argc < 2) { printf( "输入合并文件名:" ) ; scanf( "%s" , fname ) ; }
else strcpy( fname,argv[1]) ;
if ( ( fcmbn = fopen( fname , "rb" ) ) == NULL) {
printf( "文件打开错误:%s\n" , fname ) ; return 1;
}
fseek( fcmbn ,-sizeof(FileInfo),SEEK END);/*定位于合并文件末尾的标
fread(&finfo,1,sizeof(FileInfo),fcmbn) ;
if ( finfo.length !=0 || strcmp( finfo.fmane , "CombinedFile" ) ) {
printf( "指定的文件不是合法的合并文件\n" ) ;
fclose( fcmbn ) ; return 2 ;
}
fseek(fcmbn,finfo.offset,SEEK_SET );/*定位于首个原始文件的控制信息
for ( ; ; ) { /*恢复一个(argc > 2) 或全部 ( argc = 2 )原始文件*/
fread( &finfo , 1 , sizeof( FileInfo ) , fCmbn ) ;
if ( finfo.length == 0 ) break ;
if ( argc > 2 && strcmp( finfo.fname , argv[2] ) ) continue ;
if ( dofile( fcmbn , &finfo ) != 0 ) break ;
}
fclose( fcmbn ) ; return 0 ;
志信息*/
*/
}
试题四
阅读下列程序说明和 C 代码,将应填入__(n)__处的字句写在答题纸的对应栏内。
[程序 4 说明]
设一个环上有编号为 0~n-1 的 n 粒不同颜色的珠子(每粒珠子颜色用字母表示, n
粒珠子颜色由输入的字符串表示)。以环上某两粒珠子间为断点,从断点一方按顺时针方向取
走连续同色的珠子,又从断点另一方按逆时针方向对剩下珠子取走连续同色的珠子,两者之
和为该断点可取走珠子的粒数。移动断点,能取走的珠子数不尽相同。本程序找出可以取走
最多的珠子数及断点的位置。程序中用双向链表存储字符串。例如,编号为 0-9 的 10 粒珠子
颜色的字符串为“aaabbbadcc",对应链表为:
若在 2 号与 3 号珠子间为断点,共可取走 6 粒珠子,且为取走的珠子数最多。
[程序 4]
#include〈stdio.h〉
#include〈string.h〉
#include〈malloc.h〉
typedef struct node { char d ;
struct node *fpt ; /*后继指针*/
struct node*bpt ; /*前趋指针*/
}NODE ;
NODE *building( char *s ) /*生成双向循环链表*/
{ NODE *p = NULL , *q ;
while ( *s ){
q = ( NODE * ) malloc( sizeof( NODE ) ) ;
q -> ch = *s++ ;
if ( p = NULL ) p = q -> fpt = q -> b t = q ;
else {
p -> bpt -> fpt = q ;
q -> fpt = p ;
q -〉bpt = __(1)__;
__(2)__ ;
}
}
return
}
int count( NODE *start , int maxn ,int step ) /*求可取走珠子粒数*/
{ int color ,c ;
NODE *p ;
color = -1 ; C = 0 ;
for ( p = start ; c O ? p -> fpt ; p -> bpt ){
if ( color == -1 ) color = p -> ch ;
else if (__(3)__) break ;
c++
}
return
}
int find ( char *s ,int *cutpos ) /*寻找取走珠子数最多的断点和粒数*/
{ int i , c , cut , maxc = 0 ,1en = strlen(s) ;
NODE *p ;
if ( ( p = building(s) ) = NULL ){ *cu1tpos = -1 ; return -1 ; }
i = 0 ;
do { c = count( p , 1en ,1 ) ;
c = c + __(4)__ ;
if ( c > maxc ) { maxc = c ; cut = i ; }
__(5)__ ;
i++ ;
} while (i < len ) ;
* cutpos = cut ;
return maxc ;
}
void main()
{ int cut , max ;
char s[120] ;
scanf( , %s', s ) ;
max = find( s , &cut ) ;
printf ( "Cut position = %d , Number = %d.\n" , cut , max ) ;
}
试题五
阅读下列程序说明和 C 代码,将应填入__(n)__处的字句写在答题纸的对应栏内。
[程序 5 说明]
本程序采用递归算法将一个自然数 n 分解成不多于 m 个整数之和。设构成和数 n
的各个整数取于数组 d ,d 中的整数互不相等且由大到小存储。
例如,数组 d 中存储以下整数: d[] = {100 ,81 ,64 ,49 ,36 ,25 ,16 ,9 ,4 ,1} ,
则有:
n m 程序运行后的输出
100 2
100 = 100
13 2
13 = 9 + 4
No
14 2
answer
超过 2 个)
(9+4+1
71 5
71 = 49 + 9 + 9 + 4
(表示可重复
取数)
函数 End()的形参 c 表示 d 中可取的整数个数;形参 pd 指向能成为和数的整数的
存放位置。
[程序 5]
#include〈stdio.h〉
#define N 20
int find( int n ,int m ,int *d ,int c ,int *pd )
{ int r ;
if ( n == 0 ) return 0 ;
if ( m == 0 || c == 0 ) return -1 ;
if ( __(1)__ ) return find( n ,m , d+1 ,c-1 ,pd ) ;
else { *pd = *d ;
/* 已分解完成 */
/* 不可以分解 */
r = find( __(2)__ ,d , c , __(3)__ ) ;
/* 继续对剩余数作
分解 */
if ( r >= 0 ) return __(4)__ ;
return find( n ,m , __(5)__ ,pd ) ;
}
}
void main()
{ int n ,m ,k ,i ,p[N] ,*pptr = p ;
int d[ ] = { 100, 81, 64, 49, 36, 25, 16, 9, 4, 1 } ;
printf( "Enter n , m : " ; scanf( %d %d ,&n ,&m );
k = find( n , m , d , 10 , pptr ) ;
if ( k <= O ) printf ( "No answer!\n" ) ;
else{ printf( "%d = %d" , n , p[0] ) ;
for ( i = l ; i < k ; i++ )
printf(" +%d" , p[i] ) ;
printf("\n");
}
试题一
(1) *s == *t
(2) *s - *t
参考答案
试题二
(1) q ->ncxt = *p
(2) q
(3) a[row][col] > max
(3) &u ,p->val
(4) row == 0
(5) max < min
试题三
(1) siz = fsiz
(2) fsiz-siz
(3) ftell(fin)
(4) p != NULL; p = p->next
(5) p = u
试题四
(1) p->bpt
(2) p->bpt = q
(3) p->ch != color
(4) fin,inp->offset, SEEK_SET
(4) eount(p-bpt,len-c,-1)
(5) feesk(fin ,offset, SEEK_SET)
(5) p = p->fpt
试题五
(1) n<*d
(2) n-*d ,m-1
(3) pd+1
(4) r+l
(5) d+1 ,c-1