C语言基础编程题(一)

目录

1. 判断素数

2. 判断闰年

3. 最大公约数

4. 数9的个数

5. 分数求和

6. 求最大值

7. 乘法口诀表

8. 字符串逆序(递归实现)

9. 计算一个数的每位之和(递归实现)

10. 递归实现n的k次方

11. 数组操作

12. 交换数组

13. 求两个数二进制中不同位的个数

14. 打印整数二进制的奇数位和偶数位

15. 计算求和

16.打印水仙花数(加强版)

17.打印菱形

18.喝汽水问题

19.调整奇数偶数顺序

20.strcpy模拟实现


1. 判断素数

题目内容:

判断一个数是不是素数,打印100到200之间的素数并算出有几个素数。

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

//试除法
int main()
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 101; i <= 200; i+=2) //由于偶数一定不是素数 所以判断奇数即可
	{
		//sqrt是一个库函数,对i开平方 需要头文件<math.h>
		for (j = 2; j <= sqrt(i); j++) 
		{
			if (i % j == 0)
			{
				break;
			}
		}
		if (j > sqrt(i)) //上面循环有两种情况会退出:1:i % j == 0 2:j > sqrt(i) 情况2才能说明是素数
		{
			printf("%d ", i);
			count++;
		}
}
	printf("\n100--200共有:%d个素数\n", count);
	return 0;
}

注:若 i = a * b,则其中一个因子(a 或 b)一定小于等于根号i 

如:16 = 2*8 也=4 *4    其中,2和4均小于等于根号16

所以:要判断是否为素数(找的因子)只需要j 的范围在【2,sqrt(i)】之间即可

2. 判断闰年

题目内容:

打印1000年到2000年之间的闰年。

#include <stdio.h>

int main()
{	
//判断闰年的规则:(满足1或2即可)
//1.能被4整除且不能被100整除
//2.能被400整除
	int year = 0;
	int count = 0;
	for (year = 1000; year <= 2000; year++)
	{
		if (((year % 4 == 0) && (year % 100 != 0)) || year % 400 == 0)
		{
			printf("%d ", year);
			count++;
		}
	}
	printf("\n共有%d个闰年",count);
	return 0;
}

3. 最大公约数

题目内容:

给定两个数,求这两个数的最大公约数

//辗转相除法
#include <stdio.h>

int main()
{	
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d %d", &a, &b);
	while (c = a % b)
	{
		a = b;
		b = c;
	}
	printf("最大公约数为:%d",b);
	return 0;
}

//暴力求解
#include <stdio.h>
//先找到两个数中的最小值min(因为最大公约数最大能到min)
//暴力解出最大公约数
int main()
{	
	int a = 0;
	int b = 0;
	int min = 0;
	int i = 0;

	scanf("%d %d", &a, &b);
	if (a > b)
		min = b;
	else
		min = a;
	for (i = min; i > 0; i--)
	{
		if ((a % i == 0) && (b % i == 0))
			break;
	}
	
	printf("最大公约数为:%d",i);
	return 0;
}

4. 数9的个数

题目内容:

编写程序数一下1到 100 的所有整数中出现多少个数字9

#include <stdio.h>

int main()
{
	int i = 0;
	int count = 0;
	for (i = 1; i <= 100; i++)
	{
		if (i / 10 == 9)  //判断十位是否为9
			count++;
		if (i % 10 == 9)  //判断个位是否为9
			count++;
	}
	printf("\n1--100共有:%d个9\n", count);
	return 0;
}

5. 分数求和

题目内容:

计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,打印出结果

//不用逻辑判断的代码
#include <stdio.h>

int main()
{
    int i = 0;
    double sum = 0.0;
    int flag = 1;
    for (i = 1; i <= 100; i++)
    {
         sum += flag * 1.0 / i;
         flag *= -1;
    }
    printf("%lf", sum);
}


//常规思路代码
#include <stdio.h>

