Thread: Exercise 5-17 k&R

  1. #1
    Registered User
    Join Date
    Jun 2013
    Posts
    9

    Exercise 5-17 k&R

    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.)
    This is the code i was following (Tondo's Book)
    Code:
    //main.c
    #include <stdio.h>
    #include <ctype.h>
    
    
    #define NUMERIC 1
    #define DECR 2
    #define FOLD 4
    #define DIR 8
    #define LINES 100
    
    
    int charcmp(char *, char *);
    void error(char *);
    int numcmp(char *, char *);
    void readargs(int argc, char *argv[]);
    int readlines(char *lineptr[], int maxlines);
    void qusort(void *v[],int left, int right,int (*comp)(void *, void *));
    void writelines(char *lineptr[], int nlines, int decr);
    
    
    char option = 0;
    int pos1 = 0;
    int pos2 = 0;
    int main(int argc, char *argv[])
    {
        char *lineptr[LINES];
        int nlines;
        int rc = 0;
        
        readargs(argc, argv);
        if((nlines = readlines(lineptr, LINES)) > 0 ) {
            if (option & NUMERIC)
                qusort((void **) lineptr, 0 , nlines - 1,
                            (int (*) (void *, void *)) numcmp);
            else
                qusort((void **) lineptr, 0, nlines-1,
                            (int (*)(void *,void *)) charcmp);
            writelines(lineptr,nlines,option & DECR);
        } else {
                printf("input too big to sort \n");
                rc = -1;
        }
        return rc;
    }
    
    
    void readargs(int argc, char *argv[])
    {
        int c;
        int atoi(char *);
        
        while((--argc>0) && (((c = (*++argv)[0])=='-')||(c=='+')))
        {
            if (c=='-' && !isdigit(*(argv[0]+1)))
                while((c = *++argv[0]))
                    switch(c) {
                    case 'd':
                        option |= DIR;
                        break;
                    case 'f':
                        option |= FOLD;
                        break;
                    case 'n':
                        option |= NUMERIC;
                        break;
                    case 'r':
                        option |= DECR;
                        break;
                    default:
                        printf("sort: illegal option %c\n", c);
                        error("Usage: sort -dfnr [+pos1] [-pos2]");
                        break;
                    }
            else if (c == '-')
                pos2 = atoi(argv[0]+1);
            else if ((pos1 = atoi(argv[0]+1)) < 0)
                error("Usage: sort -dfnr [+pos1] [-pos2]");
        }
        if (argc || pos1 > pos2)
            error("Usage: sort -dfnr [+pos1] [-pos2]");
    }
    
    
    void writelines(char *lineptr[], int nlines, int decr)
    {
        int i;
        if(decr)
            for(i = nlines - 1; i >=0; i--)
                printf("%s\n",lineptr[i]);
        else
            for(i = 0;i <nlines; i++)
                printf("%s\n",lineptr[i]);
    }
    
    
    #include <string.h>
    #define MAXLEN 1000
    int getline(char *, int);
    char *alloc(int);
    int readlines(char *lineptr[], int maxlines)
    {
            int len, nlines;
            char *p, line[MAXLEN];
            nlines = 0;
            while ((len = getline(line, MAXLEN)) > 0)
            if (nlines >= maxlines || (p = alloc(len+1)) == NULL)
                return -1;
            else {
            line[len] = '\0'; /* delete newline */
            strcpy(p, line);
            lineptr[nlines++] = p;
            }
            return nlines;
    }
    
    
    int getline(char *s, int lim)
    {
        int c;
        char *t = s;
        while(--lim > 0 && (c = getchar()) != EOF && c != '\n')
            *s++ = c;
        *s = '\0';
        return s - t;
    }
    
    
    #define ALLOCSIZE 10000 /* size of available space */
    static char allocbuf[ALLOCSIZE]; /* storage for alloc */
    static char *allocp = allocbuf; /* next free position */
    char *alloc(int n) /* return pointer to n characters */
    {
        if (allocbuf + ALLOCSIZE - allocp >= n) 
        { /* it fits */
            allocp += n;
            return allocp - n; /* old p */
        } 
        else /* not enough room */
            return 0;
    }
    
    
    void swap(void *v[], int i, int j);
    void qusort(void *v[], int left, int right, int(*comp)(void *, void *))
    {
         int i, last;
         void swap(void *v[], int, int);
    
    
         if(left >= right)
            return;
    
    
         swap(v, left, (left + right) / 2);
         last = left;
         for(i = left + 1; i <= right; i++) 
            if((*comp)(v[i], v[left]) < 0)
               swap(v, ++last, i);
         swap(v, left, last);
         qusort(v, left, last - 1, comp);
         qusort(v, last + 1, right, comp);
    }
    
    
    void swap(void *v[], int i, int j)
    {
            void *temp;
            temp = v[i];
            v[i] = v[j];
            v[j] = temp;
    }
    //numcmp.c
    #include <math.h>
    #include <ctype.h>
    #include <string.h>
    
    
    #define MAXSTR 100
    
    
    void substr(char *s, char *t, int maxstr);
    
    
    int numcmp(char *s1, char *s2)
    {
        double v1,v2;
        char str[MAXSTR];
        
        substr(s1, str, MAXSTR);
        v1 = atof(str);
        substr(s2,str,MAXSTR);
        v2 = atof(str);
        if(v1 < v2)
            return -1;
        else if (v1 > v2)
            return 1;
        else
            return 0;
    }
    
    
    #define FOLD    4
    #define DIR        8
    int charcmp(char *s, char *t)
    {
        char a, b;
        int i, j, endpos;
        extern char option;
        extern int pos1, pos2;
        int fold = (option & FOLD) ? 1 : 0;
        int dir = (option & DIR) ? 1 : 0;
        
        i = j = pos1;
        if(pos2 > 0)
            endpos = pos2;
        else if((endpos = strlen(s)) > strlen(t))
            endpos = strlen(t);
        do {
                if(dir) {
                    while(i < endpos && !isalnum(s[i]) && s[i] != ' ' && s[i] != '\0')
                    i++;
                    while(j < endpos && !isalnum(t[j]) && t[j] != ' ' && t[j] != '\0')
                    j++;
                }
                if (i <endpos && j < endpos) {
                a = fold ? tolower(s[i]): s[i];
                i++;
                b = fold ? tolower(t[j]): t[j];
                j++;
                if(a == b && a == '\0')
                    return 0;
                }
            } while(a == b && i < endpos && j < endpos);
            return a - b;
    }
    //substr.c
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    
    void error(char *);
    
    
    void substr(char *s, char *str)
    {
        int i, j, len;
        extern int pos1, pos2;
        
        len = strlen(s);
        if(pos2 > 0 && len > pos2)
            len = pos2;
        else if(pos2 > 0 && len < pos2)
            error("substr: string too short");
        for(j = 0, i = pos1; i < len; i++, j++)
            str[j] = s[i];
        str[j] = '\0';
    }
    void error(char *s)
    {
        printf("%s \n", s);
        exit(1);
    }
    gcc main.c numcmp.c substr.c -Wall -Werror -pedantic -g -o SortFields.exe
    no errors on compilation.

    My problem lies on how to use the arguments on locating the position of the field to be sorted. I am following this link c - K&R Task Exercise 5.17 - Stack Overflow but it doesn't discuss what argument to use to sort the second field.

    The instruction "Usage: sort -dfnr [+pos1] [-pos2]" - i don't know how to use this, I only know -dfnr since i have done the previous exercises.The problem lies with what pos1 and pos2 is and use this to sort any field position i want. I think you should look at the readargs() function because i think that's where the problem lies.
    Last edited by BinaryProgamer; 06-21-2013 at 05:58 AM.

  2. #2
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by BinaryProgamer View Post
    gcc main.c numcmp.c substr.c -Wall -Werror -pedantic -g -o SortFields.exe
    no errors on compilation.
    You should get at least a warning that atof() isn't declared properly in numcmp.c.

    And this also looks strange:
    Code:
    //numcmp.c
    void substr(char *s, char *t, int maxstr);
    ...
    //substr.c
    void substr(char *s, char *str)
    Isn't there a parameter to much in numcmp.c?

    Anyways, if I fix that I get:
    Code:
    $ cat test.txt
    apple  9 3
    pear   2 8
    orange 6 4
    banana 1 4
    $ ./foo -n +7 -8 < test.txt
    banana 1 4
    pear   2 8
    orange 6 4
    apple  9 3
    $ ./foo -n +9 -10 < test.txt
    apple  9 3
    banana 1 4
    orange 6 4
    pear   2 8
    So, "pos1" is the start of the field and "pos2" one past the end which should also be obvious after reading charcmp() and substr().

    Bye, Andreas

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. exercise in c
    By hugoguan in forum C Programming
    Replies: 1
    Last Post: 11-30-2010, 04:32 AM
  2. Help exercise!
    By sanhthai in forum C++ Programming
    Replies: 10
    Last Post: 09-22-2009, 12:07 PM
  3. Exercise 2-6 K&R help
    By allix in forum C Programming
    Replies: 19
    Last Post: 08-18-2006, 09:25 AM
  4. Exercise
    By bumfluff in forum C++ Programming
    Replies: 15
    Last Post: 04-21-2006, 12:18 PM
  5. Help with K&R Exercise 1.13
    By Yannis in forum C Programming
    Replies: 2
    Last Post: 09-21-2003, 02:51 PM