Страницы

Translate

вторник, 10 сентября 2013 г.

Exercise 5.7. Rewrite readlines to store lines in an array supplied by main, rather than calling alloc to maintain storage.

Exercise 5.7. Rewrite readlines to store lines in an array supplied by main, rather than
calling alloc to maintain storage.


#include <stdio.h>
#include <string.h>

#define MAXLINES 5000 //max lines to be sorted
#define BUFSIZE 5000

char *lineptr[MAXLINES]; //pointers to text lines

int readlines(char *lineptr[], char *buf, int nlines);
void writelines(char *lineptr[], int nlines);

void qsort(char *lineptr[], int left, int right);

/* sort input lines */
int main()
{
    int nlines; //number of input lines read
    char buf[BUFSIZE];  
    if((nlines = readlines(lineptr, buf, MAXLINES)) >= 0)
    {
        printf("%d\n", nlines);
        qsort(lineptr, 0, nlines - 1);
        writelines(lineptr, nlines);
        return 0;
    }
    else
    {
        printf("error: input too big to sort\n");
        return 1;
    }
}

#define MAXLEN 1000 //max lenght of any input line


int getlin(char *, int);

/* readlines: read input lines */
int readlines(char *lineptr[], char *buf, int maxlines)
{
    int len, nlines;

    char line[MAXLEN];
    
    char *p = buf;     
    char *bufstop = buf + BUFSIZE;
    
    nlines = 0;
    while((len = getlin(line, MAXLEN)) > 0)
    {
        if(nlines >= maxlines || p + len > bufstop)
            return -1;
        else
        {
            line[len - 1] = '\0'; //delete newline
            strcpy(p, line);
            lineptr[nlines++] = p;
            p += len;
        }
    }
    return nlines;
}

/* writelines: write output lines */
void writelines(char *lineptr[], int nlines)
{
    int i;
    
    for(i = 0; i < nlines; i++)
        printf("%s\n", lineptr[i]);
}

int getlin(char *l, int lim)
{
    int c;
    char *tmp = l;
    for(; --lim > 0 && (c=getchar()) != EOF && c!='\n'; l++)
        *l = c;
    if(c=='\n')
        *l++ = c;
    *l = '\0';
    return l - tmp;
}


/* qsort: sort v[left]...v[right] into increasing order */
void qsort(char *lineptr[], int left, int right)
{
    int i, last;
    void swap(char *lineptr[], int i, int j);
    
    if(left >= right) //do nothing if array contains
        return; //fewer than two elementes
    swap(lineptr, left, (left + right)/2);
    last = left;
    for(i = left + 1; i <= right; i++)
        if(strcmp(lineptr[i], lineptr[left]) < 0)
            swap(lineptr, ++last, i);
    swap(lineptr, left, last);
    qsort(lineptr, left, last - 1);
    qsort(lineptr, last + 1, right);
}

void swap(char *lineptr[], int i, int j)
{
    char *temp;
    
    temp = lineptr[i];
    lineptr[i] = lineptr[j];
    lineptr[j] = temp;
}

Result:


суббота, 7 сентября 2013 г.

Exercise 5.6. Rewrite appropriate programs from earlier chapters and exercises with pointers instead of array indexing.