int main()
{
    int i = 0;
    double sum = 0.0;
    for (i = 1; i <= 100; i++)
    {
        if (0 == i % 2)
        {
            sum -= 1.0 / i;
        }
        else
            sum += 1.0 / i;
    }
    printf("%lf", sum);
}

注:除法操作符 / 他两边都是整数的时候,执行的是整数除法,如:1/2 = 0,但两边操作数只要有一个浮点数,执行的就是浮点数的除法

6. 求最大值

题目内容:

求10 个整数中最大值

#include <stdio.h>

int main()
{
    int arr[10] = { 0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;

    for(i = 0; i < sz; i++)
    {
        scanf("%d", &arr[i]);
    }
    int max = arr[0]; //易出错的一步
    for (i = 0; i < 10; i++)
    {
        if (arr[i] > max)
            max = arr[i];
    }
    printf("max = %d", max);
    return 0;
}

注:在定义最大值时,让其等于数组中的第一个数,而不是0(为了防止数组中全是负数的情况)

7. 乘法口诀表

题目内容:

在屏幕上输出9*9乘法口诀表

#include <stdio.h>

int main()
{
    int i = 0;
    //行数
    for (i = 1; i <= 9; i++)
    {
        int j = 0;
        //打印一行的多少列
        for (j = 1; j <= i; j++)
        {
            //打印一项
            printf("%d*%d = %-2d ", i, j, i * j);//如果不是%-2d会存在"错位"的现象
        }
        printf("\n");
    }

    return 0;
}

注意"错位"的现象:用%2d(右对齐)或%-2d(左对齐)解决

8. 字符串逆序(递归实现)

题目内容:

编写一个函数 reverse_string(char * string)(递归实现)

实现:将参数字符串中的字符反向排列,不是逆序打印。

比如:

char arr[] = "abcdef"; 逆序之后数组的内容变成:fedcba

以abcdef为例:

递归思路: 两端字符‘a’ ‘f’换位,中间剩余字符串“bcde”参与下次递归

如,第一步的具体步骤为:

① 创建tmp存储‘a’

②‘f’替换'a'的位置

③用‘\0’替换原来‘f’的位置(这样做的目的是:找到倒数第二个元素e的位置,因为strlen函数计算长度的方式是遇到'\0'终止,这样才能逆序中间剩余字符串

④当中间字符串逆序完毕,再将‘a’放入曾经‘f’的位置

注:对于逆序中间字符串的步骤,当中间字符串长度大于1,这样他们才有继续换位置 和参与下一次递归的必要

//递归版本
#include <stdio.h>
#include <string.h>

void reverse_string(char arr[])
{
	char tmp = arr[0];         //①
	int len = strlen(arr);
	arr[0] = arr[len - 1];    //②
	arr[len - 1] = '\0';      //③
	//中间字符串的逆序
	if (strlen(arr + 1) > 1)  //注
		reverse_string(arr + 1);
	arr[len - 1] = tmp;       //④
}
int main()
{
	char arr[100] = { 0 };
	//scanf("%s", arr);//有问题,遇到空格时就终止了
	gets(arr);//读取一行,有空格也会读取
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}


//非递归版本
#include <stdio.h>
#include <string.h>

void reverse_string(char arr[])
{
	int left = 0;
	int right = strlen(arr) - 1;
	
	while (left < right)
	{
		char tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}

}
int main()
{
	char arr[100] = { 0 };
	//scanf("%s", arr);
	gets(arr);
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}

9. 计算一个数的每位之和(递归实现)

题目内容:

写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和

例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19

输入:1729,输出:19

递归思路:

DigitSum(1719)  ==> DigitSum(1719/10) + (1719%10)

#include <stdio.h>

int DigitSum(int n)
{
	if (n > 9)
		return DigitSum(n / 10) + n % 10;

	else		
	return n;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int sum = DigitSum(n);
	printf("%d", sum);
	return 0;
}

10. 递归实现n的k次方

题目内容:

编写一个函数实现n的k次方,使用递归实现。

递归思路:n ^ k = n * (n ^ (k-1))

#include <stdio.h>

double Pow(int n, int k)
{
	if (k == 0)
		return 1.0;
	else if (k > 0)
		return (double)n * Pow(n, k - 1);
	else
		return 1.0 / Pow(n , -k);
}
int main()
{
	int n = 0;
	int k = 0;
	
	scanf("%d%d", &n,&k);
	double ret = Pow(n,k);
	printf("%lf", ret);
	return 0;
}

11. 数组操作

题目内容:

创建一个整形数组,完成对数组的操作

  1. 实现函数init() 初始化数组为全0
  2. 实现print()  打印数组的每个元素
  3. 实现reverse()  函数完成数组元素的逆置。

要求:自己设计以上函数的参数,返回值。

#include <stdio.h>

void init(int *a, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		*(a + i) = 0;
	}
}

void print(int* a, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(a + i));
	}
	printf("\n");
}

