zl程序教程

您现在的位置是:首页 >  其他

当前栏目

经典例题(一)——经典例题的归纳总结。

2023-03-07 09:43:20 时间

题目

1、素数打印

题目:实现一个函数,判断一个数是不是素数。利用上面实现的函数打印100到200之间的素数。

这里,我们要先了解素数的定义,素数也叫质数 ,即在正整数中,除了1与本身之外没有其他约数的数(1除外)。 方法一: 也就是说,这个数只能被1和它本身整除。了解这一点后我们开始入手写代码,在这里我们最容易想到的方法就是试除法,即从2开始,不断地对那个数进行试除,假设这个数是n,直到试除到n(不包含n)为止,如果没有出现可以被整除的数,则n就是素数。

这里我们先来看一下如何实现对一个数是否为素数的判定:

#include<stdio.h>
void is_prime(int i)

{
	//用[2,i)之间的数进行试除
	int j = 0;
	//这里我们定义一个变量,假如这个变量最后是1,说明它是素数
	//                     假如是0,说明不是素数。
	int flag = 1;
	for (j = 2; j < i; j++)
	{
		//==0,说明这个数能被j整除
		if (i % j == 0)
		{
			//能被整除,说明i不是素数,给flag赋值为0
			flag = 0;
			printf("%d 不是素数", i);
			break;//没有继续试除的必要了,因为已经出现别的约数了,可以直接停止循环
		}
	}
	//经历以上循环后,如果flag还是1,说明没有别的约数了。即,i是素数
	if (flag == 1)
	{
		printf("%d 是素数", i);
	}
}

int main()
{
	//如果一个正整数除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下
	int i = 0;
	scanf("%d", &i);
	//注意一点,1不是素数
	if (i == 1)
	{
		printf("%d 不是素数", i);
	}
	else
	{
		//进行素数判定
		is_prime(i);
	}
	return 0;
}

这里我们需要注意的是,=与==的区别,前者为赋值,后者是用来判断相等,千万不要用混了。

但是,上述方法有一个缺陷:就是超过i一半的数据,肯定不是i的倍数,上述进行了许多没有意义的运算,因此可以换一种方法,大家看举个例子,假如我们要判断100是不是素数,我们有必要从2试除到99吗?答案是否定的,我们只需要试除到它的开平方,也就是10,就可以判定是否为素数。以此类推来判断别的数

这里就需要用到库函数,sqrt(),专门用来求开平方的,使用必须包含头文件<math.h>

方法二:优化后:

#include<stdio.h>
#include<math.h>
void is_prime(int i)

{
	//用[2,sqrt(i)]之间的数进行试除,避免大量重复运算
	int j = 0;
	int flag = 1;
	for (j = 2; j <=sqrt(i); j++)
	{
		if (i % j == 0)
		{
			flag = 0;
			printf("%d 不是素数", i);
		}
	}
	if (flag == 1)
	{
		printf("%d 是素数", i);
	}
}

int main()
{
	int i = 0;
	scanf("%d", &i);
	//注意一点,1不是素数
	if (i == 1)
	{
		printf("%d 不是素数", i);
	}
	else
	{
		//进行素数判定
		is_prime(i);
	}
	return 0;
}

这么做就避免了大量重复计算。 接下来,了解这个后,进行打印1-100之间的素数就容易多了 题解:

#include<stdio.h>
#include<math.h>
//打印1-100之间的素数
void print_prime()
{
	int j = 0;
	int v = 0;
	for (v = 100; v <= 200; v++)
	{
		int prime = 1;//假设1为素数,0不是素数
		for (j = 2; j <= sqrt(v); j++)
		{
			if (v % j == 0)
			{
				prime = 0;
				break;
			}
		}
		if (prime == 1)
		{
			printf("%d ", v);
		}
	}
}

void is_prime(int i)

{
	//用[2,sqrt(i)]之间的数进行试除,避免大量重复运算
	int j = 0;
	int flag = 1;
	for (j = 2; j <=sqrt(i); j++)
	{
		if (i % j == 0)
		{
			flag = 0;
			printf("%d 不是素数\n", i);
		}
	}
	if (flag == 1)
	{
		printf("%d 是素数\n", i);
	}
}

int main()
{
	int i = 0;
	scanf("%d", &i);
	//注意一点,1不是素数
	if (i == 1)
	{
		printf("%d 不是素数\n", i);
	}
	else
	{
		//进行素数判定
		is_prime(i);
		//打印素数
		print_prime();
	}
	return 0;
}

2、二分查找

编写代码在一个整形有序数组中查找具体的某个数 要求:找到了就打印数字所在的下标,找不到则输出:找不到。

我们先了解以下什么是二分查找:如图所示

了解后我们开始入手答题:

#include<stdio.h>

int main()
{
	//定义查找的数
	int k = 0;
	//定义整型数组
	int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25 };
	int left = 0;//左下标
	//右下标为总元素个数-1,因为下标从0开始
	int right = sizeof(arr) / sizeof(arr[0]) - 1;
	printf("请输入要查找的数:->");
	scanf("%d", &k);

	//左下标始终小于右下标,当相等时就说明找到那个数了
	while (left <= right)
	{
		//中间坐标
		int mid = (right + left) / 2;
		//中间坐标对应元素<要求的,那么新的查找区域左边坐标就变成了mid+1,右边不变
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		//中间坐标对应元素>要求的,那么新的查找区域右边坐标就变成了mid-1,左边不变
		if (arr[mid] > k)
		{
			right = mid - 1;
		}
		//左右坐标相等,说明确定这个值了
		if (arr[mid] == k)
		{
			printf("找到了,下标为%d", mid);
			break;//找到结果,中止循环
		}
	}
	//左下标大于右下标说名这个数是不存在的
	if (left > right)
	{
		printf("找不到");
	}

	return 0;
}

注意一点,一定要是有序的数组!!!!从小到大或者从大到小

3、数组交换

将数组A中的内容和数组B中的内容进行交换。(数组一样大)

方法1:

这里我们主要需要知道一点,就是如何完成两个数据的交换,举个例子,一瓶水,一瓶尿,如何让它们进行交换,肯定是需要借助第三个空瓶子,把水倒进空瓶子,再把尿倒进原来盛水的瓶子,在把空瓶子里的水倒进原来盛尿的瓶子,就完成了交换(话粗理不粗)

在C语言里也是一样

千万不可以直接a=b,b=a,如果一旦这样的话,直接第一步b就把a覆盖了。 理清后入手:

#include <stdio.h>
int main()
{
	int arr1[10] = { 0 };
	int arr2[10] = { 0 };
	int i = 0;


	printf("请输入10个数字:>");
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &arr1[i]);
	}
	printf("请输入10个数字:>");
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &arr2[i]);
	}
	//交换
	for (i = 0; i < 10; i++)
	{
		int tmp = arr1[i];
		arr1[i] = arr2[i];
		arr2[i] = tmp;
	}

	return 0;
}

这里就完成数组交换了:打印看一下

方法2: 当然,我们也可以用指针来解题,指针表示的是地址,我们把两个数组的地址都进行交换,也可以实现数组交换,如下:

#include<stdio.h>
//数组名表示首元素地址
void swap(int* arr, int* brr, int sz)
{
	int n = 0;
	for (n = 0; n < sz; n++)
	{
		//首元素地址也就是arr[0],brr[0]的地址,加1就表示arr[1]与brr[1]的地址
		//解引用后进行交换,也可以实现数组交换
		int tmp = *(arr + n);
		*(arr + n) = *(brr + n);
		*(brr + n) = tmp;
	}
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };
	int brr[] = { 9,10,11,12,13,14,15,16 };
	//数组一样大
	int sz = sizeof(arr) / sizeof(arr[0]);
	//进行交换
	swap(arr, brr, sz);
	int i = 0;
	//打印arr,brr
	printf("arr=");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	printf("brr=");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", brr[i]);
	}

	return 0;
}

4、月份打印

KiKi想获得某年某月有多少天,请帮他编程实现。输入年份和月份,计算这一年这个月有多少天。 输入描述: 多组输入,一行有两个整数,分别表示年份和月份,用空格分隔。 输出描述: 针对每组输入,输出为一行,一个整数,表示这一年这个月有多少天。

方法一: 这里我们要知道,闰年2月有29天,平年28天,所以我们要进行闰年的判断,这里我们有两种方法, 第一种就是直接列举,把每个月份都列举出来,平年与闰年只有2月不同,如下;

#include <stdio.h>
int main()
{
    int year = 0;
    int month = 0;
    //多组输入
    while (scanf("%d %d", &year, &month) != EOF)
    {
        //判断是否闰年
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        {
            //2月
            if (month == 2)
            {
                printf("29\n");
            }
            //不是二月份的时候
            else
                goto end;
        }

        //不是闰年
        else
        {
            //2月
            if (month == 2)
            {
                printf("28\n");
            }
            //不是二月
            else
                goto end;
        }
        //列举
    end:
        if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
        {
            printf("30\n");

        }

        else if ((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12))
        {
            printf("31\n");
        }
    }

    return 0;
}

这样做是可以,不过看起来可能有点繁琐,大家看另一个方法: 方法二:

#include<stdio.h>
int main()
{
	int y, m;
	//我们把一年的12个月的天数都放在数组里
	int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
//多组输入
	while (scanf("%d %d", &y, &m) != EOF)
	{
		//天数对应数组的下标,数组的下标就是月份-1,比如,一月对应的就是days[0]
		int day = days[m - 1];
		//判断闰年
		if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
		{
			//如果是闰年,二月就+1天
			if (m == 2)
			{
				day += 1;
			}
		}

		printf("%d\n", day);

	}

	return 0;
}

是不是更简洁巧妙了一点,利用数组,列举所有月份天数,数组下标就是月份-1,如果是闰年,就二月对应(days[1]=28)+1即29天

5、字母大小写转换

完成字母大小写转换,有一个字符,判断它是否为大写字母,如果是,将它转换成小写字母;反之则转换为大写字母。 输入描述: 多组输入,每一行输入一个字母。 输出描述: 针对每组输入,输出单独占一行,输出字母的对应形式

这题很简单,主要就是知道大写字母与小写字母的ASCLL码值相差32,下图为ASCLL表

题解:

#include<stdio.h>

int main()
{
    char letter = '0';
    //多组输入
    while (scanf("%c", &letter) != EOF)
    {
        if ((letter >= 'a') && (letter <= 'z'))
        {
            letter -= 32;
            printf("%c\n", letter);

        }
        else if ((letter >= 'A') && (letter <= 'Z'))
        {
            letter += 32;
            printf("%c\n", letter);

        }
    }
    return 0;

6、字符串逆序并打印

将一个字符串str的内容颠倒过来,并输出。 数据范围:1≤len(str)≤10000 输入描述: 输入一个字符串,可以有空格 输出描述: 输出逆序的字符串

这里首先就是注意,输入可以有空格,那我们就不能用scanf了,因为scanf只能读取到空格,改用gets。

这里我是利用指针求解的,当然也可以用递归(不容易理解),或者一些别的方法,在这里就先介绍本人的解题:

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

void reversed(char* str)
{
	//strlen专门求字符串长度,头文件<string.h>
	int len = strlen(str);
	//将str首元素地址放在left里
	char* left = str;
	//末元素地址=首元素地址+元素个数-1,存放在right里
	char* right = str + len - 1;
	//当left=right时,就说明没有可以调换的了
	while (left < right)
	{
		//地址解引用后就会找到所指向的元素,进行交换即可实现字符串逆序
		char tmp = *left;
		*left = *right;
		*right = tmp;
		
		left++;
		right--;
	}
	printf("%s", str);
}

int main()
{
	char str[10000] = { 0 };
	//输入字符串,在这里用gets是考虑到题目要求,输入可以存在空格,而scanf只能读取到空格,空格后面的读取不了
	gets(str);
	//数组名表示数组首元素地址
	reversed(str);

	return 0;
}

end

望诸君努力,共同进步!