lolamontes69

K+R Exercise5_17

Sep 25th, 2014
425
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.87 KB | None | 0 0
  1. /* Add a field-searching capability, so sorting may be done on fields within
  2.  * lines, each field sorted according to an independent set of options. (The
  3.  * index for this book was sorted with -df for the index category and -n for
  4.  * the page numbers.)
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #define MAXLINES 5000            /* max #lines to be sorted */
  12. #define MAXLEN 1000
  13. #define ALLOCSIZE 10000          /* size of available space */
  14.  
  15. static char allocbuf[ALLOCSIZE]; /* storage of alloc   */
  16. static char *allocp = allocbuf;  /* next free position */
  17.  
  18. char *lineptr[MAXLINES];         /* pointers to text lines */
  19.  
  20. char *alloc(int n);
  21. int readlines(char *lineptr[], int nlines);
  22. int getline(char *s, int lim);
  23. void writelines(char *lineptr[], int nlines);
  24. /* qsort() renamed because qsort() in stdlib.h */
  25. void qsort1(void *lineptr[], int left, int right,
  26.            int (*comp)(void *, void*));      /* a pointer to a function that returns
  27.                                                 an integer and two pointers as args. */
  28.  
  29. double atodouble(char *s1);
  30. double atodouble1(char *s1);
  31. int numcmp(char *, char *);
  32. int strcmp1(char *s, char *t);               /* renamed because strcmp() in stdlib.h */
  33. void swap(void *v[], int, int);
  34. void errormessage(void);
  35.  
  36. static int numeric = 0;  /* 1 if numeric sort */
  37. static int reverse = 0;  /* 1 if reverse sort */
  38. static int fold = 0;
  39. static int dirorder = 0;
  40. static int search = 0;
  41. static int searchint = 0;
  42.  
  43. /* sort input lines */
  44. main(int argc, char *argv[])
  45. {
  46.     int nlines, c, count=0;       /* number of input lines read */
  47.     while(--argc>0) {
  48.         if((*++argv)[0] == '-') {
  49.             c = *++argv[0];
  50.             while(c = *argv[0]) {
  51.                 switch(c) {
  52.                 case 'n':
  53.                     numeric++;
  54.                     break;
  55.                 case 'r':
  56.                     reverse++;
  57.                     break;
  58.                 case 'f':
  59.                     fold++;
  60.                     break;
  61.                 case 'd':
  62.                     dirorder++;
  63.                     break;
  64.                 case 's':
  65.                     search++;
  66.                     break;
  67.                 default:
  68.                     errormessage();
  69.                     return 0;
  70.                 }
  71.                 c = *++argv[0];
  72.             }
  73.         }
  74.         c = *++argv[0];
  75.         if(isdigit(c)) {
  76.             if(search) {
  77.                 while(isdigit(**argv)) {
  78.                     searchint = (searchint*10)+(**argv-'0');
  79.                     (argv[0]++);
  80.                 }
  81.             }
  82.         }
  83.     }
  84.     if((nlines = readlines(lineptr, MAXLINES)) >= 0) {
  85.         qsort1((void**) lineptr, 0, nlines-1,
  86.           (int (*)(void *,void *))(numeric ? numcmp : strcmp1)); /* pointer to function that returns
  87.                                                                   an integer with two pointers as args */
  88.         writelines(lineptr,nlines);
  89.         return 0;
  90.     }
  91.     else {
  92.         printf("input too big to sort\n");
  93.         return 1;
  94.     }
  95. }
  96.  
  97. /* alloc: return pointer to n characters */
  98. char *alloc(int n)
  99. {
  100.     if(allocbuf + ALLOCSIZE - allocp >= n) {
  101.         allocp += n;
  102.         return allocp - n;
  103.     }
  104.     else return 0;
  105. }
  106.  
  107. /* readline: read input lines */
  108. int readlines(char *lineptr[], int maxlines)
  109. {
  110.     int len, nlines;
  111.     char *p, line[MAXLEN];
  112.  
  113.     nlines = 0;
  114.     while((len=getline(line, MAXLEN))>0)
  115.         if(nlines >= maxlines || (p = alloc(len+1)) == NULL)  /* len+1 to allocate next free */
  116.             return -1;                                        /* space after '\0' */
  117.         else {
  118.             line[len]='\0'; /* delete newline */
  119.             strcpy(p, line);
  120.             lineptr[nlines++] = p;
  121.         }
  122.     return nlines;
  123. }
  124.  
  125. /* getline: get a line of input into an array */
  126. int getline(char *s, int lim)
  127. {
  128.     int c, i;
  129.  
  130.     for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
  131.         s[i]=c;
  132.     s[i]='\0';
  133.     return i;
  134. }
  135.  
  136. /* writelines: write output lines */
  137. void writelines(char *lineptr[], int nlines)
  138. {
  139.     int i;
  140.     puts("---- Sorted words ----");
  141.     while(nlines-- > 0)
  142.         printf("%s\n", *lineptr++);
  143. }
  144.  
  145.  
  146. /* qsort: sort v[left]...v[right] into increasing order */
  147. void qsort1(void *v[], int left, int right,
  148.            int (*comp)(void *, void *))
  149. {
  150.     int i, last;
  151.     if(!reverse) {
  152.         if(left >= right)  /* do nothing if array contains */
  153.             return;        /* fewer than two elements */
  154.         swap(v, left, (left + right)/2);
  155.         last = left;
  156.         for(i=left+1; i<=right; i++)
  157.             if((*comp)(v[i], v[left])<0)    /* pointer to function and args */
  158.                 swap(v, ++last, i);
  159.         swap(v,left,last);
  160.         qsort1(v, left, last-1, comp);
  161.         qsort1(v, last+1, right, comp);
  162.     }
  163.     if(reverse) {
  164.         if(left >= right)  /* do nothing if array contains */
  165.             return;        /* fewer than two elements */
  166.         swap(v, left, (left + right)/2);
  167.         last = left;
  168.         for(i=left+1; i<=right; i++)
  169.             if((*comp)(v[i], v[left])>0)    /* pointer to function and args */
  170.                 swap(v, ++last, i);
  171.         swap(v,left,last);
  172.         qsort1(v, left, last-1, comp);
  173.         qsort1(v, last+1, right, comp);
  174.     }
  175. }
  176. /* atodouble: convert ascii to double */
  177. double atodouble(char *s1)
  178. {
  179.     int i=0;
  180.     double v1=0; /* always initialize counting variables to 0 */
  181.     while(isdigit(s1[i]))
  182.         v1 = (v1*10)+(s1[i++]-'0');
  183.     return v1;
  184. }
  185.  
  186. /* atodouble1: convert ascii to double after skipping n tabs */
  187. double atodouble1(char *s1)
  188. {
  189.     int i=0, scount=0;
  190.     double v1=0;
  191.  
  192.     while(scount<searchint) {
  193.         for(; s1[i]!='\t' && isdigit(s1[i]); i++)
  194.             if(s1[i]=='\0') errormessage();
  195.         if(s1[i]=='\t') i++;
  196.         scount++;
  197.     }
  198.     if(!isdigit(s1[i])) errormessage();
  199.     while(isdigit(s1[i]))
  200.         v1 = (v1*10)+(s1[i++]-'0');
  201.     return v1;
  202. }
  203.  
  204.  
  205. /* numcmp: compare s1 and s2 numerically */
  206. int numcmp(char *s1, char *s2)
  207. {
  208.     double v1, v2;
  209.  
  210.     if(search) {
  211.         v1 = atodouble1(s1);
  212.         v2 = atodouble1(s2);
  213.     }
  214.     else {
  215.         v1 = atodouble(s1);
  216.         v2 = atodouble(s2);
  217.     }
  218.     if(v1<v2)
  219.         return -1;
  220.     else if(v1>v2)
  221.         return 1;
  222.     else
  223.         return 0;
  224. }
  225.  
  226. /* strcmp: return <0 if s<t, O if s==t, >0 if s>t */
  227. int strcmp1(char *s, char *t)
  228. {
  229.     int i=0, j=0, scount=0, tcount=0, tabcount=0;
  230.  
  231.     /* run the search subroutine */
  232.     if(search) {
  233.         while(scount<searchint) {
  234.             for(; s[i]!='\t'; i++)
  235.                 if(s[i]=='\0') errormessage();
  236.             if(s[i]=='\t') i++;
  237.             scount++;
  238.         }
  239.         while(tcount<searchint) {
  240.             for(; t[j]!='\t'; j++)
  241.                 if(t[j]=='\0') errormessage();
  242.             if(t[j]=='\t') j++;
  243.             tcount++;
  244.         }
  245.     }
  246.     for(; ; i++, j++) {     /* iterate until a difference found */
  247.         if(s[i]=='\0') return 0;
  248.         if(dirorder) {
  249.             while(1) {
  250.                 if(isalnum(s[i]) || s[i]==' ') break;
  251.                 i++;
  252.                 if(s[i]=='\0') return 0;
  253.             }
  254.             while(1) {
  255.                 if(isalnum(t[j]) || t[j]==' ') break;
  256.                 j++;
  257.                 if(t[j]=='\0') return 0;
  258.             }
  259.         }
  260.         if(!fold) {
  261.             if(s[i]!=t[j])
  262.                 return s[i] - t[j];
  263.         }
  264.         else {
  265.             if(tolower(s[i]) != tolower(t[j]))
  266.                 return tolower(s[i]) - tolower(t[j]);
  267.         }
  268.     }
  269. }
  270.  
  271. void swap(void *v[], int i, int j)
  272. {
  273.     void *temp;
  274.  
  275.     temp = v[i];
  276.     v[i] = v[j];
  277.     v[j] = temp;
  278. }
  279.  
  280. /* errormessage: print an error message */
  281. void errormessage(void)
  282. {
  283.     puts("Usage: sorted [-n :numeric][-r :reverse][-f :fold][-d :directory_order][-s int :search]");
  284.     exit(-1);
  285. }
Advertisement
Add Comment
Please, Sign In to add comment