Страницы

Translate

четверг, 29 августа 2013 г.

Exercise 4.14. Define a macro swap(t,x,y) that interchanges two arguments of type t.

Exercise 4.14. Define a macro swap(t,x,y) that interchanges two arguments of type t.
(Block structure will help.)

/* swap(t, x, y) */
#include <stdio.h>

#define SWAP(t, x, y) {t tmp;\
                        tmp = y;\
                        y = x;\
                        x = tmp;}

int main()
{
    int a, b;
    
    a = 25;
    b = 1;
    SWAP(int, a, b);
    printf("a - %d\nb - %d\n", a, b);
    return 0;
}

Result:


Exercise 4.13. Write a recursive version of the function reverse(s).

Exercise 4.13. Write a recursive version of the function reverse(s), which reverses the
string s in place.

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

void reverse(char s[]);

int main()
{
    char s[] = "Hello world";
    
    reverse(s);
    printf("%s\n", s);
    return 0;
}

/* reverce: reverses the string in place */
void reverse(char s[])
{
    char tmp;
    static int i = 0;
    int j = strlen(s) - (i+1);

    if(i < j)
    {
        tmp = s[i];
        s[i++] = s[j];
        s[j] = tmp;
        reverse(s);
    }
}

Result:


Exercise 4.12. Adapt the ideas of printd to write a recursive version of itoa

Exercise 4.12. Adapt the ideas of printd to write a recursive version of itoa; that is, convert
an integer into a string by calling a recursive routine.


#include <stdio.h>

#define LEN 100

void itoa(int n, char s[]);

int abs(int x);

int main()
{
    int n;
    char s[LEN];
    
    printf("Enter the number: ");
    scanf("%d", &n);
    itoa(n, s);
    printf("%s\n", s);
    return 0;
}

/*itoa*/
void itoa(int n, char s[])
{
    static int i; 
    int sign;
    
    i = 0;
    sign = n;
    if(n/10)
        itoa(n/10, s);
    else
    {

        if(sign < 0)
            s[i++] = '-';
    }
    s[i++] = abs(n % 10) + '0';
    s[i] = '\0';
}

понедельник, 26 августа 2013 г.

Exercise 4.11. Modify getop so that it doesn't need to use ungetch. Hint: use an internal static variable.

Exercise 4.11. Modify getop so that it doesn't need to use ungetch. Hint: use an internal static variable.

I use ungetch as a static variable.

/* getop: get next character ot numeric operand */
int getop(char s[])
{
    int i, c;
    static int ungetch = 0; //the last symvol
    if(ungetch == 0)
        c = getch();
    else
    {
        c = ungetch;
        ungetch = 0;
    }
    while((s[0] = c) == ' ' || c == '\t')
        c = getch();
    s[1] = '\0';
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    i = 0;
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            s[++i] = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch = c;
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(s[++i] = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';
    if(c != EOF)
        ungetch = c;
    return NUMBER;
}

Exercise 4.10. An alternate organization uses getline to read an entire input line

Exercise 4.10. An alternate organization uses getline to read an entire input line; this makes getch and ungetch unnecessary. Revise the calculator to use this approach.


/* getop: get next character of numeric operand */
int getop(char s[])
{
    int c, i;
    if(line[m] == '\0')
    {
        if(getlin(line, MAXLINE) == 0)
            return EOF;
        else
            m = 0;
    }
    while((s[0] = c = line[m++]) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    i = 0;
    if(!isdigit(c) && c != '.') // not a number
        return c;
    i = 0;
    if(isdigit(c)) // collect integer part
        while(isdigit(s[++i] = c = line[m++]))
            ;
    if(c == '.') // collect fraction part
        while(isdigit(s[++i] = c = line[m++]))
            ;
    s[i] = '\0';
    m--;
    return NUMBER;
}

суббота, 24 августа 2013 г.

Exercise 4-9. Our getch and ungetch do not handle a pushed-back EOF correctly.

Exercise 4-9. Our getch and ungetch do not handle a pushed-back EOF correctly. Decide
what their properties ought to be if an EOF is pushed back, then implement your design.


We must change char buf into int buf/

#define BUFSIZE 100

int buf[BUFSIZE];  //buffer for ungetch;
int bufp = 0; //next free position in buf

int getch(void) // get a (possibly pushed-back) character  
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) // push character back on input
{
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characnters\n");
    else
        buf[bufp++] = c;
}

Result:


Exercise 4-8. Suppose that there will never be more than one character of pushback. Modify getch and ungetch accordingly.

Exercise 4-8. Suppose that there will never be more than one character of pushback. Modify getch and ungetch accordingly.


/* getch */
char buf = 0;

int getch(void) // get a (possibly pushed-back) character  
{
    int c;
    if(buf == 0)
        c = getchar();
    else
        c = buf;
    buf = 0;
    return c;    
}

/* ungetch */
void ungetch(int c) // push character back on input
{
    if(buf != 0)
        printf("ungetch: too many characnters\n");
    else
        buf = c;
}

Result:


Exercise 4-7. Write a routine ungets(s) that will push back an entire string onto the input.

Exercise 4-7. Write a routine ungets(s) that will push back an entire string onto the input. Should ungets know about buf and bufp, or should it just use ungetch?


#include <string.h>

/* ungets */
void ungets( char s[])
{
    int len;
    
    len = strlen(s);
    while(len > 0)
        ungetch(s[--len]);
}

 Ungets should not know about buf and bufp, and it just use ungetch.

пятница, 23 августа 2013 г.

Exercise 4-6. Add commands for handling variables.

Exercise 4-6. Add commands for handling variables. (It's easy to provide twenty-six variables with single-letter names.) Add a variable for the most recently printed value.



#include <stdio.h>
#include <stdlib.h> //for atof()
#include <math.h>

#define MAXOP 100 //max size of operand or operator
#define NUMBER '0' //signal that a number was found

int getop(char[]);
void push(double);
double pop(void);

/* reverse polish calculator */
int main()
{
    int type, i, val;
    double op2, v;
    char s[MAXOP];
    double variable[26];
    
    val = 0;
    for(i = 0; i < 26; i++)
        variable[i] = 0.0;
    while((type = getop(s)) != EOF)
    {
        switch(type)
        {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() + pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if(op2 != 0)
                    push(pop() / op2);
                else
                    printf("error: zero devisior\n");
                break;
            case '%':
                op2 = pop();
                if(op2 != 0.0)
                    push(fmod(pop(), op2));
                else
                    printf("error: zero devisor\n");
                break;
            case '=':
                pop();
                if(val >= 'A' && val <= 'Z')
                    variable[val - 'A'] = pop();
                else
                    printf("error: not name of variable\n");
                break;
            case '\n':
                v = pop();
                printf("\t%.8g\n", v);
                break;
            default:
                if(type >= 'A' && type <= 'Z')
                    push(variable[type - 'A']);
                else if (type == 'v')
                    push(v);
                else
                    printf("error: unknown command %s\n", s);
                break;
        }
        val = type;
    }
    return 0;
}

#define MAXVAL 100 //maximum depth of val stack


double val[MAXVAL]; //value stack
int sp = 0; //next free stack position

/* push: push f into value stack */
void push(double f)
{
    if(sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full, can`t push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void)
{
    if(sp > 0)
        return val[--sp];
    else
    {
        printf("error: stack empty\n");
        return 0.0;
    }
}

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getop: get next character ot numeric operand */
int getop(char s[])
{
    int i, c;
    while((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    i = 0;
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            s[++i] = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch(c);
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(s[++i] = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  //buffer for ungetch;
int bufp = 0; //next free position in buf

int getch(void) // get a (possibly pushed-back) character  
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) // push character back on input
{
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characnters\n");
    else
        buf[bufp++] = c;
}


Exercise 4-5. Add access to library functions like sin, exp, and pow.

Exercise 4-5. Add access to library functions like sin, exp, and pow.

#include <stdio.h>
#include <stdlib.h> //for atof()
#include <math.h>
#include <string.h>

#define MAXOP 100 //max size of operand or operator
#define NUMBER '0' //signal that a number was found
#define NAME 'a' // signal that a name was found

int getop(char[]);
void push(double);
double pop(void);
void clear(void);
void mathfunc(char[]);


/* reverse polish calculator */
int main()
{
    int type;
    double op2;
    char s[MAXOP];
    
    while((type = getop(s)) != EOF)
    {
        switch(type)
        {
            case NUMBER:
                push(atof(s));
                break;
            case NAME:
                mathfunc(s);
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() + pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if(op2 != 0)
                    push(pop() / op2);
                else
                    printf("error: zero devisior\n");
                break;
            case '%':
                op2 = pop();
                if(op2 != 0.0)
                    push(fmod(pop(), op2));
                else
                    printf("error: zero devisor\n");
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("error: unknown command %s\n", s);
                break;
        }
    }
    return 0;
}

#define MAXVAL 100 //maximum depth of val stack

double val[MAXVAL]; //value stack
int sp = 0; //next free stack position

/* push: push f into value stack */
void push(double f)
{
    if(sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full, can`t push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void)
{
    if(sp > 0)
        return val[--sp];
    else
    {
        printf("error: stack empty\n");
        return 0.0;
    }
}

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getop: get next character ot numeric operand */
int getop(char s[])
{
    int i, c;
    while((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    i = 0;
    if(islower(c)) //command or name
    {
        while(islower(s[++i] = c = getch()))
            ;
        s[i] = '\0';
        if(c != EOF)
            ungetch(c);
        if(strlen(s) > 1)
            return NAME;
        else
            return c;
    }
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            s[++i] = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch(c);
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(s[++i] = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  //buffer for ungetch
int bufp = 0; //next free position in buf

int getch(void) // get a (possibly pushed-back) character  
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) // push character back on input
{
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characnters\n");
    else
        buf[bufp++] = c;
}

/* mathfunc */
void mathfunc(char s[])
{
    double op2;
    if(strcmp(s, "sin") == 0)
        push(sin(pop()));
    else if(strcmp(s, "exp") == 0)
        push(exp(pop()));
    else if(strcmp(s, "pow")== 0)
        {
            op2 = pop();
            push(pow(pop(), op2));
        }
    else
        printf("error: unknown command %s\n", s);
}

Result:


Exercise 4-4. Add the commands to print the top elements of the stack without popping, to duplicate it, and to swap the top two elements. Add a command to clear the stack.

Exercise 4-4. Add the commands to print the top elements of the stack without popping, to duplicate it, and to swap the top two elements. Add a command to clear the stack.

#include <stdio.h>
#include <stdlib.h> //for atof()
#include <math.h>

#define MAXOP 100 //max size of operand or operator
#define NUMBER '0' //signal that a number was found

int getop(char[]);
void push(double);
double pop(void);
void clear(void);

/* reverse polish calculator */
int main()
{
    int type;
    double op1, op2;
    char s[MAXOP];
    
    while((type = getop(s)) != EOF)
    {
        switch(type)
        {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() + pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if(op2 != 0)
                    push(pop() / op2);
                else
                    printf("error: zero devisior\n");
                break;
            case '%':
                op2 = pop();
                if(op2 != 0.0)
                    push(fmod(pop(), op2));
                else
                    printf("error: zero devisor\n");
                break;
            case '?':
                op2 = pop();
                printf("\t%.8g\n", op2);
                push(op2);
                break;
            case 'd': //double
                op2 = pop();
                push(op2);
                push(op2);
                break;
            case 'r': //reverse
                op1 = pop();
                op2 = pop();
                push(op1);
                push(op2);
                break;
            case 'c': //clean
                clear();
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("error: unknown command %s\n", s);
                break;
        }
    }
    return 0;
}

#define MAXVAL 100 //maximum depth of val stack

double val[MAXVAL]; //value stack
int sp = 0; //next free stack position

/* push: push f into value stack */
void push(double f)
{
    if(sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full, can`t push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void)
{
    if(sp > 0)
        return val[--sp];
    else
    {
        printf("error: stack empty\n");
        return 0.0;
    }
}

/* clear */
void clear(void)
{
    sp = 0;
}

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getop: get next character ot numeric operand */
int getop(char s[])
{
    int i, c;
    while((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    i = 0;
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            s[++i] = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch(c);
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(s[++i] = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  //buffer for ungetch;
int bufp = 0; //next free position in buf

int getch(void) // get a (possibly pushed-back) character  
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) // push character back on input
{
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characnters\n");
    else
        buf[bufp++] = c;
}

Result:



Exercise 4-3. Add the modulus (%) operator and provisions for negative numbers.

Exercise 4-3. Given the basic framework, it's straightforward to extend the calculator. Add the
modulus (%) operator and provisions for negative numbers.

#include <stdio.h>
#include <stdlib.h> //for atof()
#include <math.h>

#define MAXOP 100 //max size of operand or operator
#define NUMBER '0' //signal that a number was found

int getop(char[]);
void push(double);
double pop(void);

/* reverse polish calculator */
int main()
{
    int type;
    double op2;
    char s[MAXOP];
    
    while((type = getop(s)) != EOF)
    {
        switch(type)
        {
            case NUMBER:
                push(atof(s));
                break;
            case '+':
                push(pop() + pop());
                break;
            case '*':
                push(pop() + pop());
                break;
            case '-':
                op2 = pop();
                push(pop() - op2);
                break;
            case '/':
                op2 = pop();
                if(op2 != 0)
                    push(pop() / op2);
                else
                    printf("error: zero devisior\n");
                break;
            case '%':
                op2 = pop();
                if(op2 != 0.0)
                    push(fmod(pop(), op2));
                else
                    printf("error: zero devisor\n");
                break;
            case '\n':
                printf("\t%.8g\n", pop());
                break;
            default:
                printf("error: unknown command %s\n", s);
                break;
        }
    }
    return 0;
}

#define MAXVAL 100 //maximum depth of val stack

int sp;
double val[MAXVAL]; //value stack
int sp = 0; //next free stack position

/* push: push f into value stack */
void push(double f)
{
    if(sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full, can`t push %g\n", f);
}

/* pop: pop and return top value from stack */
double pop(void)
{
    if(sp > 0)
        return val[--sp];
    else
    {
        printf("error: stack empty\n");
        return 0.0;
    }
}

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getop: get next character ot numeric operand */
int getop(char s[])
{
    int i, c;
    while((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if(!isdigit(c) && c != '.' && c != '-') // not a number
        return c; 
    i = 0;
    if (c == '-')
    {
        if(isdigit(c = getch()) || c == '.')
            s[++i] = c; //negative numbers
        else
            {
                if(c != EOF)
                    ungetch(c);
                return '-';
            }
    }
    if(isdigit(c)) //collect integer part
        while(isdigit(s[++i] = c = getch()))
            ;
    if(c == '.') //collect fraction part
        while(isdigit(s[++i] = c = getch()))
            ;
    s[i] = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  //buffer for ungetch
int bufp = 0; //next free position in buf

int getch(void) // get a (possibly pushed-back) character  
{
   return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) // push character back on input
{
    if(bufp >= BUFSIZE)
        printf("ungetch: too many characnters\n");
    else
        buf[bufp++] = c;
}

Result:


Exercise 4-2. Extend atof to handle scientific notation of the form 123.45e-6

Exercise 4-2. Extend atof to handle scientific notation of the form 123.45e-6 where a floating-point number may be followed by e or E and an optionally signed exponent.


#include <stdio.h>
#include <ctype.h>

#define MAXLINE 100

/*rudimentary calculator*/
int main()
{
    double atof(char[]);
    char line[MAXLINE];
    int getlin(char line[], int max);
    while(getlin(line, MAXLINE) > 0)
        printf("\t%g\n", atof(line));
    return 0;
}

/*atof: convert string s to double*/
double atof(char s[])
{
    double val, power;
    int i, sign, exp;
    
    for(i = 0; isspace(s[i]); i++) //skip white space
        ;
    sign = (s[i] == '-') ? -1 : 1;
    if(s[i] == '+' || s[i] == '-')
        i++;
    for(val = 0.0; isdigit(s[i]); i++)
        val = 10.0 * val +(s[i] -'0');
    if(s[i] == '.')
        i++;
    for(power = 1.0; isdigit(s[i]); i++)
    {
        val = 10.0 * val + (s[i] -'0');
        power *= 10.0;
    }
    val = sign * val / power;
    if(s[i] == 'e' || s[i] == 'E')
    {
        i++;
        sign = (s[i] == '-') ? -1 : 1;
        if(s[i] == '+' || s[i] == '-')
            i++;
        for(exp = 0; isdigit(s[i]); i++)
            exp = 10*exp + (s[i] - '0');
        if(sign == 1)
            for(; exp > 0; exp--)
                val *=10;
        else
            for(; exp > 0; exp--)
                val /= 10;
    }
    return val;
}

/* getlin */
int getlin(char line[], int max)
{
    int c, i;
    
    i = 0;
    while(--max > 0 && (c=getchar()) != EOF && c != '\n')
        line[i++] = c;
    if(c == '\n')
        line[i++] = c;
    line[i] = '\0';
    return i;
}

Result: