Страницы

Translate

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

Exercise 7.9. Functions like isupper can be implemented to save space or to save time. Explore both possibilities



Exercise 7.9. Functions like isupper can be implemented to save space or to save time.
Explore both possibilities.



#include <ctype.h>

/* to save space */

int isupper(char c)
{
    if(c >= 'A' && c =< 'Z')
        return 1;
    else
        return 0;
}

/* to save time */

#define isupper(c) ((c) >= 'A' && (c) <= 'Z') ? 1 : 0


пятница, 29 ноября 2013 г.

Exercise 7.8. Write a program to print a set of files, starting each new one on a new page, with a title and a running page count for each file



Exercise 7.8. Write a program to print a set of files, starting each new one on a new page,
with a title and a running page count for each file.



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

#define MAXFIELD 2 //maximum rows at the top and bottom of the page
#define MAXSTRING 60
#define MAXLINE 100
#define NAME 20

FILE *in, *out;
void fprint(char *pfile);
int headfile(char *pfile, int pageno);

int main(int argc, char *argv[])
{

    char file[NAME];
    char fileout[NAME]; //the output file
   
    if(argc == 1)
    {
        printf("ERROR, no arguments\n");
        return 1;
    }
    else
    {
        printf("Type the name of the output file: ");
        gets(fileout);
        out = fopen(fileout, "w");
        while(--argc > 0)
        {
            strcpy(file, *++argv);
            if((in = fopen(file, "r")) == NULL)
            {
                perror(file);
                return 1;
            }
            else
            {
                fprint(file);
                fclose(in);
            }
        }
    }
    fclose(out);
    return 0;
}

/* print the selected file */
void fprint(char *pfile)
{
    char line[MAXLINE];
    int lineno, pageno;

   
    lineno = pageno = 1;
    lineno = headfile(pfile, pageno);
    pageno++;
    while(!feof(in))
    {
        if(lineno == 1)
        {
            fprintf(out, "\f");
            lineno = headfile(pfile, pageno);
            pageno++;
        }
        fgets(line, MAXLINE-1, in);
        fputs(line,out);
        lineno++;
        if(lineno == (MAXSTRING - MAXFIELD))
            lineno = 1;
    }
    fprintf(out, "\f");
}

/* print header and blank lines */
int headfile(char *pfile, int pageno)
{
    int line = 0;
   
    while(line++ < MAXFIELD)
        fprintf(out, "\n");
    fprintf(out, "file %s, page - %d\n", pfile, pageno);
    line++;
    return line;
}

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

Exercise 7.7. Modify the pattern finding program of Chapter 5 to take its input from a set of named files or, if no files are named as arguments, from the standard input.



Exercise 7.7. Modify the pattern finding program of Chapter 5 to take its input from a set of named files or, if  no files are named as arguments, from the standard input. Should the file name be printed when a matching  line is found?

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

#define MAXLINE 1000
#define NAME 20

FILE *in;
int except = 0;
int number = 0;
long lineno = 0;

int getline(char *line, int max);
void fstdin(char *line, char *pattern);
void ffile(FILE *fp, char *pattern, char *line, char *file_name);

/* find:  print lines that match pattern from 1st arg */
int main(int argc, char *argv[])
{
     char line[MAXLINE];
     char pattern[MAXLINE];
     char file[NAME];
;
     int c;
         
     while(--argc > 0 && (*++argv)[0] == '-')
        while(c = *++argv[0])
            switch(c)
            {
                case 'x':
                    except = 1;
                    break;
                case 'n':
                    number = 1;
                    break;
                default:
                    printf("find: illegal option %c\n", c);
                    argc = 0;
                    break;
            }
    if(argc < 1)
    {
        printf("Usage: find -x -n pattern file...\n");
        return 1;
    }
    else
        strcpy(pattern, *argv);
    if (argc == 1) // read from stdin
        fstdin(line, pattern //search in the string
    else
        while(--argc != 0) //get file`s name
        {
            strcpy(file, *++argv);
            if((in = fopen(file, "r")) == NULL)
            {
                perror(file);
                return 1;
            }
            else
            {
                ffile(in, pattern, line,file); //search in the file
                fclose(in);
            }
        }
    return 0;
}

/* ffile: search in the file */

void ffile(FILE *in, char *pattern, char *line, char *file_name)
{
    while(!feof(in))
    {
        fgets(line, MAXLINE-1, in);
        lineno++;
        if((strstr(line, pattern) != NULL) != except)
        {
            printf("%s\n", file_name);
            if(number)
                printf("%ld: ", lineno);
            printf("%s", line);
        }
    }
}
       
/* fstdin: search in the string from standart input */
void fstdin(char *line, char *pattern)
{
    while(getline(line, MAXLINE) > 0)
    {
        lineno++;
        if((strstr(line, pattern) != NULL) != except)
        {
            if(number)
                printf("%ld: ", lineno);
            printf("%s", line);
        }
    }
}

/* getline: read the string, return the length */

int getline(char *line, int max)
{
    if(fgets(line, max, stdin) == NULL)
        return 0;
    else
        return strlen(line);
}


Result:


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

Exercise 7.6. Write a program to compare two files, printing the first line where they differ



Exercise 7.6. Write a program to compare two files, printing the first line where they differ.



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

#define MAXNAME 20
#define MAXLINE 100

FILE *first, *second;

int main()
{
    char f[MAXNAME], s[MAXNAME], str1[MAXLINE], str2[MAXLINE];
   
    printf("type the names of the compared files\n");
    printf("first: ");
    gets(f);
    printf("second: ");
    gets(s);
    if((first = fopen(f, "r")) == NULL)
    {
        perror(f);
        return 1;
    }
    else if((second = fopen(s, "r")) == NULL)
    {
        perror(s);
        return 1;
    }
    else
        printf("files open\n\n");
    while(!feof(first) && !feof(second))
    {
        fgets(str1, MAXLINE-1, first);
        fgets(str2, MAXLINE-1, second);
        if(strcmp(str1,str2) != 0)
             {
                printf("first different strings:\n\n");
                printf("%s\n%s\n", str1, str2);
                break;
            }
    }
    fclose(first);
    fclose(second);
    return 0;
}


Result:







понедельник, 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
    }
}