inline;strlen&sizeof

inline:

C++关键字,在函数声明或定义中函数返回类型前加上关键字inline,即可以把函数指定为内联函数。关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。inline是一种"用于实现的关键字",而不是一种"用于声明的关键字"。一般的,用户可以阅读函数的声明,但是看不到函数的定义。

C&C++inline关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中表达式形式的宏定义

表达式形式的宏定义一例:

#define ExpressionName(Var1,Var2) ((Var1)+(Var2))*((Var1)-(Var2))

 C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现(因为无法将this指针放在合适的位置)inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了宏定义的缺点,同时又很好地继承了宏定义的优点。

Strlen&sizeof:

strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')

sizeof是运算符,可用于任何变量名、类型名或常量值,当用于变量名(不是数组)或常量时,它不需要用圆括号。它在编译时起作用,而不是运行时。

二者区别

⒈sizeof操作符的结果类型是size_t,它在头文件中typedefunsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。

⒉sizeof是取字节运算符(关键字)strlen是函数。

⒊sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。sizeof还可以用函数做参数,比如:

short f();

printf("%d\n",sizeof(f()));

输出的结果是sizeof(short),即2

数组做sizeof的参数不退化,传递给strlen就退化为指针了。

大部分编译程序 在编译的时候就把sizeof计算过了是类型或是变量的长度。这就是sizeof(x)可以用来定义数组维数的原因

char str[20]="0123456789";

long a=strlen(str); //a=10;

int b=sizeof(str); //b=20;

6.strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小。

7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸

#include <stdio.h> #include <stdlib.h> #include <string.h> // 打印作者信息 void printAuthor() { printf("张三的最长公共子序列程序\n\n"); } // 返回两个数中的较大值 int max(int a, int b) { return (a > b) ? a : b; } // 打印DP表(调试用) void printDPTable(int** L, int m, int n, char* X, char* Y) { printf("DP表:\n Ø "); for (int j = 0; j < n; j++) printf("%c ", Y[j]); printf("\n"); for (int i = 0; i <= m; i++) { if (i == 0) printf("Ø "); else printf("%c ", X[i-1]); for (int j = 0; j <= n; j++) { printf("%d ", L[i][j]); } printf("\n"); } printf("\n"); } // 递归回溯所有LCS void backtrackAllLCS(char* X, char* Y, int i, int j, int** L, char* lcs, int index) { if (i == 0 || j == 0) { // 找到一个完整LCS,输出 printf("%s\n", lcs); return; } if (X[i-1] == Y[j-1]) { // 当前字符属于LCS lcs[index] = X[i-1]; backtrackAllLCS(X, Y, i-1, j-1, L, lcs, index-1); } else { if (L[i-1][j] > L[i][j-1]) { // 向上回溯 backtrackAllLCS(X, Y, i-1, j, L, lcs, index); } else if (L[i][j-1] > L[i-1][j]) { // 向左回溯 backtrackAllLCS(X, Y, i, j-1, L, lcs, index); } else { // 两个方向都需要回溯(存在多个LCS) backtrackAllLCS(X, Y, i-1, j, L, lcs, index); backtrackAllLCS(X, Y, i, j-1, L, lcs, index); } } } // 查找并打印所有LCS void findAllLCS(char* X, char* Y) { int m = strlen(X); int n = strlen(Y); // 创建DP表 int** L = (int**)malloc((m+1) * sizeof(int*)); for (int i = 0; i <= m; i++) { L[i] = (int*)malloc((n+1) * sizeof(int)); } // 初始化DP表 for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0 || j == 0) { L[i][j] = 0; // 边界条件 } else if (X[i-1] == Y[j-1]) { L[i][j] = L[i-1][j-1] + 1; // 字符匹配 } else { L[i][j] = max(L[i-1][j], L[i][j-1]); // 字符不匹配 } } } // 打印DP表(可选) // printDPTable(L, m, n, X, Y); // LCS长度 int lcsLength = L[m][n]; printf("序列X: %s\n序列Y: %s\n", X, Y); printf("LCS长度: %d\n", lcsLength); if (lcsLength > 0) { // 准备存储LCS的数组 char* lcs = (char*)malloc((lcsLength + 1) * sizeof(char)); lcs[lcsLength] = '\0'; // 字符串结束符 printf("所有LCS:\n"); backtrackAllLCS(X, Y, m, n, L, lcs, lcsLength-1); free(lcs); } else { printf("没有公共子序列\n"); } // 释放DP表内存 for (int i = 0; i <= m; i++) free(L[i]); free(L); } int main() { printAuthor(); // 测试用例1 char X1[] = "ABCBDAB"; char Y1[] = "BDCABA"; printf("测试用例1:\n"); findAllLCS(X1, Y1); // 测试用例2 char X2[] = "ABCDEF"; char Y2[] = "FBDAMN"; printf("\n测试用例2:\n"); findAllLCS(X2, Y2); // 测试用例3(无公共子序列) char X3[] = "ABCD"; char Y3[] = "EFGH"; printf("\n测试用例3:\n"); findAllLCS(X3, Y3); return 0; }优化上述代码使其能运行
最新发布
04-02
好的,以下是对你提供的C语言代码的一些优化建议及改进: --- ### **代码分析** 你当前的代码实现了“查找所有最长公共子序列”(Longest Common Subsequence, LCS)的功能。虽然功能较为完善,但在以下几个方面可以进一步优化和调整: 1. 内存分配的安全性:避免潜在的内存泄漏。 2. 可读性和模块化:将部分复杂逻辑提取成独立函数以便复用。 3. 性能提升:减少不必要的递归操作。 --- ### **优化后的代码** ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 打印作者信息 void printAuthor() { printf("张三的最长公共子序列程序\n\n"); } // 返回两个数中的较大值 inline int max(int a, int b) { return (a > b) ? a : b; } // 动态规划构建LCS表格 int** buildDPTable(const char* X, const char* Y, int m, int n) { // 分配动态规划表空间 int** L = malloc((m + 1) * sizeof(int*)); for (int i = 0; i <= m; ++i) { L[i] = calloc(n + 1, sizeof(int)); // 每行初始化为0 } // 填充动态规划表 for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (X[i - 1] == Y[j - 1]) { L[i][j] = L[i - 1][j - 1] + 1; } else { L[i][j] = max(L[i - 1][j], L[i][j - 1]); } } } return L; } // 释放动态规划表的空间 void freeDPTable(int** L, int rows) { for (int i = 0; i < rows; ++i) { free(L[i]); } free(L); } // 回溯找到所有的LCS,并将其添加到结果列表中 void backtrackAllLCS( const char* X, const char* Y, int** L, int i, int j, char* currentLCS, int index, void (*callback)(const char*) ) { if (i == 0 || j == 0) { // 将当前路径反转后传入回调函数处理 callback(currentLCS); // 调用外部回调函数保存结果 return; } if (X[i - 1] == Y[j - 1]) { // 匹配字符加入当前LCS currentLCS[index--] = X[i - 1]; // 添加匹配的字符 backtrackAllLCS(X, Y, L, i - 1, j - 1, currentLCS, index, callback); } else { if (L[i - 1][j] >= L[i][j - 1]) { backtrackAllLCS(X, Y, L, i - 1, j, currentLCS, index, callback); } if (L[i][j - 1] >= L[i - 1][j]) { backtrackAllLCS(X, Y, L, i, j - 1, currentLCS, index, callback); } } } // 查找并打印所有LCS void findAllLCS(const char* X, const char* Y) { int m = strlen(X), n = strlen(Y); // 构建动态规划表 int** L = buildDPTable(X, Y, m, n); // 输出LCS长度 printf("序列X: %s\n序列Y: %s\n", X, Y); printf("LCS长度: %d\n", L[m][n]); if (L[m][n] > 0) { // 准备缓冲区存储单条LCS char* buffer = malloc((L[m][n] + 1) * sizeof(char)); memset(buffer, 0, L[m][n] + 1); // 定义回调函数用于收集每一条LCS void collectAndPrintLCS(const char* lcs) { printf("%s\n", lcs); } // 开始回溯寻找所有LCS printf("所有LCS:\n"); backtrackAllLCS(X, Y, L, m, n, buffer, L[m][n] - 1, collectAndPrintLCS); free(buffer); } else { printf("没有公共子序列\n"); } // 清理动态规划表资源 freeDPTable(L, m + 1); } int main() { printAuthor(); // 测试用例1 char X1[] = "ABCBDAB"; char Y1[] = "BDCABA"; printf("测试用例1:\n"); findAllLCS(X1, Y1); // 测试用例2 char X2[] = "ABCDEF"; char Y2[] = "FBDAMN"; printf("\n测试用例2:\n"); findAllLCS(X2, Y2); // 测试用例3(无公共子序列) char X3[] = "ABCD"; char Y3[] = "EFGH"; printf("\n测试用例3:\n"); findAllLCS(X3, Y3); return 0; } ``` --- ### **主要改动说明** 1. **`buildDPTable` 和 `freeDPTable`:** - 提取了生成动态规划表的核心逻辑以及清理表内容的过程,增强代码可维护性。 2. **引入回调机制 (`collectAndPrintLCS`):** - 使用回调函数统一管理每次找到的新LCS字符串,方便扩展其他用途(如统计总数、去重等)。 3. **优化内存使用:** - 确保每个分配的内存块都对应地进行了释放,防止泄露。 4. **增加注释提高可读性:** - 对关键步骤增加了必要的解释文字,帮助理解算法流程。 5. **移除冗余判断与循环:** - 避免重复检查最大数值分支的情况,在一定程度提升了性能效率。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值