对文本行按特定字段排序(前N个字符或后N个字符),TCPL 练习5-17
The C programming language 的关于文本行排序的问题有很多种要求的方式,在对每行的字段排序方面,最简单的是例如对前N个字符或者末位N个字符进行排序,更高一点的要求是,对特殊符号标识的字段排序,例如,对逗号前的字段进行排序等,标识符号要尽可能地自定义,这里的程序实现了前者,即依据命令行参数N,对每行的前N或者后N个字符排序,当然,也实现了和-f(忽略大小写),-d(只对空格数字字母排序),-r(逆序)的组合使用,因此,基本完成了如书上所说,可以进行索引排序。但是哪怕是这一个简单的实现,也需要进一步考虑的问题是:能否对文本行中间N个字符进行排序?某些特殊场合可能会提出这样的要求。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/* 编写文本行排序函数,扩充其功能,使得函数能对特定字段排序,本例实现了对前leng个字符和末位leng个字符的排序,+为指令,还需能和-r,-f,-d等组合使用 */
#define MAXLINES 5000 /* 待排序的最大行数 */
char *lineptr[MAXLINES]; /* 指向问本行的指针 */ int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
int inpuntcmp(char *, char *); /* 函数inpuntcmp:将忽略除空格字母数字以外的字符比较,如果某行以上三种字符都没有,则判断为最小 */ char *alloc(int n);
void sort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int numcmp(char *, char *);
int transfercmp(char *s1, char *s2); /* 函数transfercmp:忽略大小写的按字典比较的函数,例如,认为a=A,和numcmp以及strcmp并列的选项 */
int newstrcmp(char *s1, char *s2); /* 重新编函数newstrcmp: 实现对特定字段的一般字符比较,替代原来的strcmp */
static char allocbuf[];
static char *allocp=allocbuf;
int post=,uptolow=,leng=; /* post 为1则逆序排序;uptolow为1,忽略大小写,leng为字段分隔数,如为正,则对前leng个字符排序,为负,对末位leng个字符排序 */ main(int argc, char *argv[])
{
int nlines; /* 读入的输入行数 */
int numeric=,nw=; /* numeric为1则以数值排序 uptolow为1则转换大小写 */ while(argc-->){
if(strcmp(*++argv,"-n")==)
numeric=;
else if(strcmp(*argv,"-r")==)
post=;
else if(strcmp(*argv,"-f")==)
uptolow=;
else if(strcmp(*argv,"-d")==)
nw=; /* nw为1只对字母数字空格排序 */
else if(**argv=='+') { switch ((*++(*argv))-''>= && (**argv)-''<=) {
case :
if(leng==) (int)leng=atof(*argv);
else
printf("error: leng was defined\n");
break;
case :
if(**argv=='-'&&(*++(*argv))-''>= && (**argv)-''<=&& leng==)
(int)leng=atof(--(*argv)); else
printf("error: leng was defined or unknow command after '-'");
break;
default :
printf("error: please enter number after the '+'\n");
} } else printf("error: unkonwn command\n");
}
if((nlines=readlines(lineptr,MAXLINES))>=) {
if(nw==){
sort((void **)lineptr, post?(nlines-):, post?:(nlines-), (int (*)(void*,void*))(inpuntcmp));
writelines(lineptr,nlines);
return ;
} else {
if(uptolow==)
sort((void **)lineptr, post?(nlines-):, post?:(nlines-), (int (*)(void*,void*))(numeric?numcmp:newstrcmp));
else
sort((void **)lineptr, post?(nlines-):, post?:(nlines-), (int (*)(void*,void*))(numeric?numcmp:transfercmp)); writelines(lineptr,nlines);
return ;
}
}
else {
printf("input too big to sort\n");
return ;
} } void sort(void *v[], int left, int right, int (*comp)(void *, void *))
{
if(post==) {
int i, last;
void swap(void *v[], int, int); if(left>=right)
return;
swap(v,left,(left+right)/);
last =left;
for(i=left+;i<=right;i++)
if((*comp)(v[i],v[left])<)
swap(v,++last,i);
swap(v,left,last);
sort(v,left,last-,comp);
sort(v,last+,right,comp);
} else
{
int i, last;
void swap(void *v[], int, int); if(left<=right)
return;
swap(v,left,(left+right)/);
last =left;
for(i=left-;i>=right;i--)
if((*comp)(v[i],v[left])<)
swap(v,--last,i);
swap(v,left,last);
sort(v,left,last+,comp);
sort(v,last-,right,comp);
}
} int length(char *s);
int numcmp(char *s1,char *s2)
{
double v1,v2;
v1=atof(s1);
v2=atof(s2);
if(v1<v2)
return -;
else if (v1>v2)
return ;
else
return ; } void swap(void *v[], int i, int j) {
void *temp; temp =v[i];
v[i]=v[j];
v[j]=temp; }
#define MAXLEN 1000
int getline(char *, int);
int readlines(char *lineptr[], int maxlines) {
int len,nlines;
char *p,line[MAXLEN];
nlines =;
while((len=getline(line,MAXLEN))>)
if (nlines>= maxlines || (p=alloc(len))==)
return -;
else {
line[len-]=;
strcpy(p,line);
lineptr[nlines++]=p;
}
return nlines;
} void writelines(char *lineptr[], int nlines)
{
int i; for(i=; i< nlines; i++)
printf("%s\n",lineptr[i]);
}
int getline(char *s, int lim) {
int i=,c;
for(; i<lim && (c=getchar()) != EOF && c!='\n';++i)
*(s+i)=c;
if(c=='\n') {
*(s+i)=c;
++i;}
*(s+i)=;
return i; }
char *alloc(int n) {
if(allocbuf +-allocp>=n) {
allocp +=n;
return allocp - n;
} else
return ;
} int inpuntcmp(char *s1, char *s2)
{
char c,d,leng2;
int i=,k,len1=,len2=;
if(leng>=) {
while(*s1 != && *s2!= &&leng?(i<leng):) {
while(ispunct(*s1)) {
if(*s1==||len1>=leng)
return -;
++len1;
++s1;
}
while(ispunct(*s2)) {
if(*s2==||len2>=leng)
return ;
++s2;
++len2;
}
if(uptolow==) {
c=tolower(*s1);
d=tolower(*s2);
}
else {
c=*s1;
d=*s2;
}
if(c<d)
return -;
else if (c>d)
return ;
++s1;
++s2;
++len1;
++len2; }
if(len1>=leng && len2<leng)
return -;
if(len2>=leng && len1<leng)
return ;
if(len1>=leng && len2>=leng)
return ;
if(*s1<*s2)
return -;
else if (*s1>*s2)
return ;
else
return ;
} else {
leng2=-leng;
len1=length(s1);
len2=length(s2);
i=((len1-leng2)>)?(len1-leng2):;
k=((len2-leng2)>)?(len2-leng2):; while(s1[i] != && s2[k] !=) {
while(ispunct(s1[i])) {
if(s1[i]==)
return -;
++i; }
while(ispunct(s2[k])) {
if(s2[k]==)
return ;
++k;
}
if(uptolow==) {
c=tolower(s1[i]);
d=tolower(s2[k]);
}
else {
c=s1[i];
d=s2[k];
}
if(c<d)
return -;
else if (c>d)
return ;
++i;
++k; } if(s1[i]<s2[k])
return -;
else if (s1[i]>s2[k])
return ;
else
return ; } }
int transfercmp(char *s1, char *s2)
{
char c,d,leng2;
int i=,k,len1,len2;
if(leng>=) {
while(*s1 != && *s2!= && leng?(i<leng): ) {
c=tolower(*s1);
d=tolower(*s2);
if(c<d)
return -;
else if (c>d)
return ;
++s1;
++s2;
++i; }
if(i<leng) {
if(*s1<*s2)
return -;
else if (*s1>*s2)
return ;
else
return ;
} else
return ;
} else
{
leng2=-leng;
len1=length(s1);
len2=length(s2);
i=((len1-leng2)>)?(len1-leng2):;
k=((len2-leng2)>)?(len2-leng2):;
while(s1[i] != && s2[k] != ) {
c=tolower(s1[i]);
d=tolower(s2[k]);
if(c<d)
return -;
else if (c>d)
return ;
++i;
++k; }
if(s1[i]<s2[k])
return -;
else if (s1[i]>s2[k])
return ;
else
return ; } }
int newstrcmp(char *s1, char *s2) {
char c,d,leng2;
int i=,k,len1,len2;
if(leng>=) {
while(*s1 != && *s2!= && leng?(i<leng): ) {
c=*s1;
d=*s2;
if(c<d)
return -;
else if (c>d)
return ;
++s1;
++s2;
++i; }
if(i<leng) {
if(*s1<*s2)
return -;
else if (*s1>*s2)
return ;
else
return ;
} else
return ;
} else
{
leng2=-leng;
len1=length(s1);
len2=length(s2);
i=((len1-leng2)>)?(len1-leng2):;
k=((len2-leng2)>)?(len2-leng2):; while(s1[i] != && s2[k] != ) {
c=s1[i];
d=s2[k]; if(c<d)
return -;
else if (c>d)
return ;
++i;
++k; }
if(s1[i]<s2[k])
return -;
else if (s1[i]>s2[k])
return ;
else
return ; } }
int length(char *s) {
int i;
for(i=;*s++!=;++i)
;
return i;
}
对文本行按特定字段排序(前N个字符或后N个字符),TCPL 练习5-17的更多相关文章
- mongodb 通过嵌入文档中的字段排序
mongodb中的全部数据: db.testInfo.find({}) .sort({_id:-1}) .limit(100) 查询结果: /* 1 createdAt:2019/10/11 下午5: ...
- C#中List按特定字段排序
有一个类,如Student,有学号.数学成绩.语文成绩, 存在List列表中,要将List按数学成绩排序,怎么办呢? List<Student> scores=GetScores(); s ...
- C# List<object> 按特定字段排序
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...
- List多字段排序,orderBy,ThenBy
List排序问题,orderBy,ThenBy 1.List中一个字段排序 前几天做的项目中,获取的List<T>需要用某个字段来进行排序,困扰了很久.用OrderBy解决了.具体是这样的 ...
- 对文本行进行排序,新增-d(目录排序),只对字母数字空格排序(TCPL 练习5-16)
文本行的排序用到了命令行参数以及多级指针,在要求只对字母数字空格进行排序时,关键的问题点是兼容-f命令参数,也就是排序的同时忽略大小写.由于在之前的练习中,我将忽略大小写的比较方法重新写了一个函数tr ...
- SQL 按特定字段值排序
SQL 按特定字段值排序的代码,有需要的朋友可以参考下. id, name shandong01 name1 shandong02 name2 shandong03 name3 beijing01 n ...
- MySql 去重且指定某字段在前的排序方法
今天遇到一个棘手的数据查找并去重的问题: 情况: 1.取出数据库中的数据: 2.同一字段A,不同情况<值,如A值为:a1,a2>下取出的其他数据可能相同: 3.将2情况下的重复数据< ...
- mysql 字段指定值靠前排序方法,多字段排序排序方法
背景:SEO下选择某查询条件 查询展示信息为装修设计师以及设计师作品.设计师原型设计为:选择某风格 例如:简约,则列表出现拥有简约风格的设计师信息以及该设计师类型为简约的作品(3条靠前记录) 浏览原型 ...
- 读取txt文件将文本行组合成特定格式
有一网友要求从txt文本文件读取一些数据,然后组合为特定格式的数据行.原论题如下,刚才开始的要求描述得不太清楚,后来补充完整了. Insus.NET觉得本论题可有练习文本件读取功力,因此尝试实现一下. ...
随机推荐
- C#ActiveX控件开发学习
一:C#ActiveX控件开发注意事项 1:C#开发的ActiveX控件只可在装有Framework的系统上才能用. 2:只有IE浏览器支持. 3:初次安装需要导入代码签名证书及其证书链的方式, ...
- UITextField常用属性归纳:文本框样式、文字样式、键盘样式、左右视图样式、清除按钮设置等
(1)可以根据需要设置文本框的样式(包括形状.边框颜色.背景等). (2)可以根据需要设置文字显示样式(包括输入密码时的密文显示.文字横向居中.纵向居中上下.输入的文字是否首席木大写.文字超过后是否缩 ...
- sql server 执行计划(execution plan)介绍
大纲:目的介绍sql server 中执行计划的大致使用,当遇到查询性能瓶颈时,可以发挥用处,而且带有比较详细的学习文档和计划,阅读者可以按照我计划进行,从而达到对执行计划一个比较系统的学习. 什么是 ...
- docke部署mysql
#1 docker pull mysql #2 docker run -v /data/var/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=k ...
- hash 表 | | jzoj 1335 | | 脑残+手残 | | 集合的关系
给定两个集合A.B,集合内的任一元素x满足1 ≤ x ≤ 10^9,并且每个集合的元素个数不大于10^5.我们希望求出A.B之间的关系. 给定两个集合的描述,判断它们满足下列关系的哪一种:A是B的一个 ...
- Android安全之Https中间人攻击漏洞
Android安全之Https中间人攻击漏洞 0X01 概述 HTTPS,是一种网络安全传输协议,利用SSL/TLS来对数据包进行加密,以提供对网络服务器的身份认证,保护交换数据的隐私与完整性. ...
- iis 500.19错误解决过程记录
前段时间一直在纠结C#中,dll的管理问题.最后选择使用nugetgallery进行公共库管理.项目地址:https://github.com/NuGet/NuGetGallery.这是一个nuget ...
- Git入门仅这篇就够了
版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/5978937.html 前言 大家好,我是Cavalier ...
- HDU2471_History of Languages
有意思的题目,给出两个自动机,判断这个两个自动机是否是等价的? 两个自动机是等价的,那么他们可接受的字符串集合一定是完全一样的. 于是我们可以从(0,0)开始bfs,每次看看在两个自动机上走到的两个点 ...
- hdoj 1002 A+B(2)
Problem Description I have a very simple problem for you. Given two integers A and B, your job is to ...