【C语言】练习题

发布于:2022-12-16 ⋅ 阅读:(266) ⋅ 点赞:(0)

目录

1. 计算n!

2. 计算1!+2!+...+n!

3. 输出100~200之间的素数并计数

4. 最多只能输入三次密码

5. 演示多个字符从两端移动,向中间汇聚

6. 喝汽水问题

7. 猜名次问题

8. 猜凶手问题

9. 调整数组使奇数全部都位于偶数前面

10. 杨辉三角

11. 杨氏矩阵

12. 字符串左旋


1. 计算n!

直接法:

#include <stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = 1;	
	int i = 1;
	for (i = 1; i <= n; i++)
	{
		ret *= i;
	}
	printf("%d\n", ret);
	return 0;
}

递归:

#include <stdio.h>
 
int fac(int n)
{
	if (n <= 1)
		return 1;
	else
		return n * fac(n - 1);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fac(n);
	printf("%d\n", ret);
	return 0;
}

迭代:

#include <stdio.h>

int fac(int n)
{
	int i = 0;
	int ret = 1;
	for (i = 1; i <= n; i++)
	{
		ret *= i;
	}
	return ret;
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fac(n);
	printf("%d\n", ret);
	return 0;
}

2. 计算1!+2!+...+n!

#include <stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = 1;
	int sum = 0;
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		ret *= i;
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

3. 输出100~200之间的素数并计数

素数质数(prime number)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

判断素数的一种方法是用m除以2~m-1之间的数,如果m能被其中的一个数整除,则不为素数。如,7不能被2~6之间的数整除,为素数;15能被3整除,不为素数。

上述方法可以进一步优化。如果m不为素数,m=a×b,a和b中一定有一个在2~√m之间,另一个≥√m。所以只需要用m除以2~√m之间的数即可。

除2以外的偶数一定不是素数,所以输出100~200之间的素数,只需从101开始判断,每次调整+2,跳过偶数。

#include <stdio.h>
#include <math.h>

int main()
{
	int count = 0;//计数
	int i = 0;
	for (i = 101; i < 200; i+=2)
	{
		int flag = 1;//默认是素数,flag为1
		//判断素数
		int j = 0;
		for (j = 2; j <= sqrt(i); j++)
		{
			if (i % j == 0)
			{
				flag = 0;//不是素数,flag赋值为0
				break;
			}
		}
		//输出素数并计数
		if (flag)
		{
			printf("%d ", i);
			count++;//计数
		}
	}
	printf("\ncount = %d\n", count);//输出数量
	return 0;
}

函数形式:

#include <stdio.h>
#include <math.h>

int is_prime(int n)
{
	int j = 0;
	for (j = 2; j <= sqrt(n); j++)
	{
		if (n % j == 0)
		{
			return 0;//不是素数返回0
		}
	}
	return 1;//是素数返回1
}
//或者使用布尔类型
//#include <stdbool.h>//该头文件定义了布尔类型
//bool is_prime(int n)
//{
//	int j = 0;
//	for (j = 2; j <= sqrt(n); j++)
//	{
//		if (n % j == 0)
//		{
//			return false;//不是素数返回false
//		}
//	}
//	return true;//是素数返回true
//}

int main()
{
	int count = 0;//计数
	int i = 0;
	for (i = 101; i < 200; i+=2)
	{
		if (is_prime(i))
		{
			printf("%d ", i);//输出素数
			count++;//计数
		}
	}
	printf("\ncount = %d\n", count);//输出数量
	return 0;
}

运行结果:

101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

count = 21

4. 最多只能输入三次密码

最多只能输入三次密码,密码正确则提示登录成功,三次均输入错误,则退出程序。
假设密码是字符串:abcdef。

#include <stdio.h>
#include <string.h>
 
