2024年C语言习题积累(正在更新)_语言积累 小练习(1),全网首发

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

将一个十进制数转换成二进制并打印二进制序列的每一位。

答案
void Bin(n)
{
	if (n / 2 != 0)
	{
		Bin(n / 2);
	}
	printf("%d", n % 2);
}

解析

10进制数转换成二进制数,这是一个连续除2的过程:

  1. 把要转换的数,除以2,得到商和余数,
  2. 将商继续除以2,直到商为0。

最后将所有余数倒序排列,得到数就是转换结果。

7冒泡排序
题目

有一个无序的整型数组,使用冒泡排序的方法使其按升序或降序的方式排序。

答案
int BubbleSort() {
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < sz - 1; i--) {
        for (int j = 0; j < sz - 1 - i; j++) {
            if (arr[j] < arr[j + 1]) {
               int tmp  = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

解析

冒泡排序的核心思想是相邻两数相比,可以抽象为一个比较函数。

基本思路是比较

n

1

n-1

n−1 趟,每趟比较

n

1

i

n-1-i

n−1−i 次。

因为外循环结束一次排序完一个数,使其来到其最终位置上,内循环一次使其与未经和其比较的数进行比较,并在满足条件的情况下进行交换,所以每次减i

8数组操作
题目

实现reverse()函数完成数组元素的逆置。

答案
void reverse(int arr[], int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left < right)
	{
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}

解析

通过下标访问数组元素从左向右依次进行交换。这种逆序整型数组也可以逆序字符串。都是一样的字符串也可以通过下标访问。

9打印二进制奇数偶数位
题目

输入一个整数,分别打印其二进制序列的奇数位和偶数位。

答案
int main() {
	int n = 0;
    int i = 0;
	scanf("%d", &n);
	printf("奇数位:");
	for (i = 30; i >= 0; i -= 2) {
		printf("%d ", (n >> i) & 1);
	}
	printf("\n偶数位:");
	for (i = 31; i >= 1; i -= 2) {
		printf("%d ", (n >> i) & 1);
	}
	return 0;
}

解析

循环遍历二进制序列中的每一位,让每一位右移上i位都有机会来到最后一位和整数1按位与,这样得到的数也只能10,这样就相当于变相得到二进制序列的每一位。由于要区分奇数位和偶数位且按照顺序打印,故要从后往前遍历。

10交换两个变量
题目

不创建临时变量的条件下,交换两个整型变量。

答案
int main()
{
	int a = 10;
	int b = 20;
	printf("a=%d,b=%d\n", a, b);
	//1.
	a = a + b;
	b = a - b;
	a = a - b;

	//2.
    //(a^b)^a=b (a^b)^b=a
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;

	printf("a=%d,b=%d\n", a, b);
	return 0;
}

解析

不创建临时变量来交换两个整数数据。

  • 通过赋值的方法,把a+b赋值给a,此时a已经等于a+b,再将a-b赋值给b,这样b就等于原来的a,再用a-b,这样就得到了b再赋值给a。这样a,b就完成了交换。
  • 通过按位异或的方法,按位异或的特点是,相同为0,相异为1。这样就会导致一个结果(a^b)^a=b(a^b)^b=a。这样的话把a^b的结果再与b异或然后赋值给b,再将a^b,也就是(a^b)^a=b赋值给a

但二者都有局限,前者的大小受限,a+b加起来不可以大于一个整型不然就会溢出。后者因按位操作符仅是由于整型,故后者也受限于变量类型为整型。

11统计二进制中1的个数
题目

输入一个整数,统计其二进制序列中1的个数。

答案
  1. 方法1
int Return\_Number\_1(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1) == 1)
		{
			count++;
		}
	}
	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	printf("%d\n", Return\_Number\_1(n));

	return 0;
}

  1. 方法2
int main()
{
	int n = 0;
	int count = 0;
	scanf("%d", &n);
	while (n) {
		n = n & (n - 1);
		count++;
	}
	printf("%d\n", count);

	return 0;
}

解析

如图所示我们用n&(n-1)作为计数器的条件,可以发现n&(n-1)的结果比n的二进制序列少一个1,再将结果赋值给n,就可以依靠循环来实现计数器。

12计算求和
题目

S

n

=

a

a

a

a

a

a

a

a

a

a

a

a

a

a

a

Sn = a + aa + aaa + aaaa + aaaaa

Sn=a+aa+aaa+aaaa+aaaaa 的前5项之和,其中

a

a

a 是一个数字,例如:

2

22

222

2222

22222

2 + 22 + 222 + 2222 + 22222

2+22+222+2222+22222。

答案

第一种思路:

2 = 2\*10^0
22 = 2\*10^1 + 2
222 = 2\*10^2 + 22
2222 = 2\*10^3 + 222 
22222 = 2\*10^4 + 2222
22222 = 2\*10^4 + 2222

第二种思路:

2 = 2 + 0
22 = 2 \* 10 + 2
222 = 22 \* 10 + 2
2222 = 222 \* 10 + 2
22222 = 2222 \* 10 + 2

#include <math.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	int sum = 0;
	int ret = 0;
	for (int i = 0; i < 5; i++) {
		//1.
        ret += a \* (int)pow(10, i);
		//2.
        ret = ret \* 10 + a;
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

第三种方法:

#include <math.h>
int main()
{
	int a = 0;
	int n = 0;
	int sum = 0;
	scanf("%d %d", &a, &n);
	while (n) {
		int i = n;
		int ite = 0;
		while (i) {
			ite += a \* pow(10, i - 1);
			i--;
		}
		sum += ite;
		n--;
	}
	printf("%d\n", sum);
	return 0;
}

解析
  • 第一种是把

a

a

a 看作

a

×

1

0

0

a×10^0

a×100,

a

a

aa

aa 看成

a

×

1

0

1

a

×

1

0

0

a×101+a×100

a×101+a×100 ……

  • 第二种每次在前一次运算的结果上乘10并加上2。
  • 第三种是可以规定位数。

13自幂数
题目

求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:

153

=

1

3

5

3

3

3

153=13+53+3^3

153=13+53+33 。
则153是一个“水仙花数”。

答案
#include<math.h>
int main() {
	for (int i = 0; i < 10000; i++) {
		//1. 求位数
		int n = 1;
		int num = i;
		while (num /= 10) {
			n++;
		}
		//2. 求每项和
		int sum = 0;
		num = i;
		while (num) {
			sum += (int)pow((num % 10), n);
			num /= 10;
		}
		//3. 判断
		if (sum == i) {
			printf("%d\n", i);
		}
	}
	return 0;
}

解析

求自幂数需要三步,1求出该数的位数2求每项和3.判断是否相等。每次做出改变i动作时,要把i赋值给临时变量以免在循环内改变临时变量。

14字符串逆序
题目

现有一字符串i am a student,将其全部逆序得tneduts a ma i

进阶版:将其单词外逆序,单词内顺序不变,得:student a am i

答案
#include <string.h>
char\* reverse(char\* arr) {
	int len = strlen(arr);
	char\* left = arr;
	char\* right = arr + len - 1;
	while (left < right) {
		char tmp = \*left;
		\*left = \*right;
		\*right = tmp;
		left++;
		right--;
	}
	return arr;
}
int main()
{
	char arr[] = "i am a student";
	reverse(arr);
	printf("%s\n", arr);
	return 0;
}

进阶版:

char\* reverse(char\* left, char\* right) {
	while (left < right) {
		char tmp = \*left;
		\*left = \*right;
		\*right = tmp;
		left++;
		right--;
	}
	return left;
}
char\* move(char\* arr) {
	int len = strlen(arr);
	reverse(arr, arr + len - 1);
	reverse(arr, arr + 6);
	reverse(arr + 8, arr + 8);
	reverse(arr + 10, arr + 11);
	reverse(arr + 13, arr + 13);
	return arr;

}
//tneduts a ma i
//01234567890123
int main()
{
	char arr[] = "i am a student";
	move(arr);
	printf("%s\n", arr);
	return 0;
}

解析

把所有单词都可视为字符,故逆序字符串即可。进阶版只需要将全部逆序后的结果数清每个字符的下标位置,并单独在逆序就可以了。

15喝汽水问题
题目

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水。

答案
//喝汽水
int main()
{
	int money = 20;
	//买的
	int total = money;
	int empty = money;
	//换的
	while (empty > 1) {
		total += empty / 2;
		empty = empty / 2 + empty % 2;
	}
	printf("%d\n", total);


	return 0;
}

解析

喝到的汽水可以分为两种,一种是买来的一种是换来的。首先花已有的钱买来的一元一瓶故先total等于money。

然后计算换来的,定义空瓶数,两个空瓶换一瓶,故total等于empty/2,empty执行整数除法,故empty等于不仅要/2还要%2,奇数瓶还会剩下奇数瓶。

16程序解释
题目

请解释下列代码的运行结果和问题原因。

#include <stdio.h>
int main()
{
	int i = 0;
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("hello bit\n");
	}
	return 0;
}

