只要你愿意 开始总比放弃好。 Roman.
愿我们都有自己的目标并正在为其不懈努力。
-----------------------------------------------------------------------
三、 0217
1. 有如下代码,则下面的叙述不正确的是:( )
struct student
{
int num;
char name[32];
float score;
}stu;
A.struct 是结构体类型的关键字
B.struct student 是用户定义的结构体类型
C.num, score 都是结构体成员名
D.stu 是用户定义的结构体类型名
*结果:D
*分析:
A:正确,在C语言中需要自定义类型时,要用到struct关键字
B:正确:在C语言中,用struct定义的结构体,定义结构体类型变量时,需要用struct student
C:正确:结构体中的变量名称,称之为结构体的成员
D:错误:stu是定义的结构体类型变量,不是名称,如果想要让stu为结构体类型名称时,必须在结构体定义时添加 typedef关键字
2. 结构体访问成员的操作符不包含:( )
A.. 操作符
B.-> 操作符
C.* 解引用操作符
D.sizeof
*结果:D
*分析:
A:正确,结构体类型变量访问结构体中成员时,使用.操作符
B:正确,指向结构体类型变量的指针访问结构体中成员时,使用->操作符
C:正确,指向结构体类型变量的指针也可以通过.方式访问成员,只不过要先通过*对该指针解引用
D:错误,sizeof是求结构体类型大小的,是操作符
3. 关于VS调试快捷键说法错误的是:( )
(本题注意区分: F5 与 CTRL + F5 的区别)
A.F5-是开始执行,不调试
B.F10-是逐过程调试,遇到函数不进入函数
C.F11-是逐语句调试,可以观察调试的每个细节
D.F9是设置断点和取消断点
*结果:D
*分析:
A:错误,F5是开始调试,在遇到断点的位置可以停下来,Ctrl+F5是开始执行,不调试
B:正确,F10遇到函数时不会进入到函数体中,F11会
C:F11遇到函数时,会进入函数中
D:F9会在光标所在行下断点,如果有断点会取消断点 (F9一般与F5配合使用)
4. 下面程序要求输出结构体中成员a的数据,以下不能填入横线处的内容是( )
#include < stdio.h >
struct S
{
int a;
int b;
};
int main( )
{
struct S a, *p=&a;
a.a = 99;
printf( "%d\n", __________);
return 0;
}
A.a.a
B.*p.a
C.p->a
D.(*p).a
*结果:B
*分析:
结构体类型变量需要访问其成员时,用.运算符,如果是指向结构体变量的指针访问时,需要用->,或者先对指针解引用,取到指向的结构体类型的变量,再通过.访问,但是要注意优先级
注意: .优先级 > *优先级
5. 喝汽水问题:
喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。
1)方法一:考虑 钱、可以喝的瓶数、空瓶三者的关系
2)方法二:从等价交换的角度考虑(0.5r一瓶汽水)
(注意:考虑是否可以借一个瓶子换汽水再还回去瓶子)
*代码:
1) 方法一:
#include<stdio.h>
int main()
{
int money = 0;
printf("请输入您现有的钱:");
scanf("%d", &money);//20
int total = 0;
int empty = money;
if (money >= 0)
{
total = money;
}
else
{
total = 0;
}
//置换!!
while (empty>=2)
{
total += (empty / 2);
empty = empty / 2 + empty % 2;
}
printf("您一共可以喝:%d瓶汽水\n", total);
//printf("%d\n", total);
if (total > 0)
{
printf("如果您向其他人借一个空瓶再还回去,您可以喝:%d瓶汽水\n", (total + 1));
}
return 0;
}
2)方法二:等价:规律
#include<stdio.h>
int main()
{
int money = 0;
printf("请输入您现有的钱:");
scanf("%d", &money);//20
int total = 0;
if (money <= 0)
total = 0;
else
total = money * 2 - 1; //归纳了规律:瓶数=钱*2-1
printf("您一共可以喝:%d瓶汽水\n", total);
//printf("%d\n", total);
if (total > 0)
{
printf("如果您向其他人借一个空瓶再还回去,您可以喝:%d瓶汽水\n", (total + 1));
}
return 0;
}
*结果:
6. 调整数组使奇数全部都位于偶数前面。
输入一个整数数组,实现一个函数,
来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,
所有偶数位于数组的后半部分。
*分析及注意点:
- 从前往后找偶数,从后往前找奇数,找到则停下进行交换
- 一维数组传参,大小可以不指定
- 若数组是全奇数or全偶数,则在进行寻找过程中可能会出现访问越界,故需要进行条件限制
*代码:
#include<stdio.h>
int* move(int arr[], int sz)
{
int* ret = arr;
int left = 0;
int right = sz - 1;
while (left<right) //防止数组越界条件
{
//从前往后 --跳出循环条件:left==right or 偶数
while ((left<right) && (arr[left] % 2 == 1)) //进来以后的每一个循环也要进行限制!!
{
left++;
}
//从后往前 --跳出循环条件:left==right or 奇数 此处left是上一个循环的left
while ((left < right) && (arr[right] % 2 == 0))
{
right--;
}
//跳出循环后,判断是否需要进行交换:只有在未遍历完数组(left < right)时需要进行交换
if (left < right)
{
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
//交换完成后再次进入循环找下一次奇偶交换
}
return ret;
}
void print(int *ret, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(ret+i));
}
}
int main()
{
int arr[] = { 1,2,8,9,10,3,5,7};
int sz = sizeof(arr) / sizeof(arr[0]); //数组求元素个数
int* ret = move(arr, sz);
printf("奇偶排序后:\n");
print(ret, sz);
return 0;
}
*结果:
四、 0222
1. C程序常见的错误分类不包含:( )
A.编译错误
B.链接错误
C.栈溢出
D.运行时错误
*答案:C
*分析:
- C程序常见错误分类:编译 链接 运行
- 栈溢出是运行时错误的一种,因此C程序为将栈溢出单独列出,栈溢出包含在运行时错误中。
2. 以下关于指针的说法,正确的是( ) 【数组指针与指针数组】
A.int *const p与int const *p等价
B.const int *p与int *const p等价
C.const int *p与int const *p等价
D.int *p[10]与int (*p)[10]等价
*答案:C
*分析:
A:错误,int* const p中,const修饰指针变量p本身,表示p的指向不能改变,
int const *p中,const修饰【p指针解引用之后的结果】,表示p指向的内容不能改变
因此,不等价
B:错误,同上
C:正确,const都修饰p指针解引用之后的结果,表示p指向的内容不能改变
D:错误,int *p[10]定义了一个指针数组,数组中10个元素,每个元素都是int*类型的指针
int (*p)[10]定义了一个数组指针,该指针只能指向存储10个整形元素的数组
五、 0224
1. 程序的执行结果为( )
#include<stdio.h>
int main()
{
unsigned char a = 200;
unsigned char b = 100;
unsigned char c = 0;
c = a + b;
printf("%d %d", a + b, c);
return 0;
}
*结果:300 44
*分析:
计算时进行整型提升,根据原变量的类型进行提升,最后根据类型进行截断,根据输出再进行改变(变化的时候找补码:以补码形式进行存储)【整型提升操作符-整型提升】
说明:printf在传入参数的时候如果是整形会默认传入四字节,所以a+b的结果是用一个四字节的整数接收的,不会越界。而c已经在c = a + b这一步中丢弃了最高位的1,所以只能是300-256得到的44了。
实际分析:
#include<stdio.h> int main() { //以补码存储 unsigned char a = 200; //a原反补码:1100 1000 unsigned char b = 100; //b原反补码::0110 0100 unsigned char c = 0; c = a + b; //整型提升:a b 无符号:无原反补码概念,高位补0 //a原反补码:0000 0000 0000 0000 0000 0000 1100 1000 //b原反补码:0000 0000 0000 0000 0000 0000 0110 0100 //相加 补码:0000 0000 0000 0000 0000 0001 0010 1100 printf("%d %d", a + b, c); // 打印原码:补码-1 -> 除符号位 按位取反 --易错 //a+b:0000 0000 0000 0000 0000 0001 0010 1100 (打印的是%d形式,所以默认此时是%d形式,有符号) //直接打印出来 --300 //c无符号:无原反补码概念:高位补0 //补码:0000 0000 0000 0000 0000 0001 0010 1100 //c = a + b; c是unsigned char,故截断:0010 1100 //打印时进行整型提升:0000 0000 0000 0000 0000 0000 0010 1100 --44 return 0; }
※由于printf是可变参数的函数,所以后面参数的类型是未知的,所以甭管你传入的是什么类型,printf只会根据类型的不同将用两种不同的长度存储。其中8字节的只有long long、float和double(注意float会处理成double再传入),其他类型都是4字节。所以虽然a + b的类型是char,实际接收时还是用一个四字节整数接收的。另外,读取时,%lld、%llx等整型方式和%f、%lf等浮点型方式读8字节,其他读4字节。
*注意关键点:
运算时进行整型提升,计算完成后在根据被赋值类型进行截断等操作,打印时再进行算术转换以及整型提升等,之后即以打印类型直接打印出来
2. 在32位大端模式处理器上变量b等于( )
unsigned int a= 0x1234;
unsigned char b=*(unsigned char *)&a;
*结果:0x00
*分析:
大端序中,低地址到高地址的四字节十六进制排列分别为00 00 12 34,其中第一个字节的内容为00
注意:进制表示时,位数不够,往高位添0即可
3. 在屏幕上打印杨辉三角。
1
1 1
1 2 1
1 3 3 1
……
*代码:
//1 // 1: i==j or j==0
//1 1 // 上面两个数之和:中间数的结果
//1 2 1
//1 3 3 1
//……
#include<stdio.h>
#define max 100
int main()
{
int n = 0;
int Yanghui[max][max] = { 0 };
printf("请输入您想要的杨辉三角行数:\n");
scanf("%d", &n);
int i = 0;
int j = 0;
printf("杨辉三角如下:\n");
for (i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
{
if ((i == j) || (0 == j))
{
Yanghui[i][j] = 1;
}
else if ((i > 1) && (j >= 1))
{
Yanghui[i][j] = Yanghui[i - 1][j - 1] + Yanghui[i - 1][j];
}
printf("%d ", Yanghui[i][j]);
}
printf("\n");
}
return 0;
}
*结果:
4. 猜凶手
日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。
以下为4个嫌疑犯的供词:
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。
*代码:
//先假设凶手-四个人均假设一次
//再对所说的话判断真假,三个真则booean型--四个相加和为1
// char的本质也是整形
#include<stdio.h>
int main()
{
int killer = 0;
//循环假设凶手
for (killer = 'A'; killer <= 'D'; killer++)
{
//对话语进行真假判断
if (3 == (killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D'))
{
printf("Killer is %c\n", killer);
break;
}
}
return 0;
}
*结果:
5. 猜名词
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次
*代码:
//注意每位选手说对了一半!!! --那就把每位选手的两句话分别分开进行整个选手的加和,每位选手加和boolean结果为1
//进行循环试名次,最终确定符合名次的结果
#include<stdio.h>
int main()
{
int A = 0;
int B = 0;
int C = 0;
int D = 0;
int E = 0;
for (A = 1; A <= 5; A++)
{
for (B = 1; B <= 5; B++)
{
for (C = 1; C <= 5; C++)
{
for (D = 1; D <= 5; D++)
{
for (E = 1; E <= 5; E++)
{
if ((1 == (2 == B) + (3 == A)) && (1 == (2 == B) + (4 == E)) &&
(1 == (1 == C) + (2 == D)) &&
(1 == (5 == C) + (3 == D)) && (1 == (4 == E) + (1 == A)))
{
//不能重复:相乘结果为120 (不要相加,重复可能性更大)
if (120 == (A * B * C * D * E))
{
printf("A:%d B:%d C:%d D:%d E:%d\n", A, B, C, D, E);
break;
}
}
}
}
}
}
}
return 0;
}
*结果:
------------------------一个人所有的愤怒都来源于对自己无能的痛苦。------------------------