C 2012年笔试题
1指出程序段中的错误:分析错误的原因,并进行修改#
1.1函数 swap 将两个字符串(字符数组作实参,长度不超过 100)的内容进行交换#
1234567void
swap(
char
*pa,
char
*pb)
{
char
*temp;
temp=pa;
pa=pb;
pb=temp;
}
错误原因:只是将 swap 中的局部变量 pa 和 和 pb 的值进行了交换,而作为实参的字符数组中 的内容并没有改变
改正一:
123456789101112void
swap (
char
*pa ,
char
*pb )
{
if
(
strlen
(pa)!=
strlen
(pb))
exit
(-1);
//若长度不一致,则返回
char
tmp;
int
i=-1;
while
(pa[++i])
{
tmp=pa[i];
pa[i]=pb[i];
pb[i]=tmp;
}
}
全部代码:
12345678910111213141516171819202122232425262728293031#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
swap (
char
*pa ,
char
*pb )
{
if
(
strlen
(pa)!=
strlen
(pb))
exit
(-1);
char
tmp;
int
i=-1;
while
(pa[++i])
{
tmp=pa[i];
pa[i]=pb[i];
pb[i]=tmp;
}
}
void
input(
char
*p)
{
while
(p)
{
printf
(
"%d\t"
,*p);
p++;
}
}
int
main()
{
char
a[] =
"hello"
,b[] =
"world"
;
swap(a,b);
printf
(
"交换后:\na=%s\nb=%s"
,a,b);
return
0;
}
改正二:
12345678void
swap (
char
*pa ,
char
*pb )
{
if
(
strlen
(pa)!=
strlen
(pb))
exit
(-1);
char
tmp[100];
strcpy
(tmp,pa);
strcpy
(pa,pb);
strcpy
(pb,tmp);
}
全部代码:
123456789101112131415161718192021222324252627#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
swap (
char
*pa ,
char
*pb )
{
if
(
strlen
(pa)!=
strlen
(pb))
exit
(-1);
char
tmp[100];
strcpy
(tmp,pa);
//strcpy(s1,s2):将字符串s2复制到s1中
strcpy
(pa,pb);
strcpy
(pb,tmp);
}
void
input(
char
*p)
{
while
(p)
{
printf
(
"%d\t"
,*p);
p++;
}
}
int
main()
{
char
a[] =
"hello"
,b[] =
"world"
;
swap(a,b);
printf
(
"交换后:\na=%s\nb=%s"
,a,b);
return
0;
}
1.2程序片段:#
错误点一:pb[1]=’A’, 错误原因:pb 指向一个常量字符串,不可修改其串中某个元素。
错误点二:strcpy(pa,”ABCDEFGXYZ”), 错误原因:pa 字符数组长度不够,导致溢出
2简答题(共 30 分)#
2.1设 arr 为整型数组,num 和 item 为整型变量,N=数组元素个数-1。需要查找 item 是否在数组中,如果程序片段为 for(num=N;arr[num]!=item;num--); printf(“%d\n”,num); 可能导致的异常结果是什么?为什么?(8 分)【见2014 2.1】#
异常结果:num 为负数,当查找的 item , 不在数组中的时候,num 会变为负数,直至找着 item,
这时查找已经越界了
2.2 设有递归函数 #
12345678910int
value(
int
n)
{
int
x;
if
(n==0)return0;
else
{
scanf
(“%d”,&x);
return
(value(n-1)+x);
}
}
如该函数被调用时,参数 n 值为 4,输入的 x 的值依次为 11,22,33,44,函数调用结束时返回值是多少?并用图描述函数递归执行过程。(10 分)
程序段的功能是将输入的 n 个值求和,因此返回值是:11+22+33+44=110。
函数递归执行过程:2.3数组作为函数参数有三种形式: 1)实参是数组元素; 2)形参是指针,实参是数组; 3)函数的形参和实参都是数组分别是采用什么参数传递方式?(5 分)#
参数传递方式分别为:传值、 传地址、传地址。
2.4采用高度抽象概念有利于程序设计,C 语言中循环语句 do s while(B);对应的显示控制结构是什么?请使用伪代码形式(通过条件转移指令)表达。(7 分) #
循环控制结构
12label: s;
If(B)
goto
label;
3 程序设计(共 45 分,每题的算法 50%,语法 30%,完整 20%) #
3.1 利用 2 个函数对输入的两个分数进行加、减、乘、除四则运算和输出用分数表示的结果。(注:输入格式为:%ld/%ld%c%ld/%ld,输出格式为%ld/%ld),例如:输入 1/4+1/3,输出:7/12 (10 分)#
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859#include<stdio.h>
#include<stdlib.h>
long
fz1,fm1,fz2,fm2,fz3,fm3;
char
op;
//求a,b的最大公约数
long
gcd(
long
a,
long
b)
{
int
r;
while
(b)
{
r=a%b;
a=b;
b=r;
}
return
a;
}
void
compute()
{
long
zxg;
switch
(op)
{
case
'+'
:
case
'-'
:
zxg=fm1*fm2/gcd(fm1,fm2);
// zxg是fm1和fm2的最小公倍数
fz1=zxg/fm1*fz1;
fz2=zxg/fm2*fz2;
if
(op==
'+'
)
fz3=fz1+fz2;
else
fz3=fz1-fz2;
fm3=zxg;
break
;
case
'*'
:
fz3=fz1*fz2;
fm3=fm1*fm2;
break
;
case
'/'
:
fz3=fz1*fm2;
fm3=fm1*fz2;
break
;
default
:
exit
(-1);
}
zxg=gcd(fz3,fm3);
fz3=fz3/zxg;
fm3=fm3/zxg;
printf
(
"%ld/%ld\n"
,fz3,fm3);
}
int
main()
{
while
(
scanf
(
"%ld/%ld %c %ld/%ld"
,&fz1,&fm1,&op,&fz2,&fm2)!=EOF)
{
compute();
system
(
"pause"
);
}
return
0;
}
3.2 编写函数,将单链表进行逆序,即表头变表尾,表尾变表头(15 分) 【见2017.24】#
3.2.1方法一:头插法#
代码:
1234567891011121314// 方法一:头插法 逆序链表
void
reverseslist1()
{
struct
slist *p,*r;
// p是工作指针,r是p的后继,以防断链
p = head ->next;
//从第一个元素开始
head ->next = NULL;
//将头节点后置null,断开
while
(p != NULL)
{
r = p ->next;
// r暂存s后继
p ->next = head ->next;
// 依次将元素结点摘下
head ->next = p;
p = r;
}
}
全部代码:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364#include <stdio.h>
#include <stdlib.h>
typedef
struct
slist
{
int
data;
struct
slist *next;
};
struct
slist *head;
// 尾插法建立链表
void
creatslist()
{
int
x;
head = (
struct
slist *)
malloc
(
sizeof
(
struct
slist));
//头结点
struct
slist *p,*node;
// q为尾指针
p = head;
printf
(
"请输入元素:"
);
scanf
(
"%d"
,&x);
while
(x != 9999)
{
node = (
struct
slist *)
malloc
(
sizeof
(
struct
slist));
node ->data = x;
p ->next = node;
p = node;
printf
(
"请输入元素:"
);
scanf
(
"%d"
,&x);
}
p ->next = NULL;
}
//链表输出打印
void
inputslist()
{
struct
slist *q;
//q是工作指针
q = head ->next;
//头结点无元素
while
(q != NULL)
{
printf
(
"%d\t"
,q ->data);
q = q ->next;
}
}
// 方法一:头插法 逆序链表
void
reverseslist1()
{
struct
slist *p,*r;
// p是工作指针,r是p的后继,以防断链
p = head ->next;
//从第一个元素开始
head ->next = NULL;
//将头节点后置null,断开
while
(p != NULL)
{
r = p ->next;
// r暂存s后继
p ->next = head ->next;
// 依次将元素结点摘下
head ->next = p;
p = r;
}
}
void
main()
{
creatslist();
inputslist();
printf
(
"\n逆序后:\n"
);
reverseslist1();
inputslist();
}<em id=
"__mceDel"
style=
"background-color: initial; color: rgba(51, 51, 51, 1); font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px"
> </em>
3.2.2方法二:后继指针指向前驱结点 #
代码:
1234567891011121314// 方法二:后继指针指向前驱结点
void
reverseslist2()
{
struct
slist *pre,*p = head ->next,*r =p ->next;
p ->next = NULL;
//处理第一个结点
while
(r != NULL)
// r若为空,则p为最后一个节点
{
pre = p;
p = r;
r = r ->next;
p ->next = pre;
}
head ->next = p;
//处理最后一个结点
}
全部代码:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465#include <stdio.h>
#include <stdlib.h>
typedef
struct
slist
{
int
data;
struct
slist *next;
};
struct
slist *head;
// 尾插法建立链表
void
creatslist()
{
int
x;
head = (
struct
slist *)
malloc
(
sizeof
(
struct
slist));
//头结点
struct
slist *p,*node;
// q为尾指针
p = head;
printf
(
"请输入元素:"
);
scanf
(
"%d"
,&x);
while
(x != 9999)
{
node = (
struct
slist *)
malloc
(
sizeof
(
struct
slist));
node ->data = x;
p ->next = node;
p = node;
printf
(
"请输入元素:"
);
scanf
(
"%d"
,&x);
}
p ->next = NULL;
}
//链表输出打印
void
inputslist()
{
struct
slist *q;
//q是工作指针
q = head ->next;
//头结点无元素
while
(q != NULL)
{
printf
(
"%d\t"
,q ->data);
q = q ->next;
}
}
// 方法二:后继指针指向前驱结点
void
reverseslist2()
{
struct
slist *pre,*p = head ->next,*r =p ->next;
p ->next = NULL;
//处理第一个结点
while
(r != NULL)
// r若为空,则p为最后一个节点
{
pre = p;
p = r;
r = r ->next;
p ->next = pre;
}
head ->next = p;
//处理最后一个结点
}
void
main()
{
creatslist();
inputslist();
printf
(
"\n逆序后:\n"
);
reverseslist2();
inputslist();
}
3.3编写完整程序:接收从键盘输入的仅由数字字符构成的字符串(假设字符串的最大长度为 50),统计并输出每个数字(0~9)的重复次数。(8 分)#
代码:
12345678910111213141516#include<stdio.h>
#include<stdlib.h>
int
main()
{
char
ch;
int
num[10]= {0};
printf
(
"string:\n"
);
//出现次数存储在数组中
while
(
scanf
(
"%c"
,&ch)!=EOF&&ch!=
'q'
)
num[ch-
'0'
]++;
int
i;
for
(i=0; i<10; i++)
printf
(
"%d 出现%d 次\n"
,i,num[i]);
system
(
"pause"
);
return
0;
}
解析:
1while
(
scanf
(
"%c"
,&ch)!=EOF)
C语言中,EOF常被作为文件结束的标志。还有很多文件处理函数处错误后的返回值也是EOF,因此常被用来判断调用一个函数是否成功。
当上面的程序运行时,如果不加" != EOF",那么这个程序就是个死循环,会一直运行下去;加上" != EOF"后该程序就不是死循环了,如果在终端不进行输入该程序会自动结束(while的意思就是说当当前输入缓存还有东西时就一直读取,直到输入缓存中的内容为空时停止)。
结束条件:
在终端(黑框)中手动输入时,系统并不知道什么时候到达了所谓的“文件末尾”,因此需要用<Ctrl + z>组合键然后按 Enter 键的方式来告诉系统已经到了EOF,这样系统才会结束while.
3.4 编写完整程序,采用结构数组和指向结构的指针,接收输入的 100 个学生信息(包括学号和 C 语言课程期末总成绩),输出最高、最低成绩和分别对应的学号(可能有多个同学都是最高分,可能有多个同学都是最低分)。(12 分)【见2016年4.3】#
代码:
12345678910111213141516171819202122232425262728293031323334#include<stdio.h>
#include<stdlib.h>
struct
node
{
int
num;
int
cj;
};
int
main()
{
struct
node stu[100];
//结构数组
int
max=-1,min=200;
int
i;
//输入数据,求最大最小分数
for
(i=0; i<100; i++)
{
scanf
(
"%d %d"
,&stu[i].num,&stu[i].cj);
if
(stu[i].cj>max)
max=stu[i].cj;
if
(stu[i].cj<min)
min=stu[i].cj;
}
//输出分数最大以及学号
printf
(
"max=%d\n"
,max);
for
(i=0; i<100; i++)
if
(stu[i].cj==max)
printf
(
"%d\n"
,stu[i].num);
//输出分数最小以及学号
printf
(
"min=%d\n"
,min);
for
(i=0; i<100; i++)
if
(stu[i].cj==min)
printf
(
"%d\n"
,stu[i].num);
system
(
"pause"
);
return
0;
}
使用结构的指针
123456789101112131415161718192021222324252627282930313233343536373839404142434445#include<stdio.h>
typedef
struct
Student{
int
num;
int
score;
}Stu;
int
main()
{
/*选择排序:
假设排序表为L【1....n】,第一趟排序即从L【i...n】中选择关键字最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟排序就可以使得整个排序表有序
*/
Stu stu[200],temp,*p,*q,*k;
//stu为结构体数组,*p,*q,*k为结构体指针
int
i,j,max = 0;
//max记录分数最大值
p = stu;
//输出数据
for
(i = 0;i < 200;i ++,p ++)
scanf
(
"%d%d"
,&p->num,&p->score);
//选择排序,以成绩从低到高排序
p = stu;
for
(i = 0;i < 199;i ++,p ++)
//由于题目说明要用结构体指针,所以我这使用指针操作
{
k = p;
//记录最小元素位置
q = p + 1;
for
(j = i + 1;j < 200;j ++,q ++)
if
(k->score > q->score)
k = q;
//更新最小元素的位置
//与第i个位置交换
temp = *p;
*p = *k;
*k = temp;
}
//记录最高成绩
p = stu;
for
(i = 0;i < 200;i ++,p ++)
if
(p->score > max)
max = p->score;
//输出打印最高分数和对应的学号
p = stu;
for
(i = 0;i < 200;i ++,p ++)
if
(p->score == max)
printf
(
"学号:%5d分数:%5d\n"
,p->num,p->score);
return
0;
}
作者:Hang Shao
出处:https://www.cnblogs.com/pam-sh/p/12597736.html
版权:本作品采用「知识共享」许可协议进行许可。
声明:欢迎交流! 原文链接 ,如有问题,可邮件(mir_soh@163.com)咨询.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)