答案

解析

数组其后第三块空间正好被编译器用来放置存储下标的变量,故每次到这里都会清零,就重新开始了。每个编译器的位置不一样,这个属于编译器的自我优化,不是我们可以改变的。且在release版本会优化掉这个问题。

17调整奇偶顺序
题目

调整数组使奇数全部都位于偶数前面。
输入一个整数数组,调整该数组中数字的顺序,使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。

答案
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int\* pl = arr;
	int\* pr = &arr[sz - 1];
	while (pl < pr) {
		while (\*pl % 2 == 1) {
			pl++;
		}
		while (\*pr % 2 == 0) {
			pr--;
		}
		if (pl < pr) {
			int tmp = \*pl;
			\*pl = \*pr;
			\*pr = tmp;
		}
	}
	for (int i = 0; i < sz; i++) {
		printf("%d ", arr[i]);
	}
	return 0;
}

解析

plpr不可以同时加减。在前面用pl寻找奇数,后面用pr寻找偶数。找到之后再两者交换。

18杨辉三角
题目

打印如图所示的数据三角形。

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

打印杨辉三角菱形形式。

    1
   1 1
  1 2 1
 1 3 3 1
1 4 6 4 1

答案
int main()
{
	int n = 0;
	scanf("%d", &n);
	int arr[20][20] = { 0 };
	arr[1][1] = 1;
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j <= i; j++) {
			arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];//规律
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= i; j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

进阶版:

int main()
{
	int arr[10][10] = { 0 };
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j <= i; j++) {
			//初始化
			arr[i][0] = arr[i][i] = 1;
			//计算
			if (i >= 2 && j >= 1) {
				arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
			}
			//打印
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (j < 9 - i) {
				printf(" ");
			}
			else {
				printf("%d ", arr[i][j - 9 + i]);
			}
		}
		printf("\n");
	}
	return 0;
}

解析

首先杨辉三角的规律为

a

r

r

[

i

]

[

j

]

=

a

r

r

[

i

1

]

[

j

1

]

a

r

r

[

i

1

]

[

j

]

arr[i][j] = arr[i-1][j-1]+arr[i-1][j]

arr[i][j]=arr[i−1][j−1]+arr[i−1][j] 。

  • 第一种初始化时是从第2行第2列初始化,将arr[1][1]置为1。
  • 第二种是将第1列和对角线初始化为1,然后从第3行第2列开始初始化。

19猜凶手
题目

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词:
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。

答案
int main()
{
	int kill = 0;
	//枚举法,一一列举
	for (kill = 'A'; kill <= 'D'; kill++) {
		//利用表达式返回值特点,直观
		if ((kill != 'A') +
			(kill == 'C') + 
			(kill == 'D') + 
			(kill != 'D') == 3) {
			printf("%c\n", kill);
			break;
		}
	}
	return 0;
}

解析

定义killer变量,将是与不是转化为关于killer变量的关系运算。因为只有ABCD每人一个条件故只要一个循环即可。三人真话,一人假话,故所有条件表达式相加的结果应为3,在killer假设条件正确时。

20程序解释
题目

求代码中strlen(a)的结果,并解释清楚原因。

int main()
{
	char a[1000] = { 0 };
	int i = 0;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

答案

255

解析

strlen(a)的值,也就是求a[i]=0的时候,i为多少,准确的来说应该是-1-i等于多少。因为数组a为字符元素数组,故当-1-i的尾七位二进制补码为全1的时候,由于存入数组时发生截断故存入的是0。

21猜名次
题目

5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

答案
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++) {
						//循环5^5次
						//判断条件1.
						//if ((b == 2) + (a == 3) +
						// (b == 2) + (e == 4) +
						// (c == 1) + (d == 2) +
						// (c == 5) + (d == 3) +
						// (e == 4) + (a == 1) == 5) {
						//判断条件2.
						if (((b == 2) + (a == 3) == 1) &&
							((b == 2) + (e == 4) == 1) &&
							((c == 1) + (d == 2) == 1) &&
							((c == 5) + (d == 3) == 1) &&
							((e == 4) + (a == 1) == 1)) {
							if (a \* b \* c \* d \* e == 120) {//1\*2\*3\*4\*5=120
								printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
								goto again;
								return 0;
							}
						}
					}
				}
			}
		}
	}
again:
}

解析

找凶手的题目凶手只有一个,猜名次必须要排序,所以要有5个循环,每个循环判断一个选手的名次。同样是把所有人的话作为一个条件,限制条件是每个人只有半句是对的,所以是两个条件加起来是1。最后要取出排名重复的情况。

22杨氏矩阵
题目

有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,
请编写程序在这样的矩阵中查找某个数字是否存在。
要求:时间复杂度小于O(N);

答案
void find\_key(int(\*pa)[3], int\* px, int\* py, int k) {
	int x = \*px;
	int y = \*py;
	while (x < 3 && y >= 0) {
		if (pa[x][y] > k) {
			y--;
		}
		else if (pa[x][y] < k) {
			x++;
		}
		else {
			printf("(%d,%d)\n", x, y);
			return;
		}
	}
	printf("NO\n");

}

int main() {
	int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	int key = 7;
	int x = 0;
	int y = 2;
	find\_key(arr, &x, &y, key);



![img](https://img-blog.csdnimg.cn/img_convert/585467ce564c71177d7a763d07f7dd79.png)
![img](https://img-blog.csdnimg.cn/img_convert/364a26d8d2aaf07bede1cd013dabdc16.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

	//判断条件2.
						if (((b == 2) + (a == 3) == 1) &&
							((b == 2) + (e == 4) == 1) &&
							((c == 1) + (d == 2) == 1) &&
							((c == 5) + (d == 3) == 1) &&
							((e == 4) + (a == 1) == 1)) {
							if (a \* b \* c \* d \* e == 120) {//1\*2\*3\*4\*5=120
								printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
								goto again;
								return 0;
							}
						}
					}
				}
			}
		}
	}
again:
}

解析

找凶手的题目凶手只有一个,猜名次必须要排序,所以要有5个循环,每个循环判断一个选手的名次。同样是把所有人的话作为一个条件,限制条件是每个人只有半句是对的,所以是两个条件加起来是1。最后要取出排名重复的情况。

22杨氏矩阵
题目

有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,
请编写程序在这样的矩阵中查找某个数字是否存在。
要求:时间复杂度小于O(N);

答案
void find\_key(int(\*pa)[3], int\* px, int\* py, int k) {
	int x = \*px;
	int y = \*py;
	while (x < 3 && y >= 0) {
		if (pa[x][y] > k) {
			y--;
		}
		else if (pa[x][y] < k) {
			x++;
		}
		else {
			printf("(%d,%d)\n", x, y);
			return;
		}
	}
	printf("NO\n");

}

int main() {
	int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
	int key = 7;
	int x = 0;
	int y = 2;
	find\_key(arr, &x, &y, key);



[外链图片转存中...(img-LMvvqUkI-1715570664024)]
[外链图片转存中...(img-qanY7xcT-1715570664026)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值