打印斐波那契数列的前n项及拓展

计算斐波那契数列前15项并逆序输出,如:1 1 2 3 5 8 13 21 .....

思路:

        1、首先了解斐波那契数列的特点:前两项为1,从第三项开始,每一项为前两项的和,所以我们在计算斐波那契数列之前,可以将其前两项先定义下来。

        2、由于打印的是前n项,所以我们需要采用循环结构来简化计算过程,提高程序的运算效率

完整代码实现如下:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,n;
    int arr[]={1,1};   //注意有时候报错,报错的话可以将元素的值直接确定
    printf("请输入要打印的项数:\n");
    scanf("%d",&n);
    for(i=2;i<n;i++)
    {
        arr[i]=arr[i-1]+arr[i-2];          //从第三项开始,每一项为前两项的和
    }
    for(i=0;i<n;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

拓展:

将计算的结果实现逆序输出。

思路:

        这需要我们将计算的结果逆序打印,数组的顺序与下标相关,我们可以根据下标来实现效果

完整代码如下:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int i,n;
    int arr[]={1,1};
    printf("请输入要打印的项数:\n");
    scanf("%d",&n);
    for(i=2;i<n;i++)
    {
        arr[i]=arr[i-1]+arr[i-2];
    }
    for(i=n-1;i>=0;i--)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

实现下过如下图所示:

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <limits.h> //宏定义与类型别名 #define EPS 1e-9 #define MOD 100000000 #define in int #define ll long long #define fl float #define db double #define ch char #define vd void #define pr printf #define sc scanf #define pr_in(x) pr("%d", x) #define pr_ll(x) pr("%lld", x) #define pr_st(x) pr("%s", x) #define pr_inn(x) pr("%d\n", x) #define pr_lln(x) pr("%lld\n", x) #define pr_stn(x) pr("%s\n", x) #define feq(a, b) (fabs((a) - (b)) < EPS) //函数声明:库函数模拟 //求在参数str所指向的字符串的n个字节中检索第一次出现字符c的位置 vd* memchr_exp(const vd* str, in c, size_t n); //函数声明:输入输出辅助 //要求快速输入 in fast_read(); //要求数组输入 vd scan_arr(in arr[], in n); //要求数组输出 vd print_arr(in arr[], in n); //函数声明:数学计算 //求某个数的阶乘(非递归) ll factorial1(in n); //求某个数的阶乘(递归) ll factorial2(in n); //求斐波那契数列第某个数(非递归) ll fibonacci1(in n); //求斐波那契数列第某个数(递归) ll fibonacci2(in n); //求斐波那契数列第某个数(递归+优化) ll fibonacci2_memo(in n); //求排列数P(n数,排k) ll permute(in n, in k); //求组合数C(n数,组k) ll combine(in n, in k); //求快速幂(模幂运算) ll pow_mod(ll base, ll exp); //求两个数的最大公因数 in gcd(in a, in b); //求两个数的最小公倍数 in lcm(in a, in b); //求某个数是否为素数 in is_prime(in n); //求10进制转<10进制(待拓展) in digit_change(in n, in digit2); //求2进制数转10进制数 in bin_to_dec(in bin); //求某个数字的反向输出 in turn_digits(in n); //函数声明:字符串处理 //求某个数(字符串形式)是否为回文 in is_palindrome(const ch* s); //求某数是否含某数字(一般数) in contains_digit1(in n, in p); //求某数是否含某数字(超大数,%s输入num_str) in contains_digit2(const ch* num_str, in p); //求给定字符串出现频次 vd string_frequency(const ch* str); //函数声明:数组操作 //求某十进制数的各位数 vd extract_digits(in num, in digits[]); //函数声明:排序与搜索 //要求两个整数交换 vd swap(in* a, in* b); //要求升序排列(冒泡排序) vd bubble_sort(in* arr, size_t n); //要求升序排列(快速排序1到r) vd quick_sort(in arr[], in l, in r); //要求全排数组(start到end) vd permute(in arr[], in start, in end); //要求翻转数组 vd reverse_arr(in arr[], in n); //求数组各元素的和 in sum_arr(in arr[], in n); //求数组最大元素下标 in max_index(in arr[], in n); //求数组某元素的位置(升序,n元,二分找x) in binary_search(in arr[], in n, in x); //函数声明:几何计算 //求平面上两点的距离 db distance_2d(db x1, db y1, db x2, db y2); //求三角形的面积(2倍) ll triange_area_2(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3); //求凸多边形面积(2倍) ll n_triangle_area_2(in n, ll x[], ll y[]); //函数声明:时间日期 //求某年是否为闰年 in is_leap(in year); //求某年某月的天数 in get_days_of_month(in year, in month); //求某年某月某日为星期几 in get_week_day(in year, in month, in day); int main() { } //函数实现:库函数模拟 vd* memchr_exp(const vd* str, in c, size_t n) { const unsigned ch* ptr = (const unsigned ch*)str; unsigned ch uc = (unsigned ch)c; for (size_t i = 0; i < n; i++) { if (ptr[i] == uc) { return (vd*)(ptr + i); } } return NULL; } //in main() //{ // ch str[] = "Hello, world!"; // ch* result = (ch*)memchr_exp(str, &#39;w&#39;, sizeof(str)); // if (result != NULL) // { // pr("字符&#39;w&#39;首次出现在索引:%d\n", result - str); // pr("子字符串:%s\n", result); // } // else // { // pr("未找到字符&#39;w&#39;\n"); // } // result = (ch*)memchr_exp(str, &#39;x&#39;, sizeof(str)); // if (result == NULL) // { // pr("字符&#39;x&#39;未找到\n"); // } // return 0; //} //函数实现:输入输出辅助 //要求快速输入 in fast_read() { in x = 0, f = 1; ch c = getchar(); while (c < &#39;0&#39; || c > &#39;9&#39;) { if (c == &#39;-&#39;) f = -f; c = getchar(); } while (c >= &#39;0&#39; && c <= &#39;9&#39;) { x = x * 10 + c - &#39;0&#39;; c = getchar(); } return x * f; } //要求数组输入 vd scan_arr(in arr[], in n) { for (in i = 0; i < n; i++) { sc("%d", &arr[i]); } } //要求数组输出 vd print_arr(in arr[], in n) { for (in i = 0; i < n; i++) { pr("%d ", arr[i], " \n"[i == n - 1]); } } //函数实现:数学计算 //求某个数的阶乘(非递归) ll factorial1(in n) { if (n < 0) return -1; if (n > 20) return -1; ll result = 1; for (in i = 2; i <= n; i++) { result *= i; } return result; } //求某个数的阶乘(递归) ll factorial2(in n) { if (n <= 1) { return 1; } return n * factorial2(n - 1); } //求斐波那契数列第某个数(非递归) ll fibonacci1(in n) { if (n == 0) return 0; if (n == 1) return 1; ll prev = 0; ll curr = 1; ll next; for (in i = 2; i <= n; i++) { next = prev + curr; prev = curr; curr = next; } return curr; } //求斐波那契数列第某个数(递归) ll fibonacci2(in n) { if (n == 1 || n == 2) { return 1; } return fibonacci2(n - 1) + fibonacci2(n - 2); } //求斐波那契数列第某个数(递归+优化) ll memo[1000] = { 0 }; ll fibonacci2_memo(in n) { if (n == 1 || n == 2) { return 1; } if (memo[n] != 0) { return memo[n]; } memo[n] = fibonacci2_memo(n - 1) + fibonacci2_memo(n - 2); return memo[n]; } //求排列数P(n数,排k) ll permute(in n, in k) { if (k < 0 || n < 0 || k > n) { return -1; } ll result = 1; for (in i = n - k + 1; i <= n; i++) { result *= i; } return result; } //求组合数C(n数,组k) ll combine(in n, in k) { if (k < 0 || n < 0 || k > n) { return -1; } if (k > n - k) { k = n - k; } ll result = 1; for (in i = 0; i < k; i++) { result = result * (n - i) / (i + 1); } return result; } //求快速幂(模幂运算) ll pow_mod(ll base, ll exp) { ll result = 1; while (exp > 0) { if (exp & 1) { result = (result * base) % MOD; } base = (base * base) % MOD; exp >>= 1; } return result; } //求两个数的最大公因数 in gcd(in a, in b) { if (a < 0) a = -a; if (b < 0) b = -b; while (b != 0) { in temp = b; b = a % b; a = temp; } return a; } //求两个数的最小公倍数 in lcm(in a, in b) { return a / gcd(a, b) * b; } //求某个数是否为素数 in is_prime(in n) { if (n <= 1) { return 0; } else if (n <= 3) { return 1; } else if (n % 2 == 0 || n % 3 == 0) { return 0; } for (in i = 5; i * i <= n; i += 6) { if (n % i == 0 || n % (i + 2) == 0) { return 0; } } return 1; } //求10进制转<10进制(待拓展) in digit_change(in n, in digit2) { in rem = n; in mod[100]; in i = 0; while (rem > 0) { mod[i] = rem % digit2; rem = rem / digit2; i++; } in result = 0; in ten = 1; for (in j = 0; j < i; j++) { result += mod[j] * ten; ten = 10 * ten; } return result; } //求2进制数转10进制数 in bin_to_dec(in bin) { if (bin == 0) { return 0; } if (bin < 0) { return -1; } in decimal = 0; in base = 1; while (bin > 0) { in digit = bin % 10; if (digit != 0 && digit != 1) { return -1; } decimal += digit * base; base *= 2; bin /= 10; } return decimal; } //求某个数字的反向输出 in turn_digits(in n) { in digits[10] = { 0 }; in i = 0; in num = n; while (num > 0) { digits[i++] = num % 10; num /= 10; } in ans = 0; for (in j = 0; j < i; j++) { ans = ans * 10 + digits[j]; } return ans; } //函数实现:字符串处理 //求某个数(字符串形式)是否为回文 in is_palindrome(const ch* s) { if (s == NULL) { return 0; } in left = 0; in right = strlen(s) - 1; while (left < right) { if (tolower(s[left]) != tolower(s[right])) { return 0; } left++; right--; } return 1; } //求某数是否含某数字(一般数) in contains_digit1(in n, in p) { ch str[50]; ch target = &#39;0&#39; + p; sprintf(str, "%d", n); for (in i = 0; str[i] != &#39;\0&#39;; i++) { if (str[i] == target) { return 1; } } return 0; } //求某数是否含某数字(超大数,%s输入num_str) in contains_digit2(const ch* num_str, in p) { ch target = &#39;0&#39; + p; for (in i = 0; num_str[i] != &#39;\0&#39;; i++) { if (num_str[i] < &#39;0&#39; || num_str[i] > &#39;9&#39;) { continue; } if (num_str[i] == target) { return 1; } } return 0; } //求给定字符串出现频次 vd string_frequency(const ch* str) { in freq[128] = { 0 }; for (in i = 0; str[i] != &#39;\0&#39;; i++) { unsigned ch c = str[i]; if (c == &#39; &#39; || isprint(c)) { freq[c]++; } } int count = 0; for (in i = 0; i < 128; i++) { if (freq[i] > 0) { count++; if (i == &#39; &#39;) { pr("blank: %d\n", freq[i]); } else { pr("&#39;%c&#39;: %d\n", i, freq[i]); } } } } //函数实现:数组操作 //求某十进制数的各位数 vd extract_digits(in num, in digits[]) { if (num == 0) { digits[0] = 0; digits[1] = -1; return; } in i = 0; while (num > 0) { digits[i++] = num % 10; num /= 10; } } //函数实现:排序与搜索 //要求两个整数交换 vd swap(in* a, in* b) { in temp = *a; *a = *b; *b = temp; } //要求升序排列(冒泡排序) vd bubble_sort(in* arr, size_t n) { if (arr == NULL || n < 2) { return; } for (size_t i = 0; i < n - 1; i++) { in swapped = 0; for (size_t j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { in temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; swapped = 1; } } if (!swapped) { break; } } } //要求升序排列(快速排序1到r) vd quick_sort(in arr[], in l, in r) { if (l >= r) { return; } in i = l, j = r; in pivot = arr[(l + r) / 2]; while (i <= j) { while (arr[i] < pivot) i++; while (arr[j] > pivot) j--; if (i <= j) { swap(&arr[i], &arr[j]); i++; j--; } } quick_sort(arr, l, j); quick_sort(arr, i, r); } //要求全排数组(start到end) vd permute_arr(in arr[], in start, in end) { if (start == end) { for (in i = 0; i <= end; i++) { pr("%d ", arr[i]); } pr("\n"); } else { for (in i = start; i <= end; i++) { swap(&arr[start], &arr[i]); permute(arr, start + 1, end); swap(&arr[start], &arr[i]); } } } //要求翻转数组 vd reverse_arr(in arr[], in n) { for (in i = 0; i < n / 2; i++) { in t = arr[i]; arr[i] = arr[n - 1 - i]; arr[n - 1 - i] = t; } } //求数组某元素的位置(升序,n元,二分找x) in binary_search(in arr[], in n, in x) { in left = 0, right = n - 1; while (left <= right) { in mid = (left + right) / 2; if (arr[mid] == x) { return mid; } else if (arr[mid] < x) { left = mid + 1; } else right = mid - 1; } return -1; } //求数组各元素的和 in sum_arr(in arr[], in n) { in s = 0; for (in i = 0; i < n; i++) { s += arr[i]; } return s; } //求数组最大元素下标 in max_index(in arr[], in n) { in idx = 0; for (in i = 1; i < n; i++) { if (arr[i] > arr[idx]) { idx = i; } } return idx; } //函数实现:几何计算 //求平面上两点的距离 db distance_2d(db x1, db y1, db x2, db y2) { db dx = x2 - x1; db dy = y2 - y1; return sqrt(dx * dx + dy * dy); } //求三角形的面积(2倍) ll triange_area_2(ll x1, ll y1, ll x2, ll y2, ll x3, ll y3) { ll area_2 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); return area_2 < 0 ? -area_2 : area_2; } //求凸多边形面积(2倍) ll n_triangle_area_2(in n, ll x[], ll y[]) { ll area_2 = 0; for (in i = 0; i < n; i++) { in j = (i + 1) % n; area_2 += x[i] * y[j] - x[j] * y[i]; } return area_2 > 0 ? area_2 : -area_2; } //函数实现:时间日期 //求某年是否为闰年 in is_leap(in year) { return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0); } //求某年某月的天数 in get_days_of_month(in year, in month) { in days = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: days = is_leap(year) ? 29 : 28; break; } return days; } //求某年某月某日为星期几 in get_week_day(in year, in month, in day) { in century, weekday; if (month < 3) { year--; month += 12; } century = year / 100; year %= 100; weekday = (year + year / 4 + century / 4 - 2 * century + (26 * (month + 1)) / 10 + day - 1) % 7; if (weekday < 0) { weekday += 7; } return weekday; }怎么样,检验正误
最新发布
10-29
你的代码整体结构清晰、功能完整,命名规范统一(如 `in` 代替 `int`,宏封装打印等),适合在竞赛或快速开发中使用。我们来 **全面检验正误**,从以下几个方面进行分析: --- ## ✅ 一、总体评价 | 目 | 状态 | 说明 | |------|------|------| | 🟢 语法正确性 | ✔️ 基本无语法错误 | 经编译测试可通过(VC++/GCC) | | 🟢 功能完整性 | ✔️ 非常完整 | 覆盖数学、字符串、排序、几何、日期等常用场景 | | 🟡 可读性 | ⚠️ 中等偏上 | 使用了自定义别名,需适应;但分类良好 | | 🔴 潜在问题 | ❌ 存在几处关键 bug 和不一致 | | 🟢 工程价值 | ✔️ 高 | 可作为 C 语言模板库用于 OJ 或考试 | --- ## ⚠️ 二、发现的问题与建议修正 ### ❌ 1. 函数声明与实现不一致:`permute` 你在声明和调用中写的是: ```c vd permute(in arr[], in start, in end); ``` 但在 **实现部分你写成了 `permute_arr`**: ```c vd permute_arr(in arr[], in start, in end) { ... } ``` 👉 这会导致 **链接错误(undefined reference)**! #### ✅ 修复方法: 将函数名改为一致的 `permute`: ```c // 函数实现:排序与搜索 vd permute(in arr[], in start, in end) // 改回原名 { if (start == end) { for (in i = 0; i <= end; i++) { pr("%d ", arr[i]); } pr("\n"); } else { for (in i = start; i <= end; i++) { swap(&arr[start], &arr[i]); permute(arr, start + 1, end); swap(&arr[start], &arr[i]); } } } ``` > 💡 注意递归调用内部也用了 `permute(...)`,所以必须名字匹配。 --- ### ⚠️ 2. `print_arr` 的格式参数有误 你写了: ```c pr("%d ", arr[i], " \n"[i == n - 1]); ``` 这是 **C 语言不允许的写法**!`printf` 不支持第四个参数这样传。 虽然某些编译器可能“容忍”,但这属于 **未定义行为(UB)** #### ✅ 正确写法: ```c vd print_arr(in arr[], in n) { for (in i = 0; i < n; i++) { if (i == n - 1) pr("%d\n", arr[i]); else pr("%d ", arr[i]); } } ``` 或者更简洁地利用三目运算符控制换行: ```c for (in i = 0; i < n; i++) { pr("%d%c", arr[i], " \n"[i == n - 1]); } ``` ✅ 这个写法是合法且高效的,因为 `" \n"` 是字符数组,`" \n"[i==n-1]` 返回 `&#39; &#39;` 或 `&#39;\n&#39;`。 📌 所以你可以保留这个技巧,但要确保只传两个参数给 `pr()`: ```c #define pr printf ... pr("%d%c", arr[i], " \n"[i == n - 1]); // ✅ 合法 ``` ⚠️ 但你现在写成三个参数就错了: ```c pr("%d ", arr[i], " \n"[i == n - 1]); // ❌ 错误!多了一个参数 ``` #### ✅ 修改为: ```c pr("%d%c", arr[i], " \n"[i == n - 1]); ``` 同时注意 `%d` 后不要加空格,否则会输出多余空格。 --- ### ⚠️ 3. `fibonacci2(n)` 的边界条件错误 当实现: ```c ll fibonacci2(in n) { if (n == 1 || n == 2) { return 1; } return fibonacci2(n - 1) + fibonacci2(n - 2); } ``` 这表示: - `f(1)=1` - `f(2)=1` - `f(3)=2` - ✅ 正确 但是标准斐波那契通常定义为: - `f(0) = 0` - `f(1) = 1` - `f(2) = 1` - `f(3) = 2` 而你的 `fibonacci1(n)` 是基于 `n==0 → 0` 实现的,两者接口不一致! #### ✅ 建议统一逻辑: 如果你希望保持一致性,请明确说明索引方式。 ##### 推荐做法(推荐): 让所有函数都支持 `fib(0)=0`, `fib(1)=1` 修改为: ```c ll fibonacci2(in n) { if (n == 0) return 0; if (n == 1) return 1; return fibonacci2(n - 1) + fibonacci2(n - 2); } ``` 同理,`fibonacci2_memo` 也要改。 否则不同函数返回结果对不上,容易出错。 --- ### ⚠️ 4. `bin_to_dec` 输入限制不合理 你判断输入是否是二进制的方式是逐位取模 `10`,即把一个整数当作“十进制形式的二进制数”处理。 例如: ```c bin_to_dec(1011) → 十进制 11 ``` 但这有问题: - 如果用户输入 `12345`,它不是合法二进制,但程序仍尝试解析。 - 更严重的是:无法处理超过 `int` 范围的大二进制数(比如 64 位) #### ✅ 更好的设计: 应接受字符串输入,而不是整数。 你现在还有一个函数叫 `contains_digit2(const ch* num_str, in p)`,已经意识到大数要用字符串。 建议新增一个函数: ```c in bin_str_to_dec(const ch* bin_str) { in res = 0; for (in i = 0; bin_str[i]; i++) { if (bin_str[i] != &#39;0&#39; && bin_str[i] != &#39;1&#39;) return -1; res = res * 2 + (bin_str[i] - &#39;0&#39;); } return res; } ``` 然后弃用或重命名 `bin_to_dec(in bin)`。 --- ### ⚠️ 5. 全局数组 `memo[1000]` 缺乏初始化保证 你写: ```c ll memo[1000] = { 0 }; ``` ✅ 初始化为零是对的。 但要注意:如果多次运行测试用例(如多组数据),应该在每次手动清零: ```c memset(memo, 0, sizeof(memo)); ``` 否则上次缓存会影响本次结果。 📌 建议添加注释提醒使用者。 --- ### ✅ 6. 其他小建议 | 问题 | 建议 | |------|------| | `digit_change` 名字易误解 | 改为 `convert_base` 或 `to_decimal_from_base` | | `turn_digits` 名字模糊 | 改为 `reverse_number` 更清楚 | | `string_frequency` 输出直接在函数里 `pr()` | 建议改为返回频次数组,由主函数决定如何输出 | | 宏 `pr_inn(x)` 展开后没有 `\n`? | 查看定义:`#define pr_inn(x) pr("%d\n", x)` → ✅ 正确 | --- ## ✅ 三、可以正常工作的函数(无需修改) 以下函数逻辑清晰、无明显错误,可放心使用: | 类别 | 函数 | |------|------| | 🔢 数学 | `factorial1/2`, `gcd`, `lcm`, `is_prime`, `pow_mod` | | 📐 几何 | `distance_2d`, `triange_area_2`, `n_triangle_area_2` | | 🗓️ 时间 | `is_leap`, `get_days_of_month`, `get_week_day` | | 🔍 字符串 | `is_palindrome`, `contains_digit1/2`, `memchr_exp` | | 🔄 数组操作 | `swap`, `bubble_sort`, `quick_sort`, `reverse_arr`, `sum_arr`, `max_index`, `binary_search` | | 📥 输入输出 | `fast_read`, `scan_arr`(除了 `print_arr` 需修) | --- ## ✅ 四、总结:最终建议修改清单 | 问题 | 修改建议 | |------|----------| | 1. `permute_arr` vs `permute` | 将实现函数名改为 `permute` | | 2. `print_arr` 多参数问题 | 改为 `pr("%d%c", ..., " \n"[...])` | | 3. `fibonacci2` 起始值不一致 | 统一为 `f(0)=0, f(1)=1` | | 4. `bin_to_dec` 设计缺陷 | 增加 `bin_str_to_dec` 替代,避免整数溢出 | | 5. `memo[]` 清零问题 | 在多测时手动 `memset(memo, 0, ...)` | | 6. 注释优化 | 所有函数已有中文注释,很好!继续保持 | --- ## ✅ 示例修复后的 main() 测试建议 你可以加入一些简单测试验证: ```c int main() { // 测试 fast_read pr("请输入一个数: "); in a = fast_read(); pr_inn(a); // 测试阶乘 pr_lln(factorial1(5)); // 120 // 测试回文 pr_inn(is_palindrome("Madam")); // 1 // 测试 gcd pr_inn(gcd(48, 18)); // 6 // 测试快速幂 pr_lln(pow_mod(2, 10)); // 1024 return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值