Exercise 5.6. Rewrite appropriate programs from earlier chapters and exercises with pointers
instead of array indexing. Good possibilities include getline (Chapters 1 and 4), atoi, itoa,
and their variants (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop
(Chapter 4).


/* getline */
int getline(char *l, int lim)
{
    int c;
    char *tmp = l;

    for(; --lim > 0 && (c=getchar()) != EOF && c!='\n'; l++)
        *l = c;
    if(c=='\n')
        *l++ = c;
    *l = '\0';
    return l - tmp;
}


/* atoi */
int atoi(char *s)
{
    int number, indigit, hexdig;

    if(*s++ == '0')
        if(*s == 'x' || *s == 'X')
            s++;
    indigit = IN; // in number
    number=0;
    for(;indigit == IN; s++)
    {
        if(*s >= '0' && *s <= '9')
            hexdig = *s - '0';
        else if(*s >= 'a' && *s <= 'f')
            hexdig = *s - 'a'+ 10;
        else if(*s >= 'A' && *s <= 'F')
            hexdig = *s - 'A'+ 10;
        else
            indigit = OUT; // out number
        if(indigit == IN)
            number = number*16 + hexdig;
    }
    return number;
}


/*itoa*/
void itoa(int n, char *s)
{
    int sign;
    char *t = s;
    
    sign = n; //save sign
    do 
    {
        *s++ = abs(n % 10) + '0'; //next number
    } while ((n /= 10) != 0);
    if (sign < 0)
        *s++ = '-';
    *s = '\0';
    reverse(t);
}



/* reverse */
void reverse(char *s)
{
    int c; 
    char *t;
    
    for(t = s + (strlen(s) - 1); s < t; s++, t--)
    {
        c = *s;
        *s = *t;
        *t = c;
    }
}



/*strindex: return index of pattern in line, -1 if none*/
int strindex(char *s, char *sf)
{
    char *sc = s;
    char *j, *k;
    
    for(; *s != '\0'; s++)
    {
        for(j = s, k = sf; *k != '\0' && *j == *k; j++, k++)
            ;
        if(k > sf && *k == '\0')
            return s - sc ;
    }
    return -1;
}


/* getop: get next character ot numeric operand */
#include <math.h>

int getop(char *s)
{
    int c;
    while((*s = c = getch()) == ' ' || c == '\t')
        ;
    *(s+1) = '\0';
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            *++s = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch(c);
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(*++s = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(*++s = c = getch()))
            ;
    *s = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;
}

пятница, 6 сентября 2013 г.

Exercise 5.5. Write versions of the library functions strncpy, strncat, and strncmp.

Exercise 5.5. Write versions of the library functions strncpy, strncat, and strncmp, which operate on at most the first n characters of their argument strings. For example, strncpy(s,t,n) copies at most n characters of t to s.

/* strncpy */
void strncpy(char *t, char *s, int n)
{
    while(n-- && *t)
            *t++ = *s++;
    while(*t)
        *t++='\0';
}

/* strncat */
void strncat(char *t, char *s, int n)
{
    while(*t)
        t++;
    while(*s && n--)
        *t++ = *s++;
    *t = '\0';
}


/* strncmp */
int strncmp(char *t, char *s, int n)
{
    for(;*t == *s && n > 0; t++, s++, n--)
        ;
    if(n == 0)
        return 0;
    else if(*t == '\0' && *s)
        return -1;
    else if(*t && *s == '\0')
        return 1;
    else
        return *t - *s;
}

четверг, 5 сентября 2013 г.

Exercise 5.4. Write the function strend(s,t).

Exercise 5.4. Write the function strend(s,t), which returns 1 if the string t occurs at the end of the string s, and zero otherwise.


/* strend */
int strend(char *s, char *t)
{
    char tmps = *s;
    char tmpt = *t;
    while(*s)
        s++;
    while(*t)
        t++;
    while(*s == *t)
    {
        if(*s == tmps || *t == tmpt)
            break;
        s--;
        t--;
    }
    if(*s == *t && *t == tmpt && *s != '\0')
        return 1;
    else
        return 0;
}

Exercise 5.3. Write a pointer version of the function strcat that we showed in Chapter 2

Exercise 5.3. Write a pointer version of the function strcat that we showed in Chapter 2: strcat(s,t) copies the string t to the end of s.


* strcat */
void strcat(char *s, char *t)
{
    while(*s++) //search '\0'
        ;
    s--;
    while((*s++ = *t++) != '\0') //copies the string t to the end of s
        ;
}

воскресенье, 1 сентября 2013 г.

Exercise 5.2. Write getfloat, the floating-point analog of getint

Exercise 5.2. Write getfloat, the floating-point analog of getint. What type does getfloat return as its function value?


/* getint: get next float from input into *pn */
int getfloat(float *pn)
{
    int c, sign, mark;
    float fract;
    
    while(isspace(c = getch())) //skip white space
        ;
    if(!isdigit(c) && c != EOF && c != '+' && c != '-' && c != '.')
    {
        ungetch(c); //it's not a number
        return 0;
    }
    sign = (c == '-') ? -1 : 1;
    if(c == '+' || c == '-')
    {
        mark = c; //remember a sign
        c = getch();
        if(!isdigit(c))
        {
            if(c != EOF)
                ungetch(c); //not a number - back on the input
            ungetch(mark); //back sign of the symvol on the input
            return 0; 
        }
    }
    for(*pn = 0.0; isdigit(c); c = getch())
        *pn = 10.0 * *pn + (c - '0'); // collect integer part
    if(c == '.')
        c = getch();
    for(fract = 1.0; isdigit(c); c = getch())
    {
        *pn = 10.0 * *pn +(c - '0');
        fract *=10.0;
    }
    
    *pn *= sign/fract;
    if(c != EOF)
        ungetch(c);
    return c;
}

Type function getfloat is INT.

Exercise 5.1. As written, getint treats a + or - not followed by a digit as a valid representation of zero.

Exercise 5.1. As written, getint treats a + or - not followed by a digit as a valid representation of zero. Fix it to push such a character back on the input.




* getint: get next integer from input into *pn */
int getint(int *pn)
{
    int c, sign, mark;
    
    while(isspace(c = getch())) //skip white space
        ;
    if(!isdigit(c) && c != EOF && c != '+' && c != '-')
    {
        ungetch(c); //it's not a number
        return 0;
    }
    sign = (c == '-') ? -1 : 1;
    if(c == '+' || c == '-')
    {
        mark = c; //remember a sign
        c = getch();
        if(!isdigit(c))
        {
            if(c != EOF)
                ungetch(c); //not a number - back on the input
            ungetch(mark); //back sign of the symvol on the input
            return 0; 
        }
    }
    for(*pn = 0; isdigit(c); c = getch())
        *pn = 10 * *pn + (c - '0');
    *pn *= sign;
    if(c != EOF)
        ungetch(c);
    return c;
}