C语言课程实验8

C语言第八次实验

(1)编写一个函数判定给定的一个数n是否属于Fibonacci数列中的一项,函数的返回值为0(不属于)或者1(属于)。

思路

遍历Fibonacci数列的每一项,当第i项数小于n时,判断i+1项数与n的大小。

如果第i+1项小于n,继续查找;

如果第i+1项等于n,则查找成功;

如果第i+1项大于n,说明n不属于Fibonacci数列。

伪代码

while fib[i] < n:
	if fib[i+1] == n:
		find successful
	else if fib[i+1] > n:
		find failure
	else
		go on	

以下代码仅作为简单实现,未考虑程序效率,见谅。

#include <stdio.h>
#include <stdlib.h>

long fib(int x)
{
    if (x == 1 || x == 2) return 1;
    if (x > 2) return fib(x - 1) + fib(x - 2);
}

int has(int n)
{
    int i;
    int flag = 0;
    for (i = 1; fib(i) < n; ++i)
    {
        int tmp = fib(i + 1);
        if (n == tmp)
        {
            flag = 1;
            break;
        }
        else if (n < tmp)
        {
            break;
        }

    }
    return flag;
}

int main()
{
    int n = 0;
    printf("请输入一个正整数:");
    scanf("%d", &n);
    if (has(n)) printf("%d 属于 Fibonacci数列", n);
    else printf("%d 不属于 Fibonacci数列", n);

	return EXIT_SUCCESS;
}

(2)编写函数digit(int n,int k),返回正整数n中的第k位数字(从右边算起)。例如,digit(256,1)返回6,digit(256,3)返回2。如果k大于n的数字位数,则返回-1,如digit(256,4)。

思路

每次取最后一位数字,如果是要求的位数,直接输出,

如果不是要求的位数,则原数向右平移,末尾丢弃(除以10)

伪代码

i = 0
while n != 0:
	last_positon = n % 10
	if tmp is kth position
		print last_positon and exit
	else
		n pan right 1 position(n = n / 10)

代码

#include <stdio.h>
#include <stdlib.h>

int digit(int n, int k)
{
    int rem = 0;
    int i = 0;
    while (n && i < k)
    {
        rem = n % 10;
        n = n / 10;
        ++i;

    }
    if (i == k) return rem;
    else return -1;

}

int main()
{
    int n = 0, k = 0, ans = 0;
    printf("输入正整数(格式: n,k):\n");
    scanf("%d,%d", &n, &k);
    ans = digit(n, k);
    if (ans == -1) printf("数 %d 中不存在第 %d 位", n, k);
    else printf("数 %d 中第 %d 位是 %d", n, k, ans);

	return EXIT_SUCCESS;
}

(3)哥德巴赫猜想是:任何大于2的偶数都可以写成两个素数之和,例如4=2+2,6=3+3,8=3+5。到目前为止,这个猜想还没有被证明,但是在很大的范围内是成立的。编写一个程序,产生1000个随机正偶数,对每个偶数n,如果满足猜想,就输出n=a+b(a和b为素数)。要求编写一个函数testGlodbach(int n),判断偶数n是否符合猜想,如果是,则输出上述形式。

思路

generate 1000 evens to e[]
while x in e[]:
	while i form 2 to x/2:
		if i is prime and x-i is prime:
			print "x = i + (x-i)"
		else
			go on

代码未考虑效率,如果有改进意见,还请不吝赐教。

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

#define MAXSIZE 1001

int isPrime(int n)
{
	if (n == 1 || n == 2) return 0;
	int flag = 1;
	for (int i = 2; i <= sqrt(n); ++i)
	{
		if (n % i == 0)
		{
			flag = 0;
			break;
		}
	}
	return flag;

}

int found(int e[], int n, int v)
{
	int flag = 0;
	for (int i = 0; i < n; ++i)
	{
		if (e[i] == v) 
		{
			flag = 1;
			break;
		}
	}
	return flag;
}

void testGlodbach(int n)
{
	for (int i = 2; i < n / 2; ++i)
		if (isPrime(i) && isPrime(n - i))
		{
			printf("\t\t%d = %d + %d\n", n, i, n-i);
			break;
		}
}

int main()
{
	srand((unsigned int)time(NULL));

	int even[MAXSIZE] = { 0 };

	for (int i = 0; i < 1000;)
	{
		int r = rand();
		int randEven = r % 2 ? r+1 : r;
		if (randEven > 2 && !found(even, i, randEven)) even[i++] = randEven;
	}

	for (int i = 0; i < 1000; ++i)
	{
		testGlodbach(even[i]);
	}
	return EXIT_SUCCESS;
}

(4)黑洞数:任何一个数字不全相同的3位数,经有限次“重排求差”操作,总会得到495,因而495被称为3位黑洞数。所谓“重排求差”操作是指组成该数的数字重排后的最大数减去重排后的最小数。

例如,对3位数207:

​ 第一次重排求差:720-027=693。

​ 第二次重排求差:963-369=594。

​ 第三次重排求差:954-459=495。

编写程序,验证这一现象。

思路

while answer is not equal 495:
	extract every positon of arg from arr[]
	assending array arr[]
	min = increasing order of arr[]
	max = decreasing order of arr[]
	answer = max - min
	print "answer = max - min"

代码

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

// 增序
void selectSort(int arr[], int len)
{
	int i, j;

	for (i = 0; i < len - 1; i++)
	{
		int min = i;
		for (j = i + 1; j < len; j++)     
			if (arr[j] < arr[min])
				min = j;
		// 交换
		int tmp = arr[min];
		arr[min] = arr[i];
		arr[i] = tmp;
	}
}

// 输出一轮判断过程,并返回当前轮次迭代结果
int next(int arr[], int n, int th)
{
	selectSort(arr, n);
	//for (int i = 0; i < n; ++i)
	//	printf("%d ", arr[i]);
	int max = 0, min = 0, ans = 0;
	for (int i = 0; i < n; ++i)
	{
		min = min + arr[i] * powl(10, n - i - 1);
		max = max + arr[i] * powl(10, i);
	}
	ans = max - min;
	printf("第%d次重排求差:%03d - %03d = %03d\n", th, max, min, ans);
	return ans;
	
}
void testBlackHoleNum(int n)
{
	int arr[10] = { 0 }, th = 0;
	
	//for (int j = 0; j < i; ++j)
	//	printf("%d ", arr[j]);
	while (n != 495)
	{
		int tmp = n, i = 0;
		while (tmp)		// 取各位数字
		{
			arr[i++] = tmp % 10;
			tmp = tmp / 10;
		}
		n = next(arr, i, ++th);
	}
}

int main()
{
	int n = 0;
	printf("请输入一个数字不全相同的三位数:");

	scanf("%d", &n);

	testBlackHoleNum(n);

	return EXIT_SUCCESS;
}

(5)编写程序,求10个连续自然数,要求该10个数全部都是合数。所谓合数,就是该数存在除了1和它本身之外的因子。与合数相对应的是质数(即素数)。

思路

此程序实现比较简单,所以直接上代码。

代码

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

/// @brief 判断大于0的整数是否是质数
/// @param n 
/// @return 0 for 非质数;1 for 质数
int isComp(int n)
{
    if (n == 1 || n == 2) return 0;
    int flag = 0;
    for (int i = 2; i <= sqrt(n); ++i)
    {
        if (n % i == 0)
        {
            flag = 1;
            break;
        }
    }
    return flag;

}

int main()
{
    int count = 0,
        ans[10] = { 0 };

    for (int i = 2; count != 10 ; ++i)
    {
        if (isComp(i))
        {
            ans[count++] = i;
        }
        else
        {
            count = 0;
        }
    }

    for (int i = 0; i < 10; ++i)
    {
        printf("%d\t", ans[i]);
    }

	return EXIT_SUCCESS;
}

(6)有一个文件,其中包含了学生的学号,格式如下。假设现在老师要点几位学生回答问题。编写一个函数,每次调用从中随机抽取一个学生。在主函数中对其连续调用,并可以控制是否需要继续抽取。假设每次抽取的学生可以重复。说明:学号可以按整数的方式读取。

154772 154778 154784 154793

思路

将文件中所有学号读入数组,再随机抽取数组元素。如果文件过大可以考虑固定读取学号数量,如果需要抽取其他学号,就读取文件另外的内容,实现分批读取,此程序不考虑这种情况。

read student number from file to array
get one item of array randomly
if program go on:
	go to line 2
else
	exit

代码

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAXSIZE 100

void randDrawStudent(int stuno[], int n)
{
	int i = 0;
	i = rand() % n;
	printf("抽取学号:%d", stuno[i]);
}

int main()
{
	srand((unsigned int)time(NULL));
	FILE* fp = NULL;
	int stuno[MAXSIZE] = { 0 }, n = 0;
	if (fopen_s(&fp, "stuno.txt", "r"))
	{
		printf("文件打开失败");
		exit(-1);
	}
	while (!feof(fp))
	{
		fscanf_s(fp, "%d", &stuno[n++]);
	}
	int go = 1;
	while (go)
	{
		randDrawStudent(stuno, n);
		printf("\n是否继续抽取(1|0):");
		scanf("%d", &go);
	}

	if (fp)
	{
		fclose(fp);
		fp = NULL;
	}
	return EXIT_SUCCESS;
}

(7)编写函数void printUnsignedBinary(unsigned int x),该函数输出x的二进制形式。

思路

根据十进制数转二进制数的方法进行转换(原数对2取余的结果倒排)。

本程序直接采用取末尾后移位操作,但是具体原理是差不多的。

代码

#include <stdio.h>
#include <stdlib.h>

#define UINT_LAST_BIT(x) ((x)&(0x00000001))

void printUnsignedBinary(unsigned int x)
{
    int count = sizeof(x) * 8;
    unsigned ans[32] = { 0 };
    while (count > 0)
    {
        ans[--count] = UINT_LAST_BIT(x);
        x = x >> 1;
    }

    printf("\n");
    for (int i = 0; i < sizeof(x) * 8; ++i)
        printf("%u", ans[i]);
}
int main()
{
    int n = 0;
    printf("请输入一个正整数:");
    scanf("%d", &n);
    printUnsignedBinary(n);

	return EXIT_SUCCESS;
}

结语

  1. 代码仅对思路作出实现,效率比较低下,代码质量较差,还请谅解。
  2. 若以上思路或程序有误,还请不吝赐教。
  3. 如果您有改进意见,欢迎指出。
  4. 程序的相关问题都欢迎交流
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值