lolamontes69

K+R Exercise5_16

Sep 25th, 2014
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.97 KB | None | 0 0
  1. /* Add the -d ("directory order") option, which makes comparisons only on
  2.  * letters, numbers and blanks. Make sure it works in conjunction with -f.
  3.  */
  4.  
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #define MAXLINES 5000            /* max #lines to be sorted */
  11. #define MAXLEN 1000
  12. #define ALLOCSIZE 10000          /* size of available space */
  13.  
  14. static char allocbuf[ALLOCSIZE]; /* storage of alloc   */
  15. static char *allocp = allocbuf;  /* next free position */
  16.  
  17. char *lineptr[MAXLINES];         /* pointers to text lines */
  18.  
  19. char *alloc(int n);
  20. int readlines(char *lineptr[], int nlines);
  21. int getline(char *s, int lim);
  22. void writelines(char *lineptr[], int nlines);
  23. /* qsort() renamed because qsort() in stdlib.h */
  24. void qsort1(void *lineptr[], int left, int right,
  25.            int (*comp)(void *, void*));      /* a pointer to a function that returns
  26.                                                 an integer and two pointers as args. */
  27. int numcmp(char *, char *);
  28. int strcmp1(char *s, char *t);               /* renamed because strcmp() in stdlib.h */
  29. void swap(void *v[], int, int);
  30. void errormessage(void);
  31.  
  32. static int numeric = 0;  /* 1 if numeric sort */
  33. static int reverse = 0;  /* 1 if reverse sort */
  34. static int fold = 0;
  35. static int dirorder = 0;
  36.  
  37.  
  38. /* sort input lines */
  39. main(int argc, char *argv[])
  40. {
  41.     int nlines, c;       /* number of input lines read */
  42.     while(--argc>0) {
  43.         if((*++argv)[0] == '-') {
  44.             while(c = *++argv[0])
  45.                 switch(c) {
  46.                 case 'n':
  47.                     numeric++;
  48.                     break;
  49.                 case 'r':
  50.                     reverse++;
  51.                     break;
  52.                 case 'f':
  53.                     fold++;
  54.                     break;
  55.                 case 'd':
  56.                     dirorder++;
  57.                     break;
  58.                 default:
  59.                     errormessage();
  60.                     return 0;
  61.                 }
  62.         }
  63.     }
  64.  
  65.     if((nlines = readlines(lineptr, MAXLINES)) >= 0) {
  66.         qsort1((void**) lineptr, 0, nlines-1,
  67.           (int (*)(void *,void *))(numeric ? numcmp : strcmp1)); /* pointer to function that returns
  68.                                                                   an integer with two pointers as args */
  69.         writelines(lineptr,nlines);
  70.         return 0;
  71.     }
  72.     else {
  73.         printf("input too big to sort\n");
  74.         return 1;
  75.     }
  76. }
  77.  
  78. /* alloc: return pointer to n characters */
  79. char *alloc(int n)
  80. {
  81.     if(allocbuf + ALLOCSIZE - allocp >= n) {
  82.         allocp += n;
  83.         return allocp - n;
  84.     }
  85.     else return 0;
  86. }
  87.  
  88. /* readline: read input lines */
  89. int readlines(char *lineptr[], int maxlines)
  90. {
  91.     int len, nlines;
  92.     char *p, line[MAXLEN];
  93.  
  94.     nlines = 0;
  95.     while((len=getline(line, MAXLEN))>0)
  96.         if(nlines >= maxlines || (p = alloc(len+1)) == NULL)  /* len+1 to allocate next free */
  97.             return -1;                                        /* space after '\0' */
  98.         else {
  99.             line[len]='\0'; /* delete newline */
  100.             strcpy(p, line);
  101.             lineptr[nlines++] = p;
  102.         }
  103.     return nlines;
  104. }
  105.  
  106. /* getline: get a line of input into an array */
  107. int getline(char *s, int lim)
  108. {
  109.     int c, i;
  110.  
  111.     for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
  112.         s[i]=c;
  113.     s[i]='\0';
  114.     return i;
  115. }
  116.  
  117. /* writelines: write output lines */
  118. void writelines(char *lineptr[], int nlines)
  119. {
  120.     int i;
  121.     puts("---- Sorted words ----");
  122.     while(nlines-- > 0)
  123.         printf("%s\n", *lineptr++);
  124. }
  125.  
  126.  
  127. /* qsort: sort v[left]...v[right] into increasing order */
  128. void qsort1(void *v[], int left, int right,
  129.            int (*comp)(void *, void *))
  130. {
  131.     int i, last;
  132.     if(!reverse) {
  133.         if(left >= right)  /* do nothing if array contains */
  134.             return;        /* fewer than two elements */
  135.         swap(v, left, (left + right)/2);
  136.         last = left;
  137.         for(i=left+1; i<=right; i++)
  138.             if((*comp)(v[i], v[left])<0)    /* pointer to function and args */
  139.                 swap(v, ++last, i);
  140.         swap(v,left,last);
  141.         qsort1(v, left, last-1, comp);
  142.         qsort1(v, last+1, right, comp);
  143.     }
  144.     if(reverse) {
  145.         if(left >= right)  /* do nothing if array contains */
  146.             return;        /* fewer than two elements */
  147.         swap(v, left, (left + right)/2);
  148.         last = left;
  149.         for(i=left+1; i<=right; i++)
  150.             if((*comp)(v[i], v[left])>0)    /* pointer to function and args */
  151.                 swap(v, ++last, i);
  152.         swap(v,left,last);
  153.         qsort1(v, left, last-1, comp);
  154.         qsort1(v, last+1, right, comp);
  155.     }
  156. }
  157.  
  158. /* numcmp: compare s1 and s2 numerically */
  159. int numcmp(char *s1, char *s2)
  160. {
  161.     double v1, v2;
  162.  
  163.     v1 = atof(s1);
  164.     v2 = atof(s2);
  165.     if(v1<v2)
  166.         return -1;
  167.     else if(v1>v2)
  168.         return 1;
  169.     else
  170.         return 0;
  171. }
  172.  
  173. /* strcmp: return <0 if s<t, O if s==t, >0 if s>t */
  174. int strcmp1(char *s, char *t)
  175. {
  176.     int i, j;
  177.  
  178.     for(i=0,j=0; ; i++, j++) {     /* iterate until a difference found */
  179.         if(s[i]=='\0') return 0;
  180.         if(dirorder) {
  181.             while(1) {
  182.                 if(isalnum(s[i]) || s[i]==' ') break;
  183.                 i++;
  184.                 if(s[i]=='\0') return 0;
  185.             }
  186.             while(1) {
  187.                 if(isalnum(t[j]) || t[j]==' ') break;
  188.                 j++;
  189.                 if(t[j]=='\0') return 0;
  190.             }
  191.         }
  192.         if(!fold) {
  193.             if(s[i]!=t[j])
  194.                 return s[i] - t[j];
  195.         }
  196.         else {
  197.             if(tolower(s[i]) != tolower(t[j]))
  198.                 return tolower(s[i]) - tolower(t[j]);
  199.         }
  200.     }
  201. }
  202.  
  203. void swap(void *v[], int i, int j)
  204. {
  205.     void *temp;
  206.  
  207.     temp = v[i];
  208.     v[i] = v[j];
  209.     v[j] = temp;
  210. }
  211.  
  212. /* errormessage: print an error message */
  213. void errormessage(void)
  214. {
  215.     puts("Usage: sorted [-n :numeric][-r :reverse][-f :fold][-d :directory_order]");
  216. }
Advertisement
Add Comment
Please, Sign In to add comment