int main()
{
	int i = 0;
	char password[20] = { 0 };
 
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);
 
		//比较两个字符串不能使用==,应该使用一个库函数strcmp(),头文件是string.h
		if (strcmp(password, "abcdef") == 0)//如果返回值是0,那么两个字符串相等
		{
			printf("登陆成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (3 == i)
	{
		printf("三次密码均输入错误,退出程序\n");
	}
 
	return 0;
}

5. 演示多个字符从两端移动,向中间汇聚

#include <stdio.h>
#include <windows.h>//windows头文件
#include <stdlib.h>//standard library 标准库头文件
 
int main()
{
	char arr1[] = "Welcome to JLU!!!!";
	char arr2[] = "##################";
	int left = 0;
	//int right = sizeof(arr1)/sizeof(arr1[0])-2;sizeof算\0
	int right = strlen(arr1) - 1;//strlen不算\0
 
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
 
		printf("%s\n", arr2);
 
		//程序休眠1000ms
		Sleep(1000);//Sleep()是一个库函数,头文件是window.h
 
		//清空屏幕(clear screen)
		system("cls");//system()是一个库函数,执行系统命令,头文件是stdlib.h
 
		left++;
		right--;
	}
 
	printf("%s\n", arr2);
 
	return 0;
}

运行结果:

W################!

↓(时间间隔1000ms)

We##############!!

↓(时间间隔1000ms)

Wel############!!!

↓(时间间隔1000ms)

Welc##########!!!!

↓(时间间隔1000ms)

Welco########U!!!!

↓(时间间隔1000ms)

Welcom######LU!!!!

↓(时间间隔1000ms)

Welcome####JLU!!!!

↓(时间间隔1000ms)

Welcome ## JLU!!!!

↓(时间间隔1000ms)

Welcome to JLU!!!!

↓(时间间隔1000ms)

Welcome to JLU!!!!

6. 喝汽水问题

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

#include <stdio.h>
 
int main()
{
	int money = 0;
	scanf("%d", &money);
	int drink = money / 1;
	int empty = drink;
	while (empty > 1)//只要空瓶有两个或以上就能继续换来喝
	{
		drink += empty / 2;
		empty = empty / 2 + empty % 2;
	}
	printf("%d\n", drink);
	return 0;
}
//输入:20,输出:39

7. 猜名次问题

5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:

A选手说:B第二,我第三;

B选手说:我第二,E第四;

C选手说:我第一,D第二;

D选手说:C最后,我第三;

E选手说:我第四,A第一;

比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

可以根据表达式为真,值为1,表达式为假,值为0来解题。每位选手都说对了一半,说明每位选手的2个判断表达式的和为1。为防止名次重复,设置判断条件:(a * b * c * d * e == 120) && (a + b + c + d + e == 15)。

#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 (((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) && (a + b + c + d + e == 15))
								printf("a=%d b=%d c=%d d=%d e=%d\n", a, b, c, d, e);
						}
					}
				}
			}
		}
	}
	return 0;
}
//a=3 b=1 c=5 d=2 e=4

8. 猜凶手问题

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。

以下为4个嫌疑犯的供词:

A说:不是我。

B说:是C。

C说:是D。

D说:C在胡说

已知3个人说了真话,1个人说的是假话。

现在请根据这些信息,写一个程序来确定到底谁是凶手。

因为3个人说了真话,1个人说的是假话,所以4个判断表达式的和为3。

#include <stdio.h>
 
int main()
{
	char killer = 0;
	for (killer = 'A'; killer <= 'D'; killer++)
	{
		if ((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D') == 3)
		{
			printf("%c\n", killer);//C
		}
	}
	return 0;
}

9. 调整数组使奇数全部都位于偶数前面

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

#include <stdio.h>
 
void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
 
void move_even_odd(int arr[], int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left<right)
	{
		//从前往后找一个偶数停下来
		while ((left < right) && (arr[left] % 2 == 1))
		{
			left++;
		}
		//从后往前找一个奇数停下来
		while ((left < right) && (arr[right] % 2 == 0))
		{
			right--;
		}
		if (left < right)
		{
			int tmp = arr[left];
			arr[left] = arr[right];
			arr[right] = tmp;
			left++;
			right--;
		}
	}
}
 
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9};
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(arr, sz);
	move_even_odd(arr, sz);
	print(arr, sz);
	return 0;
}

10. 杨辉三角

杨辉三角的两条斜边上都是数字1,而其余的数都等于它肩上的两个数字相加。

