习题6-3 使用函数输出指定范围内的完数
题目简介
本题要求实现一个计算整数因子和的简单函数,并利用其实现另一个函数,输出两正整数m和n(0<m≤n≤10000)之间的所有完数。所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。
函数接口定义
int factorsum( int number );
void PrintPN( int m, int n );
其中函数factorsum须返回int number的因子和;函数PrintPN要逐行输出给定范围[m, n]内每个完数的因子累加形式的分解式,每个完数占一行,格式为“完数 = 因子1 + 因子2 + … + 因子k”,其中完数和因子均按递增顺序给出。如果给定区间内没有完数,则输出一行“No perfect number”。
函数代码
int factorsum(int number)
{
int sum = 1;
int i = 2;
if(number!=1)
{
for (i = 2; i <= sqrt(number); i++)
{
if ((number%i) == 0)
{
sum = sum + i + (number/i);
}
}
if ((sum == number))
{
return number;
}
}
return 0;
}
void PrintPN(int m, int n)
{
int i = 0;
int j = 0;
int tmp = 0;
int tar = 0;
int flag = 0;
for (i = m; i <= n; i++)
{
int factor = factorsum(i);
if (factor == i)
{
flag = 1;
if (i == 1)
{
continue;
}
else
{
printf("%d = ", i);
for (tmp = 2; tmp <= sqrt(i); tmp++)
{
if ((i%tmp) == 0)
{
tar = tmp;
break;
}
}
//printf("flag = %d", flag);
for (j = 1; j < i; j++)
{
if (i%j == 0)
{
printf("%d", j);
if (j < (i / tar))
{
printf(" + ");
}
}
}
}
printf("\n");
}
}
if (flag == 0)
{
printf("No perfect number");
}
}
#####################################################################
习题6-4 使用函数输出指定范围内的Fibonacci数
题目简介
本题要求实现一个计算Fibonacci数的简单函数,并利用其实现另一个函数,输出两正整数m和n(0<m≤n≤10000)之间的所有Fibonacci数。所谓Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列。
函数代码
int fib(int n)
{
int a = 1;
int b = 1;
if (n >= 0 && n <= 2)
{
return b;
}
else
{
int i = 0;
for (i = 3; i <= n; i++)
{
int c = a + b;
a = b;
b = c;
}
}
return b;
}
void PrintFN(int m, int n)
{
int i = 0;
int flag = 0;
for (i = 1; fib(i) <= n; i++)
{
if ((fib(i) >= m) && (fib(i) <= n))
{
flag = 1;
printf("%d", fib(i));
if (fib(i + 1) <= n)
{
printf(" ");
}
}
}
if (flag == 0)
{
printf("No Fibonacci number");
}
}
#####################################################################
习题8-8 判断回文字符串
题目简介
本题要求编写函数,判断给定的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如“XYZYX”和“xyzzyx”都是回文。
函数代码
bool palindrome(char *s)
{
int sLen = strlen(s);
int right = sLen - 1;
int left = 0;
while (left <= right)
{
if (s[left] != s[right])
{
return false;
}
else
{
left++;
right--;
}
}
return true;
}
总结
一、在做6-3以及6-4题目时,
先将整体的循环写出来,确保对于大部分的数都适用,之后根据提示信息或者自己的经验,去判断可能在哪些点是特殊点,对这些点进行加入判断操作。
二、在做6-3的判断完数的题目时
(1)当时写完的时候,出现了部分测试点报错的问题,就是提示在最大范围时结果不正确。我上网搜了一下,1不是完数,我在写完整体函数时忘记考虑数字1的影响了。
(2)其实根据函数接口后面的对于每个函数需要完成的功能,我们知道将完数写成因子相加式时,这个 ‘+’ 的录入其实是一个大问题。
而在我写的代码中,
1、我在输出循环之前加了一个循环,用于找到最小因子。
for (tmp = 2; tmp <= sqrt(i); tmp++)
{
if ((i%tmp) == 0)
{
tar = tmp;
break;
}
}
2、此时拿这个完数除以最小因子就得到了这个完数的最大因子。因此在循环输出时,做一个判断,小于最大因子时,将 ’ + '带上。
for (j = 1; j < i; j++)
{
if (i%j == 0)
{
printf("%d", j);
if (j < (i / tar))
{
printf(" + ");
}
}
}
三、关于如何知晓数组的长度
1、对于数组长度
int main()
{
int count = 0;
char arr1[] = { 'a','b','c' };
char arr2[10] = { 'a','b','c' };
//数组个数未知
printf("%d\n", sizeof(arr1)); //结果是3
printf("%d\n", sizeof(arr1)/sizeof(arr1[0])); //结果是3
printf("%d\n", strlen(arr1)); //结果是随机值,因为他要往后去寻找\0的位置
//数组个数已知
printf("%d\n", sizeof(arr2)); //结果是10
printf("%d\n", strlen(arr2)); //结果是3
while (arr2[count] != '\0')
{
count++;
}
printf("count = %d\n", count); //结果是3
return 0;
}
(1)当数组大小未知时
说白了就是找不到 ‘\0’ 的位置,当你存入字符时,有多少就存入多少,sizeof(数组名)-数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节,而此时使用strlen(数组名)则会产生错误,因为它判断的依据是往后寻找到 ‘\0’ 的位置结束,但此时就不知道 ‘\0’ 的位置在哪,所以会产生错误
(2)当数组大小已知时,
当开辟好数组之后,这个数组的大小以及元素个数也就确定了。因此使用sizeof(数组名)计算的是整个数组的大小,sizeof(arr1)/sizeof(arr1[0])会得到最大元素个数。
对于strlen(数组名),此时
char arr2[10] = { ‘a’,‘b’,‘c’ }; // 长度为3
上式等价于:(2)char arr2[10] = { ‘a’,‘b’,‘c’ ,’\0’}; // 长度为3
也等价于:(3)char arr2[] = { ‘a’,‘b’,‘c’,’\0’ };// 长度为3
它就能找到 ‘\0’ 的位置,进而将此时数组含有多少元素给显示出来。
当然此时也可以用while循环去判断是否到达 ‘\0’,若到达就结束计数,将此时的计数变量打印出来。
2、对于字符串
int main()
{
int count = 0;
char arr1[] = "abcdef";
char arr2[10] = "abcdef";
printf("%d\n", sizeof(arr1));//结果是7
printf("%d\n", sizeof(arr1)/sizeof(arr1[0]));//结果是7
printf("%d\n", strlen(arr1));//结果是6
printf("%d\n", sizeof(arr2));//结果是10
printf("%d\n", strlen(arr2));//结果是6
while (arr2[count] != '\0')
{
count++;
}
printf("count = %d\n", count); //结果是6
return 0;
}
字符串在结尾之时是以 ‘\0’ 结尾的,即char arr1[] = “abcdef”;
等价于char arr1[] = “abcdef\0”;
以下是一些对应解释,理解下面这几句话,也就知晓上面代码为什么执行出来是这样的结果。
(1)、strlen()函数求出的字符串长度为有效长度,既不包含字符串末尾结束符 ‘\0’;
(2)、sizeof()操作符求出的长度包含字符串末尾的结束符 ‘\0’;
(3)、当在函数内部使用sizeof()求解由函数的形参传入的字符数组的长度时,得到的结果为指针的长度,既对应变量的字节数,而不是字符串的长度,此处一定要小心。
如果我讲的还不清楚的话,你们可以去这位博主的这篇博客下去进一步的了解这两者。
博主:wangran51
C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别