コマンドラインパラメータによる入力のソート
由来于《The C Programming Language》P 102 ex 5.11およびその後のpr 5-14...pr 5-14、コードはpr 5-16を参照:
コード:
分析:
1、設計プロセス:
(a)変数optionによってコマンドライン内のすべてのコマンドを収集し、以下のソートで使用する.
(b)関数readLinesによって入力中のすべての行を格納する.
(c)関数myQsortによってすべての入力をコマンドラインパラメータに従ってソートする.
(d)関数writeLinesによるソート後の入力印刷出力;
2、optionの値を取得する場合、上記コードのwhile switch-case文の組み合わせを用いることは、if-else文を用いるよりも可読性および拡張性に優れ、
while switch-caseバージョン:
if-elseバージョン:
3,入力文字列の関数readLinesを取得する:p=alloc(len)を通じてlenの長さの文字列に相応の空間を割り当て、strcpy(p,line)を通じて;およびlineptr[nlines++]=p;関数#カンスウ#
ローカル変数line文字配列からpが指す空間に文字列をコピーし、ポインタlineptr[nlines]をこの文字列に向けます.
関数alloc:この関数はカスタムダイナミックメモリ割り当て関数で、簡単で、分かりやすく、実行可能です(もちろん入力量が特に大きい場合を除きます).
コード:
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000 /* */
#define NUMERIC 1
#define DECR 2
#define IGNORE 4
#define DIR 8
//char* lineptr[MAXLINES]; /* */
static int option = 0;
int readLines(char* lineptr[], int maxlines);
void writeLines(char* lineptr[], int nlines, int order);
void myQsort(void* lineptr[], int left, int right,
int (*comp) (void*, void* ), int option);
int numcmp(char*, char* );
int charcmp(char*, char* );
typedef int (*PFUNC) (void*, void*);
int main(int argc, char* argv[])
{
int nlines;
//int option;
int c;
char* lineptr[MAXLINES];
PFUNC pFunc;
nlines = 0;
//option = 0;
/* while switch , if , */
while(--argc > 0 && **(++argv) == '-') /* , */
while(c = *++(*argv))
switch(c)
{
case 'n':
option |= NUMERIC;
break;
case 'r':
option |= DECR;
break;
case 'f':
option |= IGNORE;
break;
case 'd':
option |= DIR;
break;
default:
printf("error: illegal command parameters !
");
return -1;
}
if(argc)
printf("Usage: sort -dfnr
");
else if((nlines = readLines(lineptr, MAXLINES)) > 0)
{
if(nlines <= MAXLINES) /* */
{
if(option & NUMERIC)
pFunc = numcmp;
else
pFunc = charcmp;
myQsort((void** )lineptr, 0, nlines-1, pFunc, option);
writeLines(lineptr, nlines, option & DECR);
return 0;
}
else
{
printf("error: the lines overflow the MAXLINES
");
return -1;
}
}
else
{
printf("error: fail to get the lines of input
");
return -1;
}
}
#define MAXLEN 1000 /* */
int getLine(char* line, int maxlen);
char* alloc(int);
/*readLines : */
int readLines(char* lineptr[], int maxlines)
{
int len;
int nlines;
char* p;
char line[MAXLEN];
nlines = 0;
p = NULL;
while((len = getLine(line, MAXLEN)) > 0)
if(nlines >= MAXLINES || !(p = alloc(len)))
return -1;
else
{
line[len-1] = '\0';
strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
/*writeLines : */
void writeLines(char* lineptr[], int nlines, int order)
{
int i;
int j;
i = 0;
j = nlines - 1;
if(order)
while(i++ <= nlines - 1)
printf("%s
", lineptr[j--]);
else
while(nlines-- > 0)
printf("%s
", lineptr[i++]);
}
/*getLine: */
int getLine(char* line, int maxlen)
{
int i;
int c;
for(i = 0; i < maxlen-1 && (c = getchar()) != EOF && c != '
'; ++i)
line[i] = c;
if(c == '
')
line[i++] = c;
line[i] = '\0';
return i;
}
/*myQsort : , lineptr[left]...lineptr[right]
comp , , */
void myQsort(void* lineptr[], int left, int right,
int (*comp) (void*, void*), int option)
{
int last;
int i;
void swap(void* v[], int i, int j);
if(left >= right) /* 2, */
return;
swap(lineptr, left, (left + right) / 2);
last = left;
for(i = left+1; i <= right; ++i)
if(!(option & DECR))
{
if((*comp)(lineptr[i], lineptr[left]) < 0)
swap(lineptr, ++last, i);
}
else
if((*comp)(lineptr[i], lineptr[left]) > 0)
swap(lineptr, ++last, i);
swap(lineptr, left, last);
myQsort(lineptr, left, last - 1, comp, option);
myQsort(lineptr, last + 1, right, comp, option);
}
/*swap : */
void swap(void* v[], int i, int j)
{
void* tmp;
tmp = v[i];
v[i] = v[j];
v[j] = tmp;
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
int numcmp(char* s1, char* s2)
{
double v1;
double v2;
v1 = atof(s1);
v2 = atof(s2);
if(v1 < v2)
return -1;
else if(v1 > v2)
return 1;
else
return 0;
}
/*charcmp: */
int charcmp(char*s ,char* t)
{
char a;
char b;
int ignore;
int dir;
ignore = (option & IGNORE) ? 1 : 0;
dir = (option & DIR) ? 1 : 0;
do
{
if(dir)
{
while(!isalnum(*s) && *s != ' ' && *s != '\0')
++s;
while(!isalnum(*t) && *t != ' ' && *t != '\0')
++t;
}
a = ignore ? tolower(*s) : *s;
++s;
b = ignore ? tolower(*t) : *t;
++t;
if(a == b && a == '\0') /*a == '\0': ?*/
return 0;
}while(a == b);
return a - b;
}
#define ALLOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char* allocp = allocbuf;
/*alloc : n */
char* alloc(int n)
{
if(allocbuf + ALLOCSIZE - allocp >= n)
{
allocp += n;
return allocp - n;
}
else
return 0;
}
分析:
1、設計プロセス:
(a)変数optionによってコマンドライン内のすべてのコマンドを収集し、以下のソートで使用する.
(b)関数readLinesによって入力中のすべての行を格納する.
(c)関数myQsortによってすべての入力をコマンドラインパラメータに従ってソートする.
(d)関数writeLinesによるソート後の入力印刷出力;
2、optionの値を取得する場合、上記コードのwhile switch-case文の組み合わせを用いることは、if-else文を用いるよりも可読性および拡張性に優れ、
while switch-caseバージョン:
while(--argc > 0 && **(++argv) == '-') /* , */
while(c = *++(*argv))
switch(c)
{
case 'n':
option |= NUMERIC;
break;
case 'r':
option |= DECR;
break;
case 'f':
option |= IGNORE;
break;
case 'd':
option |= DIR;
break;
default:
printf("error: illegal command parameters !
");
return -1;
}
if-elseバージョン:
if(argc == 2 && strcmp(*(argv+1), "-n") == 0)
numeric = 1;
if(argc == 2 && strcmp(*(argv+1), "-r") == 0)
direction = NEGETIVE;
if(argc == 2 && (strcmp(*(argv+1), "-rn") == 0 || strcmp(*(argv+1), "-nr") == 0))
{
numeric = 1;
direction = NEGETIVE;
}
if(argc == 3 && ((strcmp(*(argv+1), "-n") == 0 && strcmp(*(argv+2), "-r") == 0) ||
(strcmp(*(argv+1), "-r") == 0 && strcmp(*(argv+2), "-n") == 0) ) )
{
numeric = 1;
direction = NEGETIVE;
}
3,入力文字列の関数readLinesを取得する:p=alloc(len)を通じてlenの長さの文字列に相応の空間を割り当て、strcpy(p,line)を通じて;およびlineptr[nlines++]=p;関数#カンスウ#
ローカル変数line文字配列からpが指す空間に文字列をコピーし、ポインタlineptr[nlines]をこの文字列に向けます.
関数alloc:この関数はカスタムダイナミックメモリ割り当て関数で、簡単で、分かりやすく、実行可能です(もちろん入力量が特に大きい場合を除きます).