将杨辉三角压缩成下三角:

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

1 5 10 10 5 1

1 6 15 20 15 6 1

可以看出第一列和对角线的数字都是1,其他坐标的数字都可以计算得出。

输出10行的杨辉三角:

#include <stdio.h>

int main()
{
	int arr[10][10] = { 0 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 10; i++)
	{
		for (j = 0; j <= i; j++)
		{
			if (j == 0 || i == j)
				arr[i][j] = 1;
			else
				arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

11. 杨氏矩阵

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

显然,矩阵右上角的数字既是该行中最大的,又是该列中最小的。将右上角的数字a与要查找的数字k进行比较,如果a<k,则去掉该行(该行所有元素都不用与k进行比较);如果a>k,则去掉该列(该列所有元素都不用与k进行比较),直到a=k。

假设查找数字4:

第一步:3<4,去掉第一行。

第二步:6>4,去掉第三列。

第三步:5>4,去掉第二列。

第四步:找到数字4。

#include <stdio.h>

void find_num(int arr[3][3], int k, int *px, int *py)
{
	int i = 0;
	int j = *py - 1;
	int flag = 0;
	while (i <= *px - 1 && j >= 0)
	{
		if (arr[i][j] < k)
		{
			i++;
		}
		else if (arr[i][j] > k)
		{
			j--;
		}
		else
		{
			//找到了
			flag = 1;
			*px = i;
			*py = j;
			break;
		}
	}
	if (flag == 0)
	{
		*px = -1;
		*py = -1;
	}
}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int k = 0;
	scanf("%d", &k);
	int x = 3;
	int y = 3;
	find_num(arr, k, &x, &y);
	if (x == -1 && y == -1)
		printf("找不到\n");
	else
		printf("找到了,下标是:%d %d\n", x, y);
	return 0;
}

12. 字符串左旋

实现一个函数,可以左旋字符串中的k个字符。例如:

abcdef左旋2个字符得到cdefab。

方法一:

将首字符拿出,剩下的字符逐个左移,再将首字符放到最后。循环k次。

#include <stdio.h>
#include <string.h>

void Left_Move(char arr[], int k)
{
	int i = 0;
	int len = strlen(arr);
	k %= len;//当k>len时,余数就是左移的次数
	for (i = 0; i < k; i++)
	{
		char tmp = arr[0];//拿出首字符
		int j = 0;
		for (j = 0; j < len - 1; j++)
		{
			arr[j] = arr[j + 1];//左移
		}
		arr[len - 1] = tmp;//首字符放到最后
	}
}

int main()
{
	char arr[] = "abcdef";
	int k = 0;
	scanf("%d", &k);
	Left_Move(arr, k);
	printf("%s\n", arr);
	return 0;
}

方法二:

先将ab逆序得到ba,再将cdef逆序得到fedc,再将整体bafedc逆序得到cdefab。

#include <stdio.h>
#include <string.h>
#include <assert.h>

void reverse(char* left, char* right)
{
    assert(left && right);
    while (left < right)
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }

}

void Left_Move(char arr[], int k)
{
    int len = strlen(arr);
    k %= len;
    reverse(arr, arr + k - 1);//左
    reverse(arr + k, arr + len - 1);//右
    reverse(arr, arr + len - 1);//整体
}

int main()
{
    char arr[] = "abcdef";
    int k = 0;
    scanf("%d", &k);
    Left_Move(arr, k);
    printf("%s\n", arr);
    return 0;
}

方法三:

abcdef abcdef

#include <stdio.h>
#include <string.h>

void Left_Move(char arr[], int k)
{
    int len = strlen(arr);
    k %= len;
    char tmp[256] = { 0 };
    strcpy(tmp, arr + k);//将cdef拷到tmp
    strncat(tmp, arr, k);//在cdef后面追加ab
    strcpy(arr, tmp);//将tmp拷到arr
}

int main()
{
    char arr[] = "abcdef";
    int k = 0;
    scanf("%d", &k);//假设输入2,即左旋2个字符
    Left_Move(arr, k);
    printf("%s\n", arr);
    return 0;
}
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到