Страницы

Translate

понедельник, 18 ноября 2013 г.

Exercise 7.5. Rewrite the postfix calculator of Chapter 4 to use scanf and/or sscanf to do the input and number conversion.



Exercise 7.5. Rewrite the postfix calculator of Chapter 4 to use scanf and/or sscanf to do the input and number conversion.



#include <stdio.h>
#include <stdlib.h>
#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

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>

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


Result:





Exercise 7.4. Write a private version of scanf analogous to minprintf




Exercise 7.4. Write a private version of scanf analogous to minprintf from the previous section.


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

#define ARRAYFMT 10

void minscanf(char *, ...);


/* minscanf: */

void minscanf(char *fmt, ...)
{
    va_list ap; //points to the next unnamed argument
    char *p, *sval;
    int *ival, i;
    unsigned *uval;
    double *dval;
    char arrayfmt[ARRAYFMT]; //array of characters
   
    i = 0;
    va_start(ap, fmt);//establishes for the first unnamed argument
    for(p = fmt; *p; p++)
    {
        if(*p != '%')
        {
            arrayfmt[i++] = *p;
            continue;
        }
        arrayfmt[i++] = '%';
        for(;*(p+1) && !isalpha(*(p+1)); i++)
            arrayfmt[i] = *++p;
        arrayfmt[i++] = *(p+1);//letter format
       
arrayfmt[i] = '\0';       
        switch (*++p) //letter format
        {
            case 'd':
            case 'i':
                ival = va_arg(ap, int *);
                scanf(arrayfmt, ival);
                break;
            case 'f':
                dval = va_arg(ap, double *);
                scanf(arrayfmt, dval);
                break;
            case 's':
                sval = va_arg(ap, char *);
                scanf(arrayfmt, sval);
                break;
            case 'o':
            case 'x':
            case 'X':
            case 'u':
            case 'e':
                uval = va_arg(ap, unsigned *);
                scanf(arrayfmt, uval);
                break;
        }
        i = 0;
    }
    va_end(ap);//clear, after finish}

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

Exercise 7.2. Write a program that will print arbitrary input in a sensible way.



Exercise 7.2. Write a program that will print arbitrary input in a sensible way. As a minimum,
it should print non-graphic characters in octal or hexadecimal according to local custom, and
break long text lines.



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

#define MAXLINE 25 //maximum number of characters in line
#define OCTLEN 8 //length of the octal value

/*  print arbitrary input in a sensible way */
int main()
{
    int c, pos;
   
    pos = 0; //position in string    

    while((c = getchar()) != EOF)
        if(iscntrl(c) || isspace(c))
        {
            if(pos + OCTLEN < MAXLINE)
                pos = pos + OCTLEN;
            else
            {
                putchar('\n');
                pos = OCTLEN;
            }
            printf("
\\%03o", c);
            if(c == '\n')
            {
                pos = 0;
                putchar('\n');
            }
        }
        else
        {
            if(pos + 1 < MAXLINE)
                pos = pos + 1;
            else
            {
                putchar('\n');
                pos = 1;
            }
            putchar(c);
        }
    return 0;
}

Exercise 7.3. Revise minprintf to handle more of the other facilities of printf.


Exercise 7.3. Revise minprintf to handle more of the other facilities of printf.


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


#define MASFMT 10

/* minprintf: */
void minprintf(char *fmt, ...)
{
    va_list ap; //points to the next unnamed argument    

    char *p, *sval;
    int ival, i;
    unsigned uval;
    double dval;
    char masfmt[MASFMT]; //array of characters
   
    va_start(ap, fmt);//establishes for the first unnamed argument
    for(p = fmt; *p; p++)
    {
        if(*p != '%')
        {
            putchar(*p);
            continue;
        }
        i = 0;
        masfmt[i++] = '%';
        for(;*(p+1) && !isalpha(*(p+1)); i++)
            masfmt[i] = *++p;
        masfmt[i++] = *(p+1);//letter format        

        masfmt[i] = '\0';       
        switch (*++p) //letter format
        {
            case 'd':
            case 'i':
                ival = va_arg(ap, int);
                printf(masfmt, ival);
                break;
            case 'f':
                dval = va_arg(ap, double);
                printf(masfmt, dval);
                break;
            case 's':
                for(sval = va_arg(ap, char *); *sval; sval++)
                putchar(*sval);
                break;
            case 'o':
            case 'x':
            case 'X':
            case 'u':
            case 'e':
                uval = va_arg(ap, unsigned);
                printf(masfmt, uval);
                break;
            default:
                putchar (*p);
                break;
        }
    }
    va_end(ap);//clear, after finish

}


вторник, 12 ноября 2013 г.

Exercise 7.1. Write a program that converts upper case to lower or lower case to upper



Exercise 7.1. Write a program that converts upper case to lower or lower case to upper,
depending on the name it is invoked with, as found in argv[0].

I changed a little exercise , I think it would be better.

 Write a program that converts upper case to lower or lower case to upper,
depending on the name it is invoked with, as found in argv[1].


#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
    int c;
   
    if(argc != 2)
    {
        printf("ERROR, no parametrs\n");
        return 1;
    }
    else if(strcmp(argv[1], "lower") == 0)
        while((c = getchar()) != EOF)
            putchar(tolower(c));
    else if(strcmp(argv[1], "upper") == 0)
        while((c = getchar()) != EOF)
            putchar(toupper(c));
    else
        printf("wrong parametrs\n");
    return 0;
}

 

среда, 6 ноября 2013 г.

Exercise 6.6. Implement a simple version of the #define processor (i.e., no arguments)



Exercise 6.6. Implement a simple version of the #define processor (i.e., no arguments) suitable for use with C programs, based on the routines of this section. You may also find getch and ungetch helpful.



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

#define MAXWORD 100
#define HASHSIZE 101

struct nlist{           //table entry
    struct nlist *next; //next entry in chain
    char *name;         //define name
    char *defn;         //replacemrnt text
};
static struct nlist *hashtab[HASHSIZE]; //pointer table 

void error(int, char *);
char *s_dup(char *);
int getch(void);
void ungetch(int);
int getword(char *, int);
void getdef(void);
void undef(char *);
void ungets(char *);
struct nlist *lookup(char *);
struct nlist *install(char *, char *);
void skipspace(void);
unsigned hash(char *);


/* a simple version of the #define processor */
int main()
{
    char word[MAXWORD];
    struct nlist *np;
    
    while(getword(word, MAXWORD) != EOF)
        if(strcmp(word, "#") == 0)  //beginning def processor
            getdef();
        else if(!isalpha(word[0]))
            printf("%s\n", word);   //can't define
        else if((np = lookup(word)) == NULL)
            printf("%s\n", word);   //not define
        else
            ungets(np->defn);       //return definition
    return 0;
}

/* getdef: get definition and put it in table */
void getdef(void)
{
    int i;
    char def[MAXWORD], dir[MAXWORD], name[MAXWORD];
    
    skipspace();
    if(!isalpha(getword(dir, MAXWORD)))
        error(dir[0], "getdef: after # waiting directive");
    else if(strcmp(dir, "define") == 0)
    {
        skipspace();
        if(!isalpha(getword(name, MAXWORD)))
            error(name[0], "getdef: not letter, waiting name");
        else
        {
            skipspace();
            for(i = 0; i < MAXWORD; i++)
                if((def[i] = getch()) == EOF || def[i] == '\n')
                    break;
            def[i] = '\0';
            if(i <= 0) //not definition
                error('\n', "getdef: incomplete definition");
            else //put definition to table
                install(name, def);
        }
    }
    else if(strcmp(dir, "undef") == 0)
    {
        skipspace();
        if(!isalpha(getword(name, MAXWORD)))
            error(name[0], "getdef: not letter in directine undef");
        else
            undef(name);
    }
    else
        error(dir[0], "getdef: aftewr # waiting directive");
}

/* error: print message about error and skip string */
void error(int c, char *s)
{
    printf("Error: %s\n", s);
    while(c != EOF && c != '\n')
        c = getch();
}

/* skipspace: skip space and tabs */
void skipspace(void)
{
    int c;
    
    while((c = getch() == ' ' || c == '\t'))
        ;
    ungetch(c);
}

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

}

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

Exercise 6.5. Write a function undef that will remove a name and definition from the table maintained by lookup and install.



Exercise 6.5. Write a function undef that will remove a name and definition from the table
maintained by lookup and install.


/* undef: remove the name and definition of the table */
void undef(char *s)
{
    int h;
    struct nlist *prev, *np;
    
    prev = NULL;
    h = hash(s);    //hash string s
    for(np = hashtab[h]; np != NULL; np = np->next)
    {
        if(strcmp(s, np->name) == 0)
            break;
        prev = np;
    }
    if(np != NULL)  // name found
    {
        if(prev == NULL)    // it is first name in hash
            hashtab[h] = np->next;
        else    //not first
            prev->next = np->next;
        free((void *) np->name);
        free((void *) np->defn);
        free((void *) np);  //releases the dedicated structure
    }
}