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;
}
结语
- 代码仅对思路作出实现,效率比较低下,代码质量较差,还请谅解。
- 若以上思路或程序有误,还请不吝赐教。
- 如果您有改进意见,欢迎指出。
- 程序的相关问题都欢迎交流。