- 选择出正确的宏定义()。C
A. #define RECT_AREA (a, b) (a * b)
B. #define RECT_AREA (a, b) (a) + (b)
C. #define RECT_AREA (a, b) ((a) * (b))
D. #define RECT_AREA (a, b) a * b
- 下列关于头文件或宏的描述错误的是()。C
A. 每一个.c文件应有一个同名.h文件,用于声明需要对外公开的接口,同时.c/.h文件禁止包含用不到的头文件;
B. 禁止在头文件中定义变量;
C. 应尽可能使用函数代替宏,建议使用宏代替 const 定义常量;
D. 使用宏时不允许参数发生变化。
- 如果a.c包含了头文件a.h,a.h包含了头文件b.h,b.c也包含了b.h,那么当b.h发生改变时,哪些文件将会被重新编译()。D
A. b.c
B. a.h
C. a.c和a.h
D. a.c和b.c
- 以下哪种措施不可以避免内存操作越界()。D
A. 数组的大小要考虑最大情况,避免数组分配空间不够;
B. 字符串要考虑最后的’\0’,确保所有字符串是以’\0’结束;
C. 指针加减操作时,考虑指针类型长度;
D. 通过手工计算结构/字符串长度。
- 对于字符串"abcdefghi0"使用多大字符数组进行存储最未合适()。B
A. 10.0
B. 11.0
C. 12.0
D. 20.0
- 针对函数的设计的说法,下面哪个是正确的()。B
A. 应尽量设计多用途面面俱到的函数,函数的参数可以超过 5个 ;
B. 在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加 static 关键字;
C. 设计高扇入,合理扇出(小于 7)的函数,新增函数的代码块嵌套不超过 5 层;
D. 函数中的冗余代码只要不影响函数的效率,不需要删除。
- 如果a.c只对外提供一个void bar()函数作为接口,而bar函数的实现部分需要使用b.c中的void foo()函数,以下做法中错误的是()。A
A. 在b.c中声明 extern void foo(),在a.c中声明 extern void foo();
B. 在b.h中声明 extern void foo(),在a.c中声明 extern void foo();
C. 在b.h中声明extern void foo(),在a.c中 #include b.h;
D. 在b.h中声明extern void foo(),在a,h中 #include b.h。
- 如果不使用常量,直接在程序中填写数字或字符串,不会有哪些麻烦()。D
A. 程序的可读性(可理解性)变差。程序员自己会忘记哪些数字或字符串是什么意思,维护人员则更加不知道它们从何处来、表示什么;
B. 如果要修改数字或者字符串,则会在很多地方改动,既麻烦又容易出错;
C. 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误;
D. 程序无法编译。
- 对于整数溢出问题,下列说法错误的是()。D
A. 无符号整数运算时要保证结果不能出现反转;
B. 有符号整数运算时要保证结果不能出现溢出;
C. 整型转换时要避免出现截断危险;
D. 整数溢出一般只会导致逻辑错误,不会产生安全问题。
- 关于变量,错误的说法是()。D
A. 若全局变量只在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
B. 若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
C. 设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;
D. 函数内部定义的自动变量过大,可能会导致堆栈溢出。
- 租船问题。
写程序计算游客需要付的租船的费用。
租船每小时30元。
游客输入租船时间,计算出租船费用。
租船费用 = 时间 * 每小时钱数 + 押金。
要求押金与每小时钱数使用宏定义。
// 押金
#define CASH_PLEDGE
// 每小时钱数
#define MONEY_PER_HOUR
void CharteringCharges(int hour)
{
return hour * MONEY_PER_HOUR + CASH_PLEDGE;
}
- 嵌入式系统总是要用客户对变量或寄存器进行位操作。
给定一个整形变量a,写两段代码,第一个设置a的bit3,第二个清除a 的bit 3。
在以上两个操作中,要保持其它位不变。
#define BIT3 (0x1 << 3)
static int a;
// 设置 a 的 bit3
void set_bit3(void)
{
a |= BIT3;
}
// 清除 a 的 bit3
void clear_bit3(void)
{
a &= ~BIT3;
}
- 约瑟夫环问题。
约瑟夫入狱,监狱内共有33个犯人。某日33名犯人围成一圈,从第一个犯人开始报数,报到数字7的犯人出列,被枪毙,下一名犯人重新开始从1开始报数。依次类推,直至剩下最后一名犯人可被赦免。聪明的约瑟夫在心里稍加计算,算出了最后枪毙的位置,他站在这个位置,最终避免了自己被枪毙,逃出生天。
递推关系式:
f(N, M) = (f(N - 1, M) + M) % N
递归出口:f(1, M) = 0
本题即求:f(33, 7) = 12
代码(链表实现)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 头结点
typedef struct header
{
int length; // 链表总长度
struct node* next; // 指向下一个结点
}head;
// 数据结点
typedef struct node
{
int val; // 数据结点的值
struct node* next; // 指向下一个结点
}node;
// 循环链表的创建
head* listcreat()
{
head* p;
p = (head*)malloc(sizeof(head));
p->next = NULL;
p->length = 0;
return p;
}
// 循环链表数据结点的插入
void listinsert(head* p,int pos,int x)
{
if(p == NULL || pos < 0 || pos > p->length)
{
printf("listinsert():error\n");
return;
}
node* temp = (node*)malloc(sizeof(node));
temp->val = x;
node* pcur = p->next; // 指向第一个数据节点
node* plast = p->next; // 指向最后一个数据节点
while(pcur != NULL&&plast->next != pcur) // 使plast指向最后一个节点
{
plast = plast->next;
}
if(p->length == 0) // 判断循环链表为空的情况
{
p->next = temp;
temp->next = temp;
}
else if(pos == 0) // 头插
{
plast->next = temp;
temp->next = pcur;
p->next = temp;
}
else if(pos == p->length) // 尾插
{
plast->next = temp;
temp->next = pcur;
}
else
{
node* pval = p->next; // pval用来指向要插入位置的数据节点
for(int i = 1; i < pos; i++)
{
pval = pval->next;
}
temp->next = pval->next;
pval->next = temp;
}
p->length++;
return;
}
// 循环链表数据结点的删除
void listdelete(head* p,int x)
{
node* temp; // temp指向要删除的节点
temp = p->next;
for(int i = 0; i < p->length; i++)
{
if(temp->val == x)
{
break;
}
temp = temp->next;
}
node* pcur = p->next; // pcur指向第一个节点
node* plast = p->next; // plast用来指向最后一个节点
while(plast->next != pcur)
{
plast = plast->next;
}
if(temp->val != x)
{
printf("listprintf():error\n");
return;
}
if(p->length == 1) // 只有一个元素时
{
p->next = NULL;
}
else if(temp == pcur) // 删除的是第一个节点
{
p->next = pcur->next;
plast->next = pcur->next;
}
else if(temp == plast) // 删除的是最后一个节点
{
node* pre = p->next; // 指向倒数第二个节点
while(pre->next != plast)
{
pre = pre->next;
}
pre->next = pcur;
}
else
{
node* pre = p->next;
while(pre->next != temp) // 使pre指向temp的前一个元素
{
pre = pre->next;
}
pre->next = temp->next;
}
p->length--;
}
// 循环链表的遍历打印(输出)
void listprint(head* p)
{
if(p == NULL || p->length == 0)
{
printf("listprint():error");
return;
}
node* temp = p->next;
for(int i = 0; i < p->length; i++)
{
printf("%d ", temp->val);
temp = temp->next;
}
printf("\n");
return;
}
int main()
{
head* p;
p = listcreat();
printf("题意:m个人围成一圈,报到n的人退出,直到只留下一个\n\n");
printf("请输入约瑟夫环的总人数m:");
int m, n;
scanf("%d", &m);
printf("\n");
printf("请输入被踢出的报数n:");
scanf("%d", &n);
printf("\n");
for(int i = m; i > 0; i--)
{
listinsert(p, 0, i);
}
printf("输出初始循环链表:");
listprint(p);
node* temp = p->next;
int count = 1;
printf("\n被踢顺序:");
while(temp->next != temp) // 剩下一个数时结束循环
{
if(count == n)
{
node* pre = p->next;
while(pre->next != temp) // 指向temp的前一个节点
{
pre = pre->next;
}
printf("%d ", temp->val);
listdelete(p, temp->val);
temp = pre;
count = 0;
continue;
}
count++;
temp = temp->next;
}
printf("\n");
printf("\n链表中最后被剩下的是:");
listprint(p);
}