当前位置: 首页 > news >正文

C风格字符串排序全解析【模板练习题】

void sort(char data[][M], int n) { for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n - 1 - i; ++j) { if (strcmp(data[j], data[j + 1]) > 0) { char temp[M]; strcpy(temp, data[j]); strcpy(data[j], data[j + 1]); strcpy(data[j + 1], temp); } } } }

二维字符数组(C 风格字符串数组)作为函数参数的标准写法

  • 第一维(行数 / 字符串个数)可以省略:数组传参会退化为指针,编译器不需要提前知道总共有多少行;
  • 第二维(每行的长度 / 单个字符串最大长度)必须明确写死:编译器需要靠这个长度计算内存地址,才能正确定位到每一行的起始位置。

因此:

  • char data[][M]char (*data)[M](数组指针)是完全等价的
  • 含义是:data指向一组字符数组,每个字符数组的固定长度为M
  • 这里的M是代码开头的宏定义#define M 30,表示每个字符串最多存 30 个字符(含末尾的结束符\0
  • 这个参数专门对应题目里type == 4的场景:

    每一行data[j]就是一个完整的 C 风格字符串(比如"abc""bca")整个二维数组就是一个 “字符串列表”,总共有n个字符串这个sort函数的作用,就是把这 n 个字符串按字典序从小到大排序

原因在于C 字符串不能直接用>比较大小

  • 对于intdoublechar来说,arr[j] > arr[j+1]比较的是数值大小,逻辑正确;
  • 但对于 C 字符串(本质是char*指针)来说,直接用>比较的是字符串在内存中的地址大小,不是字典序,排序结果完全错误。

所以必须单独写这个重载版本,用 C 标准库函数做字符串专属操作:

  • 比较用strcmpstrcmp(data[j], data[j+1]) > 0表示前一个字符串字典序更大,需要交换,符合从小到大排序的逻辑。
  • 交换用strcpy:C 字符串不能直接用=赋值(只会拷贝指针地址,不会拷贝内容),必须通过strcpy逐个字符拷贝完成交换。

cpp里面两种字典序的实现

C风格字符串char[]/char*必须用strcmp(s1,s2)函数
C++string 类必须用> < == 运算符即可,内部自动按字典序比较

strcmp

返回<0 s1<s2;

>0 s1>s2;

=0 s1=s2;

不用C风格的字符串,用的是string的封装,已经封装好了,比较的时候自动比较的就是字典序的大小,就使用通用的排序模板sort即可。

#include <iostream> #include <string> #include <fstream> using namespace std; // 通用输入模板 template <class T> void input(T arr[], int n, ifstream& in) { for (int i = 0; i < n; ++i) in >> arr[i]; } // 通用冒泡排序模板 template <class T> void sort(T arr[], int n) { for (int i = 0; i < n - 1; ++i) for (int j = 0; j < n - 1 - i; ++j) if (arr[j] > arr[j + 1]) swap(arr[j], arr[j + 1]); // 可以直接用std::swap简化交换代码 } // 通用输出模板 template <class T> void output(T arr[], int n, ofstream& out) { for (int i = 0; i < n; ++i) { if (i != 0) out << " "; out << arr[i]; } out << endl; } int main() { ifstream in("input.txt"); ofstream out("output.txt"); int type, n; while(in >> type && type) { if(type == 1) { in >> n; int *data = new int[n]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } else if(type == 2) { in >> n; char *data = new char[n]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } else if(type == 3) { in >> n; double *data = new double[n]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } else if(type == 4) { in >> n; string *data = new string[n]; // 改用string数组 input(data, n, in); sort(data, n); // string自带字典序比较,直接走通用模板 output(data, n, out); delete []data; } } in.close(); out.close(); return 0; }

原题目有框架要求,故代码如下:

#include <iostream> #include <string> #include <fstream> #include <cstring> using namespace std; #define M 30 // 字符串串长小于30 // 补齐排序、输入、输出函数模版等 template <class T> void input(T arr[], int n, ifstream& in) { for (int i = 0; i < n; ++i) { in >> arr[i]; } } template <class T> void sort(T arr[], int n) { for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n - 1 - i; ++j) { if (arr[j] > arr[j + 1]) { T temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } template <class T> void output(T arr[], int n, ofstream& out) { for (int i = 0; i < n; ++i) { if (i != 0) out << " "; out << arr[i]; } out << endl; } void sort(char data[][M], int n) { for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n - 1 - i; ++j) { if (strcmp(data[j], data[j + 1]) > 0) { char temp[M]; strcpy(temp, data[j]); strcpy(data[j], data[j + 1]); strcpy(data[j + 1], temp); } } } } int main() { // 补齐文件操作 ifstream in("input.txt"); ofstream out("output.txt"); int type, n; while(in >> type && type) { if(type == 1) // 整数类型 { in >> n; int *data = new int[n]; input(data, n, in); // in文件流输入n个数据 sort(data, n); // 排序 output(data, n, out); // 输出n个数据到out文件流 delete []data; } else if(type == 2) // 字符类型 { in >> n; char *data = new char[n]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } else if(type == 3) // 浮点数类型 { in >> n; double *data = new double[n]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } else if(type == 4) // C字符串类型 { in >> n; char (*data)[M] = new char[n][M]; input(data, n, in); sort(data, n); output(data, n, out); delete []data; } } in.close(); out.close(); return 0; }
http://www.jsqmd.com/news/1080249/

相关文章:

  • 在职考公每天只有 1 小时,粉笔线上课和题库怎么用
  • VMware安装MySQL后无法远程访问?3分钟定位网络配置、端口映射、bind-address三重陷阱
  • AI 应用日志与监控系统构建实战
  • 电商作图工具有哪些?支持AI抠图、主图生成和详情页设计
  • Outfit字体终极指南:9种字重的专业级开源几何无衬线字体如何重塑现代品牌视觉系统
  • 2026年AI大模型API代理网站全维度深度测评:主流服务商性能与成本全场景权威排名指南
  • 计算机毕业设计之jsp基于SSM的热点个性化推荐新闻
  • 华硕笔记本性能调优与显示优化:G-Helper深度解析
  • 凸优化加速算法:精度证书与复杂度分析,实现稳且快的模型训练
  • Cookie 还在,为什么登录态还是异常?
  • IntelliJ IDEA安装失败?97%的报错都源于这5个隐藏配置——资深JetBrains认证讲师逐行调试实录
  • 百度网盘直链解析技术深度解析:绕过限速的架构实现与实战指南
  • 第 14 篇:robots.txt 协议 —— 尊重站长的规则
  • 从零基础启航SEO之旅,全面提升网站流量与排名的实用指南
  • 现代 C++ 协程如何优雅降维打击局域网 UDP 爆仓事故
  • 深度解析:Obsidian Excel表格转换插件的技术架构与实现机制
  • 非线性薛定谔方程中异常波的大偏差原理:从随机初值到极端事件预测
  • 2026年,这家现货当天发的新吨袋供应商,究竟有何独特魅力?
  • 全域轨迹精准溯源 跨镜无缝追踪夯实司法监管规范化建设——智能行为研判·无缝跨镜续迹监所安全闭环治理技术白皮书
  • 安卓7.0+模拟器HTTPS抓包:Burp证书系统级安装与Mumu配置实战
  • Input Leap:一套键盘鼠标控制多台电脑的终极开源方案
  • 门店别只靠探店
  • 餐饮神秘顾客到底做什么?一文说清
  • VMware Web服务器安全加固清单:27项CIS基准配置+自动检测脚本,漏配1项即成攻击入口
  • 3分钟部署智慧树自动刷课插件:告别重复点击,提升300%学习效率
  • 如何用DLSS Swapper轻松管理游戏DLSS版本:3个简单步骤提升游戏性能
  • RePKG终极指南:三步解锁Wallpaper Engine PKG文件与TEX格式转换
  • 手机应用界面范式变迁观察
  • 2026国内数字孪生头部企业排名:从平台能力、工业仿真到物理AI趋势
  • 从数据分析到长期研究,解析中吉安策多因子模型