[Exercise] Exercise 5-17 field-searching capability page 121

User avatar

Topic author
BJT
Site Admin
Site Admin
Posts: 141
Joined: Thu Apr 20, 2017 4:43 pm
Instruction: University Student
Gender:
Age: 27
Venezuela

Exercise 5-17 field-searching capability page 121

Post by BJT » Sat May 13, 2017 1:33 am

Exercise 5-17. Add a field-searching capability, so sorting may bee done on fields within lines, each field sorted according to an independent set of options. (The index for this book was sorted with -df for the index category and -n for the page numbers.)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #define NUMERIC 1
  7. #define DECR 2
  8. #define FOLD 4
  9. #define DIR 8
  10. #define MAXLINES 5000       /* max #lines to be sorted */
  11. #define MAXLEN 1000 /* max length of any input line */
  12.  
  13. size_t get_line(char *, int);
  14. char *alloc(int);
  15. int readlines(char *lineptr[], int nlines);
  16. void writelines(char *lineptr[], int nlines, int decr);
  17. void my_qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
  18. int numcmp(char *, char *);
  19. int charcmp(char *, char *);
  20.  
  21. char *lineptr[MAXLINES];    /* pointers to text lines */
  22.  
  23. static char option=0;
  24. int pos1=0;  //position to star the compare to sort in the string
  25. int pos2=0;  //position to end the compare to sort in the string
  26. int flag=0; //to know if a sort by field was requested
  27. char aux1[1000],aux2[1000]; //auxiliar char to not change the original s1 and s2
  28. void substring(char* aux1, char* s1, size_t original_length_s1, char* aux2, char* s2, size_t original_length_s2); //obtain a substring if sort by field was requested
  29.  
  30. /* sort input lines */
  31. int main(int argc, char *argv[])
  32. {
  33.     int nlines;     /* number of input lines read */
  34.  
  35.     while (--argc>0 && (**(++argv)=='-'||**(argv)=='+'))
  36.     {
  37.         if( isalpha(*(*(argv)+1)) ) //Is it a letter?
  38.         {
  39.             for(int i=1; i<strlen(*argv);i++)
  40.             {
  41.                 if( *(*(argv)+i)=='n' && **argv=='-')
  42.                 {
  43.                     option|=NUMERIC;
  44.                 }
  45.                 else if ( *(*(argv)+i)=='r' && **argv=='-')
  46.                 {
  47.                     option|=DECR;
  48.                 }
  49.                 else if ( *(*(argv)+i)=='f' && **argv=='-')
  50.                 {
  51.                     option|=FOLD;
  52.                 }
  53.                 else if ( *(*(argv)+i)=='d' && **argv=='-')
  54.                 {
  55.                     option|=DIR;
  56.                 }
  57.             }
  58.         }
  59.  
  60.         if( isdigit(*(*(argv)+1)) && **argv=='-') //Is it a digit?
  61.         {
  62.             pos1=atoi((*(argv)+1));
  63.             flag=1;
  64.         }
  65.  
  66.         if( isdigit(*(*(argv)+1)) && **argv=='+') //Is it a digit?
  67.         {
  68.             pos2=atoi((*(argv)+1));
  69.             flag=1;
  70.         }
  71.     }
  72.  
  73.     //check input of pos1 and pos2
  74.  
  75.     if(pos1==pos2 && flag)
  76.     {
  77.         printf("Error: pos1 must be different to pos2");
  78.         return EXIT_FAILURE;
  79.     }
  80.     else if((pos1<0||pos2<0) && flag)
  81.     {
  82.         printf("Error: pos1 and pos2 must be greater than zero");
  83.         return EXIT_FAILURE;
  84.     }
  85.     else if(pos1>pos2 && flag)
  86.     {
  87.         printf("Error: pos1 must be greater than pos2");
  88.         return EXIT_FAILURE;
  89.     }
  90.  
  91.     if ((nlines = readlines(lineptr, MAXLINES)) >= 0)
  92.     {
  93.         if(option&NUMERIC)
  94.             my_qsort((void**) lineptr, 0, nlines-1,(int (*)(void*,void*))numcmp);
  95.         else
  96.             my_qsort((void**) lineptr, 0, nlines-1,(int (*)(void*,void*))charcmp);
  97.         writelines(lineptr, nlines, option & DECR);
  98.         return 0;
  99.     }
  100.     else
  101.     {
  102.         printf("input too big to sort\n");
  103.         return 1;
  104.     }
  105. }
  106.  
  107. /* readlines: 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 = get_line(line, MAXLEN)) > 0)
  115.         if (nlines >= maxlines || (p = alloc(len))== NULL)
  116.             return -1;
  117.         else
  118.         {
  119.             line[len-1] = '\0'; /* delete newline */
  120.             strcpy(p, line);
  121.             lineptr[nlines++] = p;
  122.         }
  123.  
  124.     return nlines;
  125. }
  126.  
  127. /* writelines: write output lines */
  128. void writelines(char *lineptr[], int nlines, int decr)
  129. {
  130.     int i;
  131.  
  132.     if (decr) /*Print in reveser order*/
  133.         for(int i=nlines-1;i>=0;i--)
  134.             printf("%s\n", lineptr[i]);
  135.     else
  136.         for (i = 0; i < nlines; i++)
  137.             printf("%s\n", lineptr[i]);
  138. }
  139.  
  140. /* qsort: sort v[left]...v[right] into increasing order */
  141. void my_qsort(void *v[], int left, int right, int (*comp)(void *, void *))
  142. {
  143.     int i, last;
  144.     void swap(void *v[], int, int);
  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)
  151.             swap(v, ++last, i);
  152.     swap(v, left, last);
  153.     my_qsort(v, left, last-1, comp);
  154.     my_qsort(v, last+1, right, comp);
  155. }
  156.  
  157. int charcmp(char *s, char *t)
  158. {
  159.     char a,b;
  160.     int fold= (option & FOLD) ? 1:0;
  161.     int dir = (option & DIR) ? 1:0;
  162.  
  163.     if (flag)
  164.     {
  165.         substring(aux1,s,strlen(s),aux2,t,strlen(t)); //Geting sub string
  166.         char *p_aux1=aux1,*p_aux2=aux2;
  167.         do
  168.         {
  169.             if(dir)
  170.             {
  171.                 while(!isalnum(*p_aux1) && *p_aux1 != ' ' && *p_aux1 != '\0')
  172.                     p_aux1++;
  173.                 while(!isalnum(*p_aux2) && *p_aux2 != ' ' && *p_aux2 != '\0')
  174.                     p_aux2++;
  175.             }
  176.             a = fold ? tolower(*p_aux1):*p_aux1;
  177.             p_aux1++;
  178.             b = fold ? tolower(*p_aux2):*p_aux2;
  179.             p_aux2++;
  180.  
  181.             if (a==b && a=='\0')
  182.                 return 0;
  183.  
  184.         } while(a==b);
  185.     }
  186.     else
  187.     {
  188.         do
  189.         {
  190.             if(dir)
  191.             {
  192.                 while(!isalnum(*s) && *s != ' ' && *s != '\0')
  193.                     s++;
  194.                 while(!isalnum(*t) && *t != ' ' && *t != '\0')
  195.                     t++;
  196.             }
  197.             a = fold ? tolower(*s):*s;
  198.             s++;
  199.             b = fold ? tolower(*t):*t;
  200.             t++;
  201.  
  202.             if (a==b && a=='\0')
  203.                 return 0;
  204.  
  205.         } while(a==b);
  206.     }
  207.  
  208.     return a-b;
  209. }
  210.  
  211. /* numcmp: compare s1 and s2 numerically */
  212. int numcmp(char *s1, char *s2)
  213. {
  214.     double v1, v2;
  215.  
  216.     //Geting a substring if sort by field was requested
  217.     if(flag)
  218.     {
  219.         substring(aux1,s1,strlen(s1),aux2,s2,strlen(s2));
  220.         v1 = atof(aux1);
  221.         v2 = atof(aux2);
  222.  
  223.     }
  224.     else
  225.     {
  226.         v1 = atof(s1);
  227.         v2 = atof(s2);
  228.     }
  229.  
  230.     if (v1 < v2)
  231.         return -1;
  232.     else if (v1 > v2)
  233.         return 1;
  234.     else
  235.         return 0;
  236. }
  237.  
  238. void swap(void *v[],int i, int j)
  239. {
  240.     void *temp;
  241.  
  242.     temp = v[i];
  243.     v[i] = v[j];
  244.     v[j] = temp;
  245. }
  246.  
  247. #define ALLOCSIZE 10000
  248. static char allocbuf[ALLOCSIZE];
  249. static char *allocp = allocbuf;
  250.  
  251. char *alloc(int n)
  252. {
  253.     if(ALLOCSIZE + allocbuf - allocp>= n )
  254.     {
  255.         allocp += n;
  256.         return allocp - n;
  257.     }
  258.     else
  259.         return 0;
  260. }
  261.  
  262. size_t get_line(char* f_line,int n)
  263. {
  264.     int c;
  265.     size_t size=(size_t)f_line;
  266.  
  267.     while(((size_t)f_line-size)<n && (c=getchar())!=EOF && c!='\n')
  268.         *f_line++=c;
  269.  
  270.     if(c=='\n')
  271.         *(f_line++)=c;
  272.  
  273.     *(f_line)='\0';
  274.  
  275.     return (size_t)f_line-size;
  276. }
  277.  
  278. void substring(char* aux1, char* s1, size_t l1, char* aux2, char* s2, size_t l2)
  279. {
  280.     //create s1 field
  281.     if(pos1>l1)//take all the string
  282.        memccpy(aux1,s1,l1,l1);
  283.     else if (pos2>l1)  //take it to the end of the stirng
  284.     {
  285.         memccpy(aux1,s1+pos1,l1-pos1,l1-pos1); //copy the bytes to compare in the beginning of s1;
  286.         *(aux1 + l1-pos1)='\0';                //truncate to get olny the bytes to compare
  287.     }
  288.     else
  289.     {
  290.         memccpy(aux1,s1+pos1,pos2-pos1,pos2-pos1);
  291.         *(aux1 + pos2-pos1)='\0';
  292.     }
  293.  
  294.     //create s2 field
  295.     if(pos1>l2)//take all the string
  296.         memccpy(aux2,s2,l2,l2);
  297.     else if (pos2>l2)  //take it to the end of the stirng
  298.     {
  299.         memccpy(aux2,s1+pos1,l2-pos1,l2-pos1); //copy the bytes to compare in the beginning of s1;
  300.         *(aux2 + l1-pos1)='\0';                //truncate to get olny the bytes to compare
  301.     }
  302.     else
  303.     {
  304.         memccpy(aux2,s2+pos1,pos2-pos1,pos2-pos1);
  305.         *(aux2 + pos2-pos1)='\0';
  306.     }
  307. }

NOTE: the field position of pos1 points to the next character and the field search pos2 points the character before

input Will sort by the field of the second number in reverse

Code: Select all

./c -dnfr -1 +2
6345643
43424
2345236
6575363
242432
654654
output

Code: Select all

654654
6575363
242432
43424
6345643
2345236
input Will sort by the field of the second character in reverse

Code: Select all

./c -dr -1 +2
rfvey
tyjty
awefwaf
tykur
wfjyt
luykyuj
gvfdbv
wcfd
output

Code: Select all

tyjty
tykur
awefwaf
gvfdbv
luykyuj
wfjyt
rfvey
wcfd
word count: 1159

Link:
BBcode:
HTML:
Hide post links
Show post links

Who is online

Users browsing this forum: No registered users and 2 guests