void reverse(int* a, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left < right)
	{
		int temp = a[left];
		a[left] = a[right];
		a[right] = temp;
		left++;
		right--;
	}
}


int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	init(arr,sz);
	print(arr,sz);
	int brr[5] = { 1, 2, 3, 4, 5 };
	reverse(brr,sz);
	print(brr, sz);
	return 0;
}

注:在编写函数时尽量不要有多余的操作(如:初始化函数,那就初始化即可,不需要打印出来),另外,逆置数组是要求把数组元素逆置而不只是逆序打印

12. 交换数组

题目内容:

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

#include <stdio.h>

void SwapArr(int* arr1, int* arr2, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		int temp = arr1[i];
		arr1[i] = arr2[i];
		arr2[i] = temp;
	}
}

int main()
{
	int arr1[] = { 1, 3, 5, 7, 9 };
	int arr2[] = { 2, 4, 6, 8, 0 };
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	SwapArr(arr1, arr2, sz);
    return 0;
}

13. 求两个数二进制中不同位的个数

题目内容:

编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同? 

输入例子:

1999 2299

输出例子:7

#include <stdio.h>


//方法一:
int get_diff_bit1(int m, int n)
{
	//一个数与1按位与,可知从右往左第一位是0还是1
	//eg:11 - 十进制
	//00000000000000000000000000001011 - 二进制
	//00000000000000000000000000000001 - 和1按位与 结果为1,若最右是0,则结果为1
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) != ((n >> i) & 1))
			count++;
	}
	return count;
}


//方法二:
//要求m与n之间有多少位不同,就相当于求 m^n后二进制序列里有多少个1(因为异或相同为0相异为1)
//又已知a & (a - 1)可以使a从左往右第一个1变成0,所以代码如下:
int get_diff_bit2(int m, int n)
{
	int i = 0;
	int count = 0;
	int tmp = m ^ n;
	while (tmp)
	{
		tmp = tmp & (tmp - 1);
		count++;
	}
	return count;
}

int main()
{
	int m = 0;
	int n = 0;
	scanf("%d%d", &m, &n);
	
	int count = get_diff_bit2(m, n);

	printf("%d\n", count);
}

14. 打印整数二进制的奇数位和偶数位

题目内容:

获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

#include <stdio.h>

int main()
{
	int m = 0;
	scanf("%d", &m);
	//eg:11
	//00000000000000000000000000001011

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

15. 计算求和

题目内容:

求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,

例如:2+22+222+2222+22222

#include <stdio.h>

int main()
{
	int a = 0;
	int n = 0;
	int i = 0;
	scanf("%d%d", &a, &n);
	int b = 0;
	int sum = 0;

	for (i = 0; i < n; i++)
	{
		b = b * 10 + a;
		sum += b;

	}
	printf("%d\n", sum);
	
	return 0;
}

16.打印水仙花数(加强版)

题目内容:

求出0~100000之间的所有“水仙花数”并输出。

“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3+5^3+3^3,则153是一个“水仙花数”。

int main()
{
	int i = 0;

	for (i = 0; i <= 100000; i++)
	{
		//判断i是否为自幂数
		//1. 计算i的位数 - n
		int tmp = i;
		int count = 1;
		int sum = 0; //*易错点*,每次循环开始时sum要归0,不能写在循环外面
		while (tmp /= 10)
		{
			count++;
		}
		//2.获得i的每一位,计算其每一位的n次方和
		tmp = i;
		while (tmp)
		{
			sum += pow(tmp % 10, count);//pow为求幂的库函数,需要头文件math.h
			tmp /= 10;
		}
		//3.比较并打印
		if (i == sum)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

17.打印菱形

题目内容:

用C语言在屏幕上输出一个菱形。

#include <stdio.h>

int main()
{
	//打印一个菱形
	int line = 0; //行数
	int i = 0;

	scanf("%d", &line); //假设为6
	//菱形上半部分打印line行
	for (i = 0; i < line; i++)
	{
		//打印一行
		//先打印空格,再打印* 
		//第一行打印line - 1个空格,第二行line - 2个空格...
		int j = 0;
		for (j = 0; j < (line - 1 - i); j++)
		{
			printf(" ");
		}
		for (j = 0; j < (2 * i + 1); j++)
		{
			printf("*");
		}
		printf("\n");
	}
	//下半部分打印line - 1行
	for (i = 0; i < line - 1; i++)
	{
		 //打印一行
		//先打印空格,再打印*
		int j = 0;
		for (j = 0; j < i + 1; j++)
		{
			printf(" ");
		}
		for (j = 0; j <(line - 1 - i) * 2 - 1; j++)
		{
			printf("*");
		}
		printf("\n");
	}
	return 0;
}

18.喝汽水问题

题目内容:

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。

#include <stdio.h>

int main()
{
	int money = 0;
	int total = 0;  //总共换了多少瓶汽水
	int empty = 0;  //现在手里有多少空瓶

	scanf("%d", &money); //20
	total += money; //用钱买汽水
	empty = money;  //由汽水变空瓶

	while (empty >= 2)
	{
		total += empty / 2;//空瓶换来的汽水
		empty = empty / 2 + empty % 2;//*盘点手里的空瓶数
	}
	printf("total = %d\n", total);
	
	return 0;
}

19.调整奇数偶数顺序

题目内容:

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

思路:双指针:在数组中从前往后找到一个偶数,从后往前找到一个奇数,交换,指针向中间移动

#include <stdio.h>

//简单的版本
void move_arr1(int *arr, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left < right)
	{
		if (arr[left] % 2 == 0)
		{
			if (arr[right] % 2 == 1)
			{
				int tmp = arr[left];
				arr[left] = arr[right];
				arr[right] = tmp;
			}
			else
			{
				right--;
			}
		}
		else
		{
			left++;
		}
	}
}

//更易理解的版本,但更复杂
//该方法要单独考虑数组全为奇数或全为偶数的情况:
//若全是奇数,left会一直++,出现越界的情况

void move_arr2(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;
		}
	}
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	move_arr1(arr , sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));//验证
	}
	return 0;
}

20.strcpy模拟实现

题目内容:

模拟实现库函数strcpy

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

char* my_strcpy(char* dest, const char* src) 
                //const为了保证拷贝的数组不发生变化,防止输错了的时候改变了原数组的值
{
	assert(dest && src); //assert:断言(当dest或src为空时,会报错),需要头文件<assert.h>                    
	char* ret = dest;
	while (*dest++ = *src++)
	{
		; //一举两得,既将arr1赋值了hello\0,且赋值\0后,循环条件判定为假,终止循环
	}
	return ret;
}

//简化前的代码
void my_strcpy2(char* dest, char* src)
{
	assert(dest != NULL);//断言
	assert(src != NULL);//断言
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;//处理'\0'
}

int main()
{
	char arr1[20] = "xxxxxxxxxxxxx";
	char arr2[] = "hello";
    my_strcpy(arr1, arr2);
	printf("%s", arr1);
	printf("%s\n",my_strcpy(arr1, arr2));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_62934529/article/details/123215709