news 2026/6/26 8:24:04

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 8:19:48

在职考公每天只有 1 小时,粉笔线上课和题库怎么用

每天只有 1 小时&#xff0c;还能准备公务员考试吗&#xff1f; 能&#xff0c;但不能按全职备考的方式来。全职备考可以上午听课、下午刷题、晚上复盘&#xff1b;在职考生如果也照搬这种计划&#xff0c;很容易坚持三天就断掉。工作日下班后已经很累&#xff0c;真正能安静学…

作者头像 李华
网站建设 2026/6/26 8:18:37

用TRAE软件跑出来的白银临界点的结论

下面是TRAE根据模态信息论跑出的白银临界点的结论。还是波普尔说得对&#xff1a;"科学理论的价值不在于它的推导是否精美&#xff0c;而在于它能否做出可验证的预测。" 有了这个图&#xff0c;说明面上的的工作已经完成了三分之一&#xff0c;下面就是按部就班把书写…

作者头像 李华
网站建设 2026/6/26 8:18:06

Android加固逆向实战:从梆梆、乐固到聚安全的深度分析与对抗

1. 项目概述&#xff1a;一次深入Android加固腹地的逆向之旅 在移动应用安全领域&#xff0c;Android加固技术就像一道不断升级的“防盗门”&#xff0c;而逆向分析则是试图在不破坏门锁结构的前提下&#xff0c;找到开锁方法的过程。我最近花了相当长一段时间&#xff0c;集中…

作者头像 李华
网站建设 2026/6/26 8:17:30

全域轨迹精准溯源 跨镜无缝追踪夯实司法监管规范化建设——智能行为研判·无缝跨镜续迹监所安全闭环治理技术白皮书

一、前言司法监所是法治建设的关键阵地&#xff0c;监管规范化、流程标准化、治理法治化、溯源制度化是新时代智慧监所建设的核心硬性要求。当前传统监所安防治理模式普遍存在监管碎片化、追踪断点化、研判人工化、溯源形式化的短板&#xff0c;过度依赖人工值守、人工巡查、人…

作者头像 李华