From 54db8ccf0e734028e2ed17f3371d258d3daa4d9c Mon Sep 17 00:00:00 2001 From: aro17 Date: Thu, 14 Nov 2013 14:23:46 +0100 Subject: [PATCH] Ex chapter 4 and 5 --- c_programming/ex_4-06_variables.c | 295 ++++++ c_programming/ex_4-06_variables_v2.c | 405 ++++++++ c_programming/ex_4-06_variables_v3.c | 404 ++++++++ c_programming/ex_4-07_ungets.c | 85 ++ c_programming/ex_4-08_ungetch_v2.c | 57 ++ c_programming/ex_4-09_ungetch_EOF.c | 58 ++ c_programming/ex_4-10_getline.c | 285 ++++++ c_programming/ex_4-11_static.c | 297 ++++++ c_programming/ex_4-12_recursive_itoa.c | 75 ++ c_programming/ex_4-13_recursive_reverse.c | 77 ++ c_programming/ex_4-14_macro_swap.c | 49 + c_programming/ex_4-14_macro_swap.i | 877 ++++++++++++++++++ c_programming/ex_5-01-02_pointers-arrays.c | 144 +++ .../ex_5-03-06_pointers_characters.c | 167 ++++ c_programming/getopt.c | 166 ++++ c_programming/signed_char_conversion.c | 37 + 16 files changed, 3478 insertions(+) create mode 100644 c_programming/ex_4-06_variables.c create mode 100644 c_programming/ex_4-06_variables_v2.c create mode 100644 c_programming/ex_4-06_variables_v3.c create mode 100644 c_programming/ex_4-07_ungets.c create mode 100644 c_programming/ex_4-08_ungetch_v2.c create mode 100644 c_programming/ex_4-09_ungetch_EOF.c create mode 100644 c_programming/ex_4-10_getline.c create mode 100644 c_programming/ex_4-11_static.c create mode 100644 c_programming/ex_4-12_recursive_itoa.c create mode 100644 c_programming/ex_4-13_recursive_reverse.c create mode 100644 c_programming/ex_4-14_macro_swap.c create mode 100644 c_programming/ex_4-14_macro_swap.i create mode 100644 c_programming/ex_5-01-02_pointers-arrays.c create mode 100644 c_programming/ex_5-03-06_pointers_characters.c create mode 100644 c_programming/getopt.c create mode 100644 c_programming/signed_char_conversion.c diff --git a/c_programming/ex_4-06_variables.c b/c_programming/ex_4-06_variables.c new file mode 100644 index 0000000..a6f54f6 --- /dev/null +++ b/c_programming/ex_4-06_variables.c @@ -0,0 +1,295 @@ +/* + * ex_4-06_variables.c -- Ex KnR book + * + * 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. + * + * Written by Harold André + * E-mail + * + * Started on Thu Oct 24 15:33:18 2013 Harold André + * Last update Thu Oct 24 18:37:28 2013 Harold André + * + * gcc -Wall -o ex_4-06_variables ex_4-06_variables.c -lm + * + */ + + +#include +#include /* for atof() - in K&R, math.h is referenced - this is an anachronism */ +#include /* for sin(), exp(), pow() */ +#include /* for strcmp() */ + +#define MAXOP 100 /* max size of operand or operator */ +#define NUMBER '0' /* signal that a number was found */ +#define IDENTIFIER 1 +#define VARMAX 26 /* variables from 'A' to 'Z' */ + +//#define DEBUG + +double var_array[VARMAX]; + +int getop(char []); +void push(double); +double pop(void); +void print(void); +void dup(void); +void swap(void); +void clear(void); +void dealWithName(char []); + +/* reverse Polish calculator */ + +int main(void) +{ + int type; + double op2; + char s[MAXOP]; + + while((type = getop(s)) != EOF) + { + switch(type) + { + case NUMBER: +#ifdef DEBUG + printf("NUMBER string = %s, NUMBER convert to float = %f\n",s, atof(s)); +#endif + push(atof(s)); + break; + case IDENTIFIER: +#ifdef DEBUG + printf("Operator IDENTIFIER receive\n"); +#endif + dealWithName(s); + break; + case '+': +#ifdef DEBUG + printf("Operator '+' receive\n"); +#endif + push(pop() + pop()); + break; + case '*': +#ifdef DEBUG + printf("Operator '*' receive\n"); +#endif + push(pop() * pop()); + break; + case '-': +#ifdef DEBUG + printf("Operator '-' receive\n"); +#endif + op2 = pop(); + push(pop() - op2); + break; + case '/': +#ifdef DEBUG + printf("Operator '/' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + push(pop() / op2); + else + printf("error: zero divisor\n"); + break; + case '%': +#ifdef DEBUG + printf("Operator '%%' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + /* % don't work with double or float type */ + /* we could use fmod instead */ + push((int)pop() % (int)op2); + else + printf("error: zero divisor\n"); + break; + case '\n': + /* TODO: No pop if stak is empty ?*/ + printf("\t%.8g\n", pop()); + break; + case 'p': + print(); + break; + case 'd': + dup(); + break; + case 's': + swap(); + break; + case 'c': + clear(); + break; + default: + printf("error: unknown command %s\n", s); + break; + } + } + + return 0; +} + +#define MAXVAL 100 /* maximum depth of val stack */ + +int sp = 0; /* next free stack position */ +double val[MAXVAL]; /* value stack */ + +/* push: push f onto 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; + } +} + +/* print: print the top element of the stack without popping */ +void print(void) +{ + printf("sp = %d\n", sp); + if (sp > 0) + printf("%e, %f, %g\n", val[sp-1], val[sp-1], val[sp-1]); + else + printf("Stack empty\n"); +} + +/* dup: duplicate the top element of the stack */ +void dup(void) +{ + if (sp > 0) { + val[sp] = val[sp-1]; + sp++; + } else { + printf("error: stack empty, can't duplicate"); + } +} + +/* swap: swap the top two elements of the stack */ +void swap(void) +{ + /* TODO: improve it without temp*/ + double temp; + + if (sp > 1) { + temp = val[sp-1]; + val[sp-1] = val[sp-2]; + val[sp-2] = temp; + } else { + printf("error: stack hold less than two elements, can't swap"); + } +} + +/* clear: clear the stack */ +void clear(void) +{ + sp = 0; +} + +/* deal with a string/name this may be either a maths function + or for future exercices: a variable */ +void dealWithName(char s[]) +{ + double op2; + + if (0 == strcmp(s, "sin")) + push(sin(pop())); + else if (0 == strcmp(s, "exp")) + push(exp(pop())); + else if (0 == strcmp(s, "pow")) { + op2 = pop(); + push(pow(pop(), op2)); + } + else + printf("%s is not a supported function.\n", s); +} + +#include + +int getch(void); +void ungetch(int); + +/* getop: get next operator or numeric operand */ +int getop(char s[]) +{ + int i, c; + + /* ignore space and tabulation characters */ + while((s[0] = c = getch()) == ' ' || c == '\t') + ; + + s[1] = '\0'; /* useless ??? why this line, avoid security whole ? */ + + /* variables are 'A' to 'Z' */ + if (isalpha(c) && (c >= 'A' || c <= 'Z')) { + var_array[c - 'A'] + return VARIABLE; + } + + if (isalpha(c)) { + i = 0; + while (isalpha(s[i++] = c)) + c = getch(); + s[i - 1] = '\0'; + if (c != EOF) + ungetch(c); + return IDENTIFIER; + } + + if (!isdigit(c) && c != '.' && c != '-') + return c; /* not a number */ + + i = 0; + /* a minus immediatly follow by a number is a negative number + otherwise is minus operator */ + if (s[0] == '-') { + c = getch(); + if (!isdigit(c) && c != '.') { + if(c != EOF) + ungetch(c); + return s[0]; + } else { + s[++i] = c; + } + } + + 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 characters\n"); + else + buf[bufp++] = c; +} diff --git a/c_programming/ex_4-06_variables_v2.c b/c_programming/ex_4-06_variables_v2.c new file mode 100644 index 0000000..a521702 --- /dev/null +++ b/c_programming/ex_4-06_variables_v2.c @@ -0,0 +1,405 @@ +/* + * ex_4-06_variables_v2.c -- Ex KnR book + * + * Solution 1 from website + * + * 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. + * + * Written by Harold André + * E-mail + * + * Started on Thu Oct 24 18:34:55 2013 Harold André + * Last update Thu Oct 24 18:37:16 2013 Harold André + * + * gcc -Wall -o ex_4-06_variables_v2 ex_4-06_variables_v2.c -lm + * + */ + +#include +#include +#include +#include +#include + +#define MAXOP 100 +#define NUMBER 0 +/* 4-6 these are new for this exercise*/ +#define IDENTIFIER 1 +#define ENDSTRING 2 +/* 4-6 end of new stuff */ +#define TRUE 1 +#define FALSE 0 +#define MAX_ID_LEN 32 +#define MAXVARS 30 + +/* +The new additions deal with adding variables to the calculator. + + If the identifier is recognised as one of the supported mathematical + functions then that function from the library is called. If the + identifier is not one of the supported functions, even if it is a + valid function from math.h it is ignored. + + This is a class 1 solution as it uses structures which are not + introduced until Chapter 6. This allows the use of "normal" names for + variables rather than the suggested single letter though any + identifier is limited to 31 characters. + + The main changes are: + + 1. The introduction of two more define values (IDENTIFIER, + ENDSTRING) along with associated cases in the switch statement. + 2. Getop has also been changed to deal with reading in alphabetical + characters and coping with the '=' sign. + 3. A structure to hold the variable name and value. + 4. Another case in the switch statement to deal with the '=' sign. + 5. Altering the clearStack function to clear the array of structs as + well as the stack. + 6. The '<' operator now prints the last accessed variable. + + Improvements: + The code could be made class 0 by the use of "parallel" arrays for the + names and values rather than a struct but this would be messy and is + the situation that structs were made for. + The use of a binary tree together with dynamically allocated memory + would allow the arbitrary limit of 30 variables to be avoided. This + would still be a class 1 solution. + + This is exercise 4-6 from Kernighan & Ritchie, page 79. +*/ + +/* 4-6 this is new for this program */ +struct varType{ + char name[MAX_ID_LEN]; + double val; +}; +/* 4-6 End of new stuff */ + +int Getop(char s[]); +void push(double val); +double pop(void); +void showTop(void); +void duplicate(void); +void swapItems(void); + +/* 4-6 this is new for this program */ +/* Changed clearStack(void) to clearStacks(struct varType var[])*/ +void clearStacks(struct varType var[]); +void dealWithName(char s[], struct varType var[]); +void dealWithVar(char s[], struct varType var[]); + +int pos = 0; +struct varType last; + +/* 4-6 End of new stuff */ + +int main(void) +{ + int type; + double op2; + char s[MAXOP]; + struct varType var[MAXVARS]; + + /* Use the new function here */ + clearStacks(var); + + while((type = Getop(s)) != EOF) + { + switch(type) + { + case NUMBER: + push(atof(s)); + break; + case IDENTIFIER: + dealWithName(s, var); + break; + case '+': + push(pop() + pop()); + break; + case '*': + push(pop() * pop()); + break; + case '-': + op2 = pop(); + push(pop()- op2); + break; + case '/': + op2 = pop(); + if(op2) + push(pop() / op2); + else + printf("\nError: division by zero!"); + break; + case '%': + op2 = pop(); + if(op2) + push(fmod(pop(), op2)); + else + printf("\nError: division by zero!"); + break; + case '?': + showTop(); + break; + case '#': + duplicate(); + break; + case '~': + swapItems(); + break; + case '!': + clearStacks(var); + break; + case '\n': + printf("\n\t%.8g\n", pop()); + break; + /* 4-6 this is new for this program */ + case ENDSTRING: + break; + case '=': + pop(); + var[pos].val = pop(); + last.val = var[pos].val; + push(last.val); + break; + case '<': + printf("The last variable used was: %s (value == %g)\n", + last.name, last.val); + break; + /* 4-6 End of new stuff */ + default: + printf("\nError: unknown command %s.\n", s); + break; + } + } + return EXIT_SUCCESS; +} + +#define MAXVAL 100 + +int sp = 0; /* Next free stack position. */ +double val[MAXVAL]; /* value stack. */ + +/* push: push f onto stack. */ +void push(double f) +{ + if(sp < MAXVAL) + val[sp++] = f; + else + printf("\nError: 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("\nError: stack empty\n"); + return 0.0; + } +} + +void showTop(void) +{ + if(sp > 0) + printf("Top of stack contains: %8g\n", val[sp-1]); + else + printf("The stack is empty!\n"); +} + +/* +Alternatively: +void showTop(void) +{ +double item = pop(); +printf("Top of stack contains: %8g\n", item); +push(item); +} +*/ + +void duplicate(void) +{ + double temp = pop(); + + push(temp); + push(temp); +} + +void swapItems(void) +{ + double item1 = pop(); + double item2 = pop(); + + push(item1); + push(item2); +} + +/* 4-6 this is new for this program */ +/* Altered to clear both the main stack and that of the variable +structure */ +void clearStacks(struct varType var[]) +{ + int i; + + /* Clear the main stack by setting the pointer to the bottom. */ + sp = 0; + + /* Clear the variables by setting the initial element of each name + to the terminating character. */ + for( i = 0; i < MAXVARS; ++i) + { + var[i].name[0] = '\0'; + var[i].val = 0.0; + } +} + +/* a string/name may be either a maths function or a variable */ +void dealWithName(char s[], struct varType var[]) +{ + double op2; + + if(!strcmp(s, "sin")) + push(sin(pop())); + else if(!strcmp(s, "cos")) + push(cos(pop())); + else if (!strcmp(s, "exp")) + push(exp(pop())); + else if(!strcmp(s, "pow")) + { + op2 = pop(); + push(pow(pop(), op2)); + } + /* Finally if it isn't one of the supported maths functions we have a + variable to deal with. */ + else + { + dealWithVar(s, var); + } +} + +/* Our identifier is not one of the supported maths function so we have + to regard it as an identifier. */ +void dealWithVar(char s[], struct varType var[]) +{ + int i = 0; + + while(var[i].name[0] != '\0' && i < MAXVARS-1) + { + if(!strcmp(s, var[i].name)) + { + strcpy(last.name, s); + last.val = var[i].val; + push(var[i].val); + pos = i; + return; + } + i++; + } + + /* variable name not found so add it */ + strcpy(var[i].name, s); + /* And save it to the last variable */ + strcpy(last.name, s); + push(var[i].val); + pos = i; +} +/* 4-6 End of new stuff */ + +int getch(void); +void unGetch(int); + +/* Getop: get next operator or numeric operand. */ +int Getop(char s[]) +{ + int i = 0; + int c; + int next; + + /* Skip whitespace */ + while((s[0] = c = getch()) == ' ' || c == '\t') + { + ; + } + s[1] = '\0'; + + if(isalpha(c)) + { + i = 0; + while(isalpha(s[i++] = c )) + { + c = getch(); + } + s[i - 1] = '\0'; + if(c != EOF) + unGetch(c); + return IDENTIFIER; + } + + /* Not a number but may contain a unary minus. */ + if(!isdigit(c) && c != '.' && c != '-') + { + /* 4-6 Deal with assigning a variable. */ + if('=' == c && '\n' == (next = getch())) + { + unGetch('\0'); + return c; + } + if('\0' == c) + return ENDSTRING; + + return c; + } + + if(c == '-') + { + next = getch(); + if(!isdigit(next) && next != '.') + { + return c; + } + c = next; + } + else + { + c = getch(); + } + + while(isdigit(s[++i] = c)) + { + 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 + +int buf[BUFSIZE]; +int bufp = 0; + +/* Getch: get a ( possibly pushed back) character. */ +int getch(void) +{ + return (bufp > 0) ? buf[--bufp]: getchar(); +} + +/* unGetch: push character back on input. */ +void unGetch(int c) +{ + if(bufp >= BUFSIZE) + printf("\nUnGetch: too many characters\n"); + else + buf[bufp++] = c; +} diff --git a/c_programming/ex_4-06_variables_v3.c b/c_programming/ex_4-06_variables_v3.c new file mode 100644 index 0000000..74126a9 --- /dev/null +++ b/c_programming/ex_4-06_variables_v3.c @@ -0,0 +1,404 @@ +/* + * ex_4-06_variables_v3.c -- Ex KnR book + * + * Solution 2 from website + * + * 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. + * + * Written by Harold André + * E-mail + * + * Started on Thu Oct 24 18:34:55 2013 Harold André + * Last update Thu Oct 24 18:39:33 2013 Harold André + * + * gcc -Wall -o ex_4-06_variables_v3 ex_4-06_variables_v3.c -lm + * + */ + +#include +#include /* For atof() */ +#include +#include + +#define MAXOP 100 /* Max size of operand or operator. */ +#define NUMBER '0' /* Signal that a number was found. */ +#define VARIABLE '1' +#define VARMAX 27 + +int is_first_input = 0; /* Prevents the solution from being printed on first + input */ +double var_array[VARMAX]; /* Contains user defined variables. */ + +int getop(char []); +void push(double); +double pop(void); +double top(void); +int clear(void); +int swap(void); +int elem(void); +int dup(void); +void sprnt(void); +void result(void); +void set_solution(void); +void print_help(void); + +int main() +{ + int type; + int i, j; + int op3; + double topd; + double op2; + char s[MAXOP]; + char tmp[MAXOP]; + + for (i = 0; i < VARMAX; i++) { + var_array[i] = 0; + } + + print_help(); + + while ((type = getop(s)) != EOF) { + + op3 = elem(); + if (op3 == 0) { /* Only one input completed. */ + is_first_input = 1; + } else if (op3 > 1) { + is_first_input = 0; + } + + i = j = 0; + + switch (type) { + case NUMBER: + push(atof(s)); + break; + case VARIABLE: + for (i = 2; s[i] != '\0'; i++){ + tmp[j++] = s[i]; + tmp[j] = '\0'; + } + var_array[s[0] - 'A'] = atof(tmp); + break; + case '+': + push(pop() + pop()); + break; + case '*': + push(pop() * pop()); + break; + case '-': + op2 = pop(); + push(pop() - op2); + break; + case '/': + op2 = pop(); + if (op2 != 0.0){ + push(pop() / op2); + } else { + printf("Error: Divide by zero.\n"); + } + break; + case '%': + op3 = (int) pop(); + push((int) pop() % op3); + break; + case 'c': + if (clear()) { + printf("Stack Cleared.\n"); + } + break; + case 'p': + if ((topd = top()) != 0) { + printf("Top stack element: %g", topd); + printf(" of %d elements.\n", elem()); + } + break; + case 's': + if (swap()) { + printf("Swap successful.\n"); + } + break; + case 'd': + if (dup()) { + printf("Duplication is successful.\n"); + } else { + printf("Error: Stack empty.\n"); + } + break; + case 'r': + sprnt(); + break; + case 'o': + if (elem() < 2) { + printf("Error: pow requires at least two "); + printf("items on the stack.\n"); + break; + } + op2 = pop(); + push(pow(op2, pop())); + break; + case 'i': + set_solution(); + push(sin(pop())); + result(); + break; + case 'y': + set_solution(); + push(cos(pop())); + break; + case 't': + set_solution(); + push(tan(pop())); + break; + case 'x': + set_solution(); + push(exp(pop())); + break; + case 'q': + set_solution(); + push(sqrt(pop())); + break; + case 'f': + set_solution(); + push(floor(pop())); + break; + case 'l': + set_solution(); + push(ceil(pop())); + break; + case 'v': + for (i = 0; i < VARMAX; i++) { + if (i < VARMAX-1) { + printf("%c: %10.10G\n", 'A' + i, var_array[i]); + } else { + printf("%c: %10.10G\n", '=', var_array[VARMAX]); + } + } + break; + case 'h': + print_help(); + break; + case '\n': + result(); + break; + default: + if ((type >= 'A' && type <= 'Z') || type == '=') { + if (type != '=') { + push(var_array[type - 'A']); + } else { + push(var_array[VARMAX]); + } + } else { + printf("Error: Unknown command \'%s\'\n", s); + } + break; + + } + } + return 0; +} + +#define MAXVAL 100 /* Maximum depth of val stack. */ +int sp = 0; /* Next free stack position. */ +double val[MAXVAL]; /* Value stack. */ + +void push(double f) +{ + if (sp < MAXVAL) { + val[sp++] = f; + } else { + printf("Error: Stack full, cannot push %g\n", f); + } +} + +double pop(void) +{ + if (sp > 0) { + return val[--sp]; + } else { + printf("Error: Stack empty.\n"); + return 0.0; + } +} + +double top(void) +{ + if (sp > 0) { + return val[sp-1]; + } else { + printf("Error: Stack empty.\n"); + return 0.0; + } +} + +int clear(void) +{ + if (sp > 0) { + while(val[--sp] != '\0'); + sp = 0; + return 1; + } else { + printf("Error: Stack empty.\n"); + return 0; + } +} + +int swap(void) +{ + double sbuf; + if (sp > 0) { + sbuf = val[sp-2]; + val[sp-2] = val[sp-1]; + val[sp-1] = sbuf; + return 1; + } else { + printf("Error: Stack empty.\n"); + return 0; + } +} + +int elem(void) +{ + return sp; +} + +int dup (void) +{ + if (sp > 0) { + sp++; + val[sp] = val[sp-1]; + return 1; + } else { + return 0; + } +} + +void sprnt(void) +{ + int count = 0; + while (count < sp) { + printf("%d:%10.12g\n", count+1, val[count]); + count++; + } +} + +void result(void) +{ + if (sp == 1 && is_first_input != 1) { + printf("Solution: %10.20g\n", val[0]); + var_array[VARMAX] = val[0]; + is_first_input = 0; + clear(); + } +} + +/* + * Opens result() for execution. + * Primarily used with the math functions because they can be used with only + * one stack item. For ex, if "1 i" is entered as the first input, this + * function would allow for a result to be shown and the stack cleared. + */ +void set_solution(void) +{ + if (elem() >= 1) { + is_first_input = 0; + } +} + +int getch(void); +void ungetch(int); + +int getop(char s[]) +{ + int i = 0, c; + while ((s[0] = c = getch()) == ' ' || c == '\t'); + + s[1] = '\0'; + + if (isalpha(c) && c >= 'A' && c <= 'Z') { + /* Collect the variable. */ + for ( ; s[i] != ' ' && s[i] != '\n'; s[++i] = getch()); + s[i] = '\0'; + + if (i > 1) { /* A properly formed variable definition. */ + return VARIABLE; + } else { + return c; + } + } else if (!isdigit(c) && c != '.' && c != '-') { + return c; /* Not a number. */ + } + + if (c == '-') { + if ((c = getch()) == ' ') { + /* If the next char is space, then c is a operator. */ + return c; + } else if (isdigit(c)) { + s[++i] = c; + } + + } + + 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) +{ + return (bufp > 0) ? buf[--bufp] : getchar(); +} + +void ungetch(int c) +{ + if (bufp >= BUFSIZE) { + printf("Ungetch: Too many characters.\n"); + } else { + buf[bufp++] = c; + } +} + +void print_help(void) +{ + printf("The Polish Calculator\n"); + printf("-----------------------------------------------\n"); + printf("-> Enter equations in the form: \"1 1 + 2 5 + *\"\n"); + printf("-> Use \"A=1 B=2 C=3\" to store variables.\n"); + printf("-> Use \"A B C * *\" to use stored variables.\n"); + printf("-----------------------------------------------\n"); + printf(">>> Command Help:\n"); + printf(">>> c: Clear memory.\n"); + printf(">>> p: Print last character.\n"); + printf(">>> s: Swap last two characters.\n"); + printf(">>> d: Duplicate the last input.\n"); + printf(">>> r: Print the entire stack.\n"); + printf(">>> v: Print variable list.\n"); + printf(">>> o: pow(x,y), x^y, x > 0.\n"); + printf(">>> i: sin(x), sine of x.\n"); + printf(">>> y: cos(x), cosine of x.\n"); + printf(">>> t: tan(x), tangent of x.\n"); + printf(">>> x: exp(x), e^x, exponential function.\n"); + printf(">>> q: sqrt(x), x >= 0, square of x.\n"); + printf(">>> f: floor(x), largest integer not greater than x.\n"); + printf(">>> l: ceil(x), smallest integer not less than x.\n"); + printf(">>> =: Access the last successful solution.\n"); + printf(">>> h: Print this help text.\n"); +} diff --git a/c_programming/ex_4-07_ungets.c b/c_programming/ex_4-07_ungets.c new file mode 100644 index 0000000..50c202c --- /dev/null +++ b/c_programming/ex_4-07_ungets.c @@ -0,0 +1,85 @@ +/* + * ex_4-07_ungets.c -- Ex KnR book + * + * 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 ? + * + * Written by Harold André + * E-mail + * + * Started on Fri Oct 25 13:59:38 2013 Harold André + * Last update Fri Oct 25 14:09:44 2013 Harold André + * + * gcc -Wall -o ex_4-07_ungets ex_4-07_ungets.c -lm + * + */ + +/* Solution by Steven Huang */ + +#include +#include + +#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 characters\n"); + else + buf[bufp++] = c; +} + +/* + ungets() actually takes a little bit of thought. Should the + first character in "s" be sent to ungetch() first, or should + it be sent last? I assumed that most code calling getch() + would be of this form: + + char array[...]; + int i; + + while (...) { + array[i++] = getch(); + } + + In such cases, the same code might call ungets() as: + + ungets(array); + + and expect to repeat the while loop to get the same string + back. This requires that the last character be sent first + to ungetch() first, because getch() and ungetch() work with + a stack. + + To answer K&R2's additional question for this problem, + it's usually preferable for something like ungets() to just + build itself on top of ungetch(). This allows us to change + ungetch() and getch() in the future, perhaps to use a linked + list instead, without affecting ungets(). +*/ +void ungets(const char *s) +{ + size_t i = strlen(s); + + while (i > 0) + ungetch(s[--i]); +} + +int main(void) +{ + char *s = "hello, world. this is a test."; + int c; + + ungets(s); + while ((c = getch()) != EOF) + putchar(c); + return 0; +} diff --git a/c_programming/ex_4-08_ungetch_v2.c b/c_programming/ex_4-08_ungetch_v2.c new file mode 100644 index 0000000..973835c --- /dev/null +++ b/c_programming/ex_4-08_ungetch_v2.c @@ -0,0 +1,57 @@ +/* + * ex_4-08_ungetch_v2.c -- Ex KnR book + * + * Suppose that there will never be more than one character of pushback. + * Modify getch and ungetch accordingly. + * + * Written by Harold André + * E-mail + * + * Started on Fri Oct 25 14:19:52 2013 Harold André + * Last update Fri Oct 25 14:39:56 2013 Harold André + * + * gcc -Wall -o ex_4-08_ungetch_v2 ex_4-08_ungetch_v2.c -lm + * + */ + + +#include +#include + +int getch(void); +void ungetch(int); + +int main(void) +{ + char *s = "hello, world. this is a test."; + int c; + int i = 0; + + while (s[i] != '\0') + ungetch(s[i++]); + + while ((c = getch()) != EOF) + putchar(c); + + return 0; +} + + +int buf = -1; /* the unget char */ + +int getch(void) /* get a (possibly pushed back) character */ +{ + int tmp = -1; + + if (buf != -1) { + tmp = buf; + buf = -1; + } + + return (tmp != -1) ? tmp : getchar(); +} + +void ungetch(int c) /* push character back on input */ +{ + buf = c; +} diff --git a/c_programming/ex_4-09_ungetch_EOF.c b/c_programming/ex_4-09_ungetch_EOF.c new file mode 100644 index 0000000..50480bd --- /dev/null +++ b/c_programming/ex_4-09_ungetch_EOF.c @@ -0,0 +1,58 @@ +/* + * ex_4-09_ungetch_EOF.c -- Ex KnR book + * + * 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. + * + * Written by Harold André + * E-mail + * + * Started on Fri Oct 25 14:41:47 2013 Harold André + * Last update Fri Oct 25 17:34:53 2013 Harold André + * + * gcc -Wall -o ex_4-09_ungetch_EOF ex_4-09_ungetch_EOF.c -lm + * + */ + + +#include +#include + +int getch(void); +void ungetch(int); + +int main(void) +{ + // char *s = "hello, world. this is a test."; + int c; + //int i = 0; + + //while (s[i] != '\0') + // ungetch(s[i++]); + + while ((c = getch())) + putchar(c); + + return 0; +} + +#define BUFSIZE 100 + +/* use int type for buf array to handle EOF + * Because EOF is frequently -1 and convesion to char result to 1 */ +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 characters\n"); + else + buf[bufp++] = c; +} diff --git a/c_programming/ex_4-10_getline.c b/c_programming/ex_4-10_getline.c new file mode 100644 index 0000000..5779e3a --- /dev/null +++ b/c_programming/ex_4-10_getline.c @@ -0,0 +1,285 @@ +/* + * ex_4-10_getline.c -- Ex KnR book + * + * An alternate organization uses getline to read an entire input line; + * this makes getch and ungetch unnecessary. + * Revise the calculator to use this approach. + * + * Written by Harold André + * E-mail + * + * Started on Fri Oct 25 17:43:07 2013 Harold André + * Last update Fri Oct 25 17:46:24 2013 Harold André + * + * gcc -Wall -o ex_4-10_getline ex_4-10_getline.c -lm + * + */ + +#include +#include /* for atof() - in K&R, math.h is referenced - this is an anachronism */ +#include /* for sin(), exp(), pow() */ +#include /* for strcmp() */ + +#define MAXOP 100 /* max size of operand or operator */ +#define NUMBER '0' /* signal that a number was found */ +#define IDENTIFIER 1 + +//#define DEBUG + +int getop(char []); +void push(double); +double pop(void); +void print(void); +void dup(void); +void swap(void); +void clear(void); +void dealWithName(char []); + +/* reverse Polish calculator */ + +int main(void) +{ + int type; + double op2; + char s[MAXOP]; + + while((type = getop(s)) != EOF) + { + switch(type) + { + case NUMBER: +#ifdef DEBUG + printf("NUMBER string = %s, NUMBER convert to float = %f\n",s, atof(s)); +#endif + push(atof(s)); + break; + case IDENTIFIER: +#ifdef DEBUG + printf("Operator IDENTIFIER receive\n"); +#endif + dealWithName(s); + break; + case '+': +#ifdef DEBUG + printf("Operator '+' receive\n"); +#endif + push(pop() + pop()); + break; + case '*': +#ifdef DEBUG + printf("Operator '*' receive\n"); +#endif + push(pop() * pop()); + break; + case '-': +#ifdef DEBUG + printf("Operator '-' receive\n"); +#endif + op2 = pop(); + push(pop() - op2); + break; + case '/': +#ifdef DEBUG + printf("Operator '/' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + push(pop() / op2); + else + printf("error: zero divisor\n"); + break; + case '%': +#ifdef DEBUG + printf("Operator '%%' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + /* % don't work with double or float type */ + /* we could use fmod instead */ + push((int)pop() % (int)op2); + else + printf("error: zero divisor\n"); + break; + case '\n': + /* TODO: No pop if stak is empty ?*/ + printf("\t%.8g\n", pop()); + break; + case 'p': + print(); + break; + case 'd': + dup(); + break; + case 's': + swap(); + break; + case 'c': + clear(); + break; + default: + printf("error: unknown command %s\n", s); + break; + } + } + + return 0; +} + +#define MAXVAL 100 /* maximum depth of val stack */ + +int sp = 0; /* next free stack position */ +double val[MAXVAL]; /* value stack */ + +/* push: push f onto 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; + } +} + +/* print: print the top element of the stack without popping */ +void print(void) +{ + printf("sp = %d\n", sp); + if (sp > 0) + printf("%e, %f, %g\n", val[sp-1], val[sp-1], val[sp-1]); + else + printf("Stack empty\n"); +} + +/* dup: duplicate the top element of the stack */ +void dup(void) +{ + if (sp > 0) { + val[sp] = val[sp-1]; + sp++; + } else { + printf("error: stack empty, can't duplicate"); + } +} + +/* swap: swap the top two elements of the stack */ +void swap(void) +{ + /* TODO: improve it without temp*/ + double temp; + + if (sp > 1) { + temp = val[sp-1]; + val[sp-1] = val[sp-2]; + val[sp-2] = temp; + } else { + printf("error: stack hold less than two elements, can't swap"); + } +} + +/* clear: clear the stack */ +void clear(void) +{ + sp = 0; +} + +/* deal with a string/name this may be either a maths function + or for future exercices: a variable */ +void dealWithName(char s[]) +{ + double op2; + + if (0 == strcmp(s, "sin")) + push(sin(pop())); + else if (0 == strcmp(s, "exp")) + push(exp(pop())); + else if (0 == strcmp(s, "pow")) { + op2 = pop(); + push(pow(pop(), op2)); + } + else + printf("%s is not a supported function.\n", s); +} + +#include + +int getch(void); +void ungetch(int); + +/* getop: get next operator or numeric operand */ +int getop(char s[]) +{ + int i, c; + + /* ignore space and tabulation characters */ + while((s[0] = c = getch()) == ' ' || c == '\t') + ; + + s[1] = '\0'; /* useless ??? why this line, avoid security whole ? */ + + if (isalpha(c)) { + i = 0; + while (isalpha(s[i++] = c)) + c = getch(); + s[i - 1] = '\0'; + if (c != EOF) + ungetch(c); + return IDENTIFIER; + } + + if (!isdigit(c) && c != '.' && c != '-') + return c; /* not a number */ + + i = 0; + /* a minus immediatly follow by a number is a negative number + otherwise is minus operator */ + if (s[0] == '-') { + c = getch(); + if (!isdigit(c) && c != '.') { + if(c != EOF) + ungetch(c); + return s[0]; + } else { + s[++i] = c; + } + } + + 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 characters\n"); + else + buf[bufp++] = c; +} diff --git a/c_programming/ex_4-11_static.c b/c_programming/ex_4-11_static.c new file mode 100644 index 0000000..5031379 --- /dev/null +++ b/c_programming/ex_4-11_static.c @@ -0,0 +1,297 @@ +/* + * ex_4-11_static.c -- Ex KnR book + * + * Modify getop so that it doesn't need to use ungetch. + * Hint: use an internal static variable. + * + * Written by Harold André + * E-mail + * + * Started on Sat Oct 26 11:55:57 2013 Harold André + * Last update Sat Oct 26 13:48:52 2013 Harold André + * + * gcc -Wall -o ex_4-11_static ex_4-11_static.c -lm + * + */ + +#include +#include /* for atof() - in K&R, math.h is referenced - this is an anachronism */ +#include /* for sin(), exp(), pow() */ +#include /* for strcmp() */ + +#define MAXOP 100 /* max size of operand or operator */ +#define NUMBER '0' /* signal that a number was found */ +#define IDENTIFIER 1 + +//#define DEBUG + +int getop(char []); +void push(double); +double pop(void); +void print(void); +void mydup(void); +void swap(void); +void clear(void); +void dealWithName(char []); + +/* reverse Polish calculator */ + +int main(void) +{ + int type; + double op2; + char s[MAXOP]; + + while((type = getop(s)) != EOF) + { + switch(type) + { + case NUMBER: +#ifdef DEBUG + printf("NUMBER string = %s, NUMBER convert to float = %f\n",s, atof(s)); +#endif + push(atof(s)); + break; + case IDENTIFIER: +#ifdef DEBUG + printf("Operator IDENTIFIER receive\n"); +#endif + dealWithName(s); + break; + case '+': +#ifdef DEBUG + printf("Operator '+' receive\n"); +#endif + push(pop() + pop()); + break; + case '*': +#ifdef DEBUG + printf("Operator '*' receive\n"); +#endif + push(pop() * pop()); + break; + case '-': +#ifdef DEBUG + printf("Operator '-' receive\n"); +#endif + op2 = pop(); + push(pop() - op2); + break; + case '/': +#ifdef DEBUG + printf("Operator '/' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + push(pop() / op2); + else + printf("error: zero divisor\n"); + break; + case '%': +#ifdef DEBUG + printf("Operator '%%' receive\n"); +#endif + op2 = pop(); + if(op2 != 0.0) + /* % don't work with double or float type */ + /* we could use fmod instead */ + push((int)pop() % (int)op2); + else + printf("error: zero divisor\n"); + break; + case '\n': + /* TODO: No pop if stak is empty ?*/ + printf("\t%.8g\n", pop()); + break; + case 'p': + print(); + break; + case 'd': + mydup(); + break; + case 's': + swap(); + break; + case 'c': + clear(); + break; + default: + printf("error: unknown command %s\n", s); + break; + } + } + + return 0; +} + +#define MAXVAL 100 /* maximum depth of val stack */ + +int sp = 0; /* next free stack position */ +double val[MAXVAL]; /* value stack */ + +/* push: push f onto 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; + } +} + +/* print: print the top element of the stack without popping */ +void print(void) +{ + printf("sp = %d\n", sp); + if (sp > 0) + printf("%e, %f, %g\n", val[sp-1], val[sp-1], val[sp-1]); + else + printf("Stack empty\n"); +} + +/* mydup: duplicate the top element of the stack */ +void mydup(void) +{ + if (sp > 0) { + val[sp] = val[sp-1]; + sp++; + } else { + printf("error: stack empty, can't duplicate"); + } +} + +/* swap: swap the top two elements of the stack */ +void swap(void) +{ + /* TODO: improve it without temp*/ + double temp; + + if (sp > 1) { + temp = val[sp-1]; + val[sp-1] = val[sp-2]; + val[sp-2] = temp; + } else { + printf("error: stack hold less than two elements, can't swap"); + } +} + +/* clear: clear the stack */ +void clear(void) +{ + sp = 0; +} + +/* deal with a string/name this may be either a maths function + or for future exercices: a variable */ +void dealWithName(char s[]) +{ + double op2; + + if (0 == strcmp(s, "sin")) + push(sin(pop())); + else if (0 == strcmp(s, "exp")) + push(exp(pop())); + else if (0 == strcmp(s, "pow")) { + op2 = pop(); + push(pow(pop(), op2)); + } + else + printf("%s is not a supported function.\n", s); +} + +#include +#include + +int getch(void); +/* void ungetch(int); */ + +/* getop: get next operator or numeric operand */ +int getop(char s[]) +{ + int i; + /* static variable initialization is only 1 time */ + static int ch_used = 0; /* 1: c has been used, 0: not yet */ + static int c = EOF; + + if (c != EOF && c != ' ' && c != '\t' && ch_used != 1) { + s[0] = c; + } + else { + /* ignore space and tabulation characters */ + while((s[0] = c = getch()) == ' ' || c == '\t') + ; + ch_used = 0; + } + s[1] = '\0'; /* useless ??? why this line, avoid security whole ? */ + /* This is the null terminated C string... ? Why I have ask myself about that !!!! */ + +#ifdef DEBUG + printf("getop: c = '%c'\n", c); + sleep(1); +#endif + + if (isalpha(c)) { + i = 0; + while (isalpha(s[i++] = c)) + c = getch(); + s[i - 1] = '\0'; + return IDENTIFIER; + } + + if (!isdigit(c) && c != '.' && c != '-') { + ch_used = 1; + return c; /* not a number */ + } + + i = 0; + /* a minus immediatly follow by a number is a negative number + otherwise is minus operator */ + if (s[0] == '-') { + c = getch(); + if (!isdigit(c) && c != '.') { + return s[0]; + } else { + s[++i] = c; + } + } + + 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'; + 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(); +} + +#ifdef NOTDEF +void ungetch(int c) /* push character back on input */ +{ + if(bufp >= BUFSIZE) + printf("ungetch: too many characters\n"); + else + buf[bufp++] = c; +} +#endif diff --git a/c_programming/ex_4-12_recursive_itoa.c b/c_programming/ex_4-12_recursive_itoa.c new file mode 100644 index 0000000..2405ff8 --- /dev/null +++ b/c_programming/ex_4-12_recursive_itoa.c @@ -0,0 +1,75 @@ +/* + * ex_4-12_recursive_itoa.c -- Ex KnR book + * + * 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. + * + * Written by Harold André + * E-mail + * + * Started on Sat Oct 26 12:47:50 2013 Harold André + * Last update Sat Oct 26 14:10:05 2013 Harold André + * + * gcc -Wall -o ex_4-12_recursive_itoa ex_4-12_recursive_itoa.c + * + */ + + +#include + +#define MAXCHAR 100 +char ascii_int[MAXCHAR]; + +/* printd: print n in decimal */ +void printd(int); +/* itoa: convert integer to string */ +void itoa(int, char []); + +int main(void) +{ + int i = 12345678; + + printd(i); + + itoa(i, ascii_int); + + printf("\nitoa: decimal: %d -> string: %s\n", i, ascii_int); + + i = 987; + + itoa(i, ascii_int); + + printf("\nitoa: decimal: %d -> string: %s\n", i, ascii_int); + + return 0; +} + +/* printd: print n in decimal */ +void printd(int n) +{ + if (n < 0) { + putchar('-'); + n = -n; + } + if (n / 10) + printd(n / 10); + putchar(n % 10 + '0'); +} + +void itoa(int n, char s[]) +{ + static int i; /* static variable is initialized with 0 by convention */ + + if (n < 0) { + s[i++] = '-'; + n = -n; + } + + if (n / 10) + itoa(n / 10, s); + else + i = 0; + s[i++] = (n % 10 + '0'); + + s[i] = '\0'; +} diff --git a/c_programming/ex_4-13_recursive_reverse.c b/c_programming/ex_4-13_recursive_reverse.c new file mode 100644 index 0000000..7981777 --- /dev/null +++ b/c_programming/ex_4-13_recursive_reverse.c @@ -0,0 +1,77 @@ +/* + * ex_4-13_recursive_reverse.c -- Ex KnR book + * + * Write a recursive version of the function reverse(s), + * which reverses the string s in place. + * + * Written by Harold André + * E-mail + * + * Started on Sat Oct 26 13:46:40 2013 Harold André + * Last update Sat Oct 26 16:06:36 2013 Harold André + * + * gcc -Wall -o ex_4-13_recursive_reverse ex_4-13_recursive_reverse.c + * + */ + +#include +#include + +void reverse(char []); +void reverse2(char []); + +int main(void) +{ + char string[] = "voiture"; + + printf("Original string: %s\n", string); + + reverse2(string); + + printf("Reversed string: %s\n", string); + + reverse(string); + + printf("Twice reversed string: %s\n", string); + + return 0; +} + +/* reverse: reverse string s in place */ +void reverse(char s[]) +{ + char tmp; + static int i; + + tmp = s[i]; + s[i] = s[strlen(s) - (i+1)]; + s[strlen(s) - (i+1)] = tmp; + + if((strlen(s) - i) > ((strlen(s) / 2) +1)) { + i++; + reverse(s); + } + + printf("reverse - i: %d, s: %s\n", i, s); + +} + +/* Sander Goos solution + * http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_4:Exercise_13 + */ +void reverse2(char s[]) +{ + static int i, n; + int c = s[i]; + + if (c) { + i++; + reverse2(s); + s[n-i] = c; + i--; + } else { + n = i; + } + + printf("reverse2 - i: %d, s: %s\n", i, s); +} diff --git a/c_programming/ex_4-14_macro_swap.c b/c_programming/ex_4-14_macro_swap.c new file mode 100644 index 0000000..dab122c --- /dev/null +++ b/c_programming/ex_4-14_macro_swap.c @@ -0,0 +1,49 @@ +/* + * ex_4-14_macro_swap.c -- Ex KnR book + * + * Define a macro swap(t,x,y) that interchanges two arguments of type t. + * (Block structure will help.) + * + * Written by Harold André + * E-mail + * + * Started on Sun Oct 27 00:14:44 2013 Harold André + * Last update Sun Oct 27 00:50:45 2013 Harold André + * + * gcc -Wall -o ex_4-14_macro_swap ex_4-14_macro_swap.c + * + * See the result after preprocess only: + * gcc -Wall -E ex_4-14_macro_swap.c -o ex_4-14_macro_swap.i + * + */ + +#include + +#define swap(t,x,y) { t _z; \ + _z = x; \ + x = y; \ + y = _z; } + + +int main(void) +{ + int i = 12; + int j = 68; + + { + int i = 8; + printf("i = %d\n", i); + { + int i = 34; + printf("i = %d\n", i); + } + } + + printf("Before swap: i = %d, j = %d\n", i, j); + + swap(int, i, j); + + printf("After swap: i = %d, j = %d\n", i, j); + + return 0; +} diff --git a/c_programming/ex_4-14_macro_swap.i b/c_programming/ex_4-14_macro_swap.i new file mode 100644 index 0000000..3f94558 --- /dev/null +++ b/c_programming/ex_4-14_macro_swap.i @@ -0,0 +1,877 @@ +# 1 "ex_4-14_macro_swap.c" +# 1 "" +# 1 "ex_4-14_macro_swap.c" +# 17 "ex_4-14_macro_swap.c" +# 1 "/usr/include/stdio.h" 1 3 4 +# 28 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/features.h" 1 3 4 +# 323 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/predefs.h" 1 3 4 +# 324 "/usr/include/features.h" 2 3 4 +# 356 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4 +# 359 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 360 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4 +# 357 "/usr/include/features.h" 2 3 4 +# 388 "/usr/include/features.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4 + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 5 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 + + + + +# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4 +# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4 +# 389 "/usr/include/features.h" 2 3 4 +# 29 "/usr/include/stdio.h" 2 3 4 + + + + + +# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h" 1 3 4 +# 213 "/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h" 3 4 +typedef long unsigned int size_t; +# 35 "/usr/include/stdio.h" 2 3 4 + +# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4 +# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4 +# 29 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; + + +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; + +typedef signed long int __int64_t; +typedef unsigned long int __uint64_t; + + + + + + + +typedef long int __quad_t; +typedef unsigned long int __u_quad_t; +# 131 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4 +# 132 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4 + + +typedef unsigned long int __dev_t; +typedef unsigned int __uid_t; +typedef unsigned int __gid_t; +typedef unsigned long int __ino_t; +typedef unsigned long int __ino64_t; +typedef unsigned int __mode_t; +typedef unsigned long int __nlink_t; +typedef long int __off_t; +typedef long int __off64_t; +typedef int __pid_t; +typedef struct { int __val[2]; } __fsid_t; +typedef long int __clock_t; +typedef unsigned long int __rlim_t; +typedef unsigned long int __rlim64_t; +typedef unsigned int __id_t; +typedef long int __time_t; +typedef unsigned int __useconds_t; +typedef long int __suseconds_t; + +typedef int __daddr_t; +typedef long int __swblk_t; +typedef int __key_t; + + +typedef int __clockid_t; + + +typedef void * __timer_t; + + +typedef long int __blksize_t; + + + + +typedef long int __blkcnt_t; +typedef long int __blkcnt64_t; + + +typedef unsigned long int __fsblkcnt_t; +typedef unsigned long int __fsblkcnt64_t; + + +typedef unsigned long int __fsfilcnt_t; +typedef unsigned long int __fsfilcnt64_t; + +typedef long int __ssize_t; + + + +typedef __off64_t __loff_t; +typedef __quad_t *__qaddr_t; +typedef char *__caddr_t; + + +typedef long int __intptr_t; + + +typedef unsigned int __socklen_t; +# 37 "/usr/include/stdio.h" 2 3 4 +# 45 "/usr/include/stdio.h" 3 4 +struct _IO_FILE; + + + +typedef struct _IO_FILE FILE; + + + + + +# 65 "/usr/include/stdio.h" 3 4 +typedef struct _IO_FILE __FILE; +# 75 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/libio.h" 1 3 4 +# 32 "/usr/include/libio.h" 3 4 +# 1 "/usr/include/_G_config.h" 1 3 4 +# 15 "/usr/include/_G_config.h" 3 4 +# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h" 1 3 4 +# 16 "/usr/include/_G_config.h" 2 3 4 + + + + +# 1 "/usr/include/wchar.h" 1 3 4 +# 83 "/usr/include/wchar.h" 3 4 +typedef struct +{ + int __count; + union + { + + unsigned int __wch; + + + + char __wchb[4]; + } __value; +} __mbstate_t; +# 21 "/usr/include/_G_config.h" 2 3 4 + +typedef struct +{ + __off_t __pos; + __mbstate_t __state; +} _G_fpos_t; +typedef struct +{ + __off64_t __pos; + __mbstate_t __state; +} _G_fpos64_t; +# 53 "/usr/include/_G_config.h" 3 4 +typedef int _G_int16_t __attribute__ ((__mode__ (__HI__))); +typedef int _G_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__))); +# 33 "/usr/include/libio.h" 2 3 4 +# 53 "/usr/include/libio.h" 3 4 +# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h" 1 3 4 +# 40 "/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h" 3 4 +typedef __builtin_va_list __gnuc_va_list; +# 54 "/usr/include/libio.h" 2 3 4 +# 170 "/usr/include/libio.h" 3 4 +struct _IO_jump_t; struct _IO_FILE; +# 180 "/usr/include/libio.h" 3 4 +typedef void _IO_lock_t; + + + + + +struct _IO_marker { + struct _IO_marker *_next; + struct _IO_FILE *_sbuf; + + + + int _pos; +# 203 "/usr/include/libio.h" 3 4 +}; + + +enum __codecvt_result +{ + __codecvt_ok, + __codecvt_partial, + __codecvt_error, + __codecvt_noconv +}; +# 271 "/usr/include/libio.h" 3 4 +struct _IO_FILE { + int _flags; + + + + + char* _IO_read_ptr; + char* _IO_read_end; + char* _IO_read_base; + char* _IO_write_base; + char* _IO_write_ptr; + char* _IO_write_end; + char* _IO_buf_base; + char* _IO_buf_end; + + char *_IO_save_base; + char *_IO_backup_base; + char *_IO_save_end; + + struct _IO_marker *_markers; + + struct _IO_FILE *_chain; + + int _fileno; + + + + int _flags2; + + __off_t _old_offset; + + + + unsigned short _cur_column; + signed char _vtable_offset; + char _shortbuf[1]; + + + + _IO_lock_t *_lock; +# 319 "/usr/include/libio.h" 3 4 + __off64_t _offset; +# 328 "/usr/include/libio.h" 3 4 + void *__pad1; + void *__pad2; + void *__pad3; + void *__pad4; + size_t __pad5; + + int _mode; + + char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; + +}; + + +typedef struct _IO_FILE _IO_FILE; + + +struct _IO_FILE_plus; + +extern struct _IO_FILE_plus _IO_2_1_stdin_; +extern struct _IO_FILE_plus _IO_2_1_stdout_; +extern struct _IO_FILE_plus _IO_2_1_stderr_; +# 364 "/usr/include/libio.h" 3 4 +typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes); + + + + + + + +typedef __ssize_t __io_write_fn (void *__cookie, __const char *__buf, + size_t __n); + + + + + + + +typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w); + + +typedef int __io_close_fn (void *__cookie); +# 416 "/usr/include/libio.h" 3 4 +extern int __underflow (_IO_FILE *); +extern int __uflow (_IO_FILE *); +extern int __overflow (_IO_FILE *, int); +# 460 "/usr/include/libio.h" 3 4 +extern int _IO_getc (_IO_FILE *__fp); +extern int _IO_putc (int __c, _IO_FILE *__fp); +extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__)); +extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__)); + +extern int _IO_peekc_locked (_IO_FILE *__fp); + + + + + +extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__)); +extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__)); +extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__)); +# 490 "/usr/include/libio.h" 3 4 +extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict, + __gnuc_va_list, int *__restrict); +extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict, + __gnuc_va_list); +extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t); +extern size_t _IO_sgetn (_IO_FILE *, void *, size_t); + +extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int); +extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int); + +extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__)); +# 76 "/usr/include/stdio.h" 2 3 4 + + + + +typedef __gnuc_va_list va_list; +# 91 "/usr/include/stdio.h" 3 4 +typedef __off_t off_t; +# 103 "/usr/include/stdio.h" 3 4 +typedef __ssize_t ssize_t; + + + + + + + +typedef _G_fpos_t fpos_t; + + + + +# 161 "/usr/include/stdio.h" 3 4 +# 1 "/usr/include/x86_64-linux-gnu/bits/stdio_lim.h" 1 3 4 +# 162 "/usr/include/stdio.h" 2 3 4 + + + +extern struct _IO_FILE *stdin; +extern struct _IO_FILE *stdout; +extern struct _IO_FILE *stderr; + + + + + + + +extern int remove (__const char *__filename) __attribute__ ((__nothrow__)); + +extern int rename (__const char *__old, __const char *__new) __attribute__ ((__nothrow__)); + + + + +extern int renameat (int __oldfd, __const char *__old, int __newfd, + __const char *__new) __attribute__ ((__nothrow__)); + + + + + + + + +extern FILE *tmpfile (void) ; +# 206 "/usr/include/stdio.h" 3 4 +extern char *tmpnam (char *__s) __attribute__ ((__nothrow__)) ; + + + + + +extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__)) ; +# 224 "/usr/include/stdio.h" 3 4 +extern char *tempnam (__const char *__dir, __const char *__pfx) + __attribute__ ((__nothrow__)) __attribute__ ((__malloc__)) ; + + + + + + + + +extern int fclose (FILE *__stream); + + + + +extern int fflush (FILE *__stream); + +# 249 "/usr/include/stdio.h" 3 4 +extern int fflush_unlocked (FILE *__stream); +# 263 "/usr/include/stdio.h" 3 4 + + + + + + +extern FILE *fopen (__const char *__restrict __filename, + __const char *__restrict __modes) ; + + + + +extern FILE *freopen (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream) ; +# 292 "/usr/include/stdio.h" 3 4 + +# 303 "/usr/include/stdio.h" 3 4 +extern FILE *fdopen (int __fd, __const char *__modes) __attribute__ ((__nothrow__)) ; +# 316 "/usr/include/stdio.h" 3 4 +extern FILE *fmemopen (void *__s, size_t __len, __const char *__modes) + __attribute__ ((__nothrow__)) ; + + + + +extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__)) ; + + + + + + +extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__)); + + + +extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, + int __modes, size_t __n) __attribute__ ((__nothrow__)); + + + + + +extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, + size_t __size) __attribute__ ((__nothrow__)); + + +extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__)); + + + + + + + + +extern int fprintf (FILE *__restrict __stream, + __const char *__restrict __format, ...); + + + + +extern int printf (__const char *__restrict __format, ...); + +extern int sprintf (char *__restrict __s, + __const char *__restrict __format, ...) __attribute__ ((__nothrow__)); + + + + + +extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg); + + + + +extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg); + +extern int vsprintf (char *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) __attribute__ ((__nothrow__)); + + + + + +extern int snprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, ...) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4))); + +extern int vsnprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0))); + +# 414 "/usr/include/stdio.h" 3 4 +extern int vdprintf (int __fd, __const char *__restrict __fmt, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__printf__, 2, 0))); +extern int dprintf (int __fd, __const char *__restrict __fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + + + + + + + + +extern int fscanf (FILE *__restrict __stream, + __const char *__restrict __format, ...) ; + + + + +extern int scanf (__const char *__restrict __format, ...) ; + +extern int sscanf (__const char *__restrict __s, + __const char *__restrict __format, ...) __attribute__ ((__nothrow__)); +# 445 "/usr/include/stdio.h" 3 4 +extern int fscanf (FILE *__restrict __stream, __const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") + + ; +extern int scanf (__const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") + ; +extern int sscanf (__const char *__restrict __s, __const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__)) + + ; +# 465 "/usr/include/stdio.h" 3 4 + + + + + + + + +extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 2, 0))) ; + + + + + +extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 1, 0))) ; + + +extern int vsscanf (__const char *__restrict __s, + __const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__scanf__, 2, 0))); +# 496 "/usr/include/stdio.h" 3 4 +extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf") + + + + __attribute__ ((__format__ (__scanf__, 2, 0))) ; +extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf") + + __attribute__ ((__format__ (__scanf__, 1, 0))) ; +extern int vsscanf (__const char *__restrict __s, __const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__)) + + + + __attribute__ ((__format__ (__scanf__, 2, 0))); +# 524 "/usr/include/stdio.h" 3 4 + + + + + + + + + +extern int fgetc (FILE *__stream); +extern int getc (FILE *__stream); + + + + + +extern int getchar (void); + +# 552 "/usr/include/stdio.h" 3 4 +extern int getc_unlocked (FILE *__stream); +extern int getchar_unlocked (void); +# 563 "/usr/include/stdio.h" 3 4 +extern int fgetc_unlocked (FILE *__stream); + + + + + + + + + + + +extern int fputc (int __c, FILE *__stream); +extern int putc (int __c, FILE *__stream); + + + + + +extern int putchar (int __c); + +# 596 "/usr/include/stdio.h" 3 4 +extern int fputc_unlocked (int __c, FILE *__stream); + + + + + + + +extern int putc_unlocked (int __c, FILE *__stream); +extern int putchar_unlocked (int __c); + + + + + + +extern int getw (FILE *__stream); + + +extern int putw (int __w, FILE *__stream); + + + + + + + + +extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + ; + + + + + + +extern char *gets (char *__s) ; + +# 658 "/usr/include/stdio.h" 3 4 +extern __ssize_t __getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; +extern __ssize_t getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) ; + + + + + + + +extern __ssize_t getline (char **__restrict __lineptr, + size_t *__restrict __n, + FILE *__restrict __stream) ; + + + + + + + + +extern int fputs (__const char *__restrict __s, FILE *__restrict __stream); + + + + + +extern int puts (__const char *__s); + + + + + + +extern int ungetc (int __c, FILE *__stream); + + + + + + +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; + + + + +extern size_t fwrite (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s); + +# 730 "/usr/include/stdio.h" 3 4 +extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) ; +extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream); + + + + + + + + +extern int fseek (FILE *__stream, long int __off, int __whence); + + + + +extern long int ftell (FILE *__stream) ; + + + + +extern void rewind (FILE *__stream); + +# 766 "/usr/include/stdio.h" 3 4 +extern int fseeko (FILE *__stream, __off_t __off, int __whence); + + + + +extern __off_t ftello (FILE *__stream) ; +# 785 "/usr/include/stdio.h" 3 4 + + + + + + +extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); + + + + +extern int fsetpos (FILE *__stream, __const fpos_t *__pos); +# 808 "/usr/include/stdio.h" 3 4 + +# 817 "/usr/include/stdio.h" 3 4 + + +extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__)); + +extern int feof (FILE *__stream) __attribute__ ((__nothrow__)) ; + +extern int ferror (FILE *__stream) __attribute__ ((__nothrow__)) ; + + + + +extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__)); +extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ; +extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ; + + + + + + + + +extern void perror (__const char *__s); + + + + + + +# 1 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 1 3 4 +# 27 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 3 4 +extern int sys_nerr; +extern __const char *__const sys_errlist[]; +# 847 "/usr/include/stdio.h" 2 3 4 + + + + +extern int fileno (FILE *__stream) __attribute__ ((__nothrow__)) ; + + + + +extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ; +# 866 "/usr/include/stdio.h" 3 4 +extern FILE *popen (__const char *__command, __const char *__modes) ; + + + + + +extern int pclose (FILE *__stream); + + + + + +extern char *ctermid (char *__s) __attribute__ ((__nothrow__)); +# 906 "/usr/include/stdio.h" 3 4 +extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__)); + + + +extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ; + + +extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__)); +# 936 "/usr/include/stdio.h" 3 4 + +# 18 "ex_4-14_macro_swap.c" 2 + + + + + + +int main(void) +{ + int i = 12; + int j = 68; + + { + int i = 8; + printf("i = %d\n", i); + { + int i = 34; + printf("i = %d\n", i); + } + } + + printf("Before swap: i = %d, j = %d\n", i, j); + + { int _z; _z = i; i = j; j = _z; }; + + printf("After swap: i = %d, j = %d\n", i, j); + + return 0; +} diff --git a/c_programming/ex_5-01-02_pointers-arrays.c b/c_programming/ex_5-01-02_pointers-arrays.c new file mode 100644 index 0000000..62c8190 --- /dev/null +++ b/c_programming/ex_5-01-02_pointers-arrays.c @@ -0,0 +1,144 @@ +/* + * ex_5-01-02_pointers-arrays.c -- Ex KnR book + * + * Ex 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. + * Ex 5.2 + * Write getfloat , the floating-point analog of getint. + * What type does getfloat return as its function value? + * + * Written by Harold André + * E-mail + * + * Started on Sun Oct 27 00:14:44 2013 Harold André + * Last update Sun Nov 10 12:27:56 2013 Harold André + * + * gcc -Wall -o ex_5-01-02_pointers-arrays ex_5-01-02_pointers-arrays.c + * + * + */ + +#include +#include + +//#define DEBUG + +#define SIZE 10 + +int getch(void); +void ungetch(int); +int getint(int *); +int getfloat(float *); + +int main(void) +{ + int n; + /* int array[SIZE], intrvalue; */ + float floatarray[SIZE], floatrvalue; + /* + for (n = 0; n < SIZE && (intrvalue = getint(&array[n])) != EOF; n++) + printf("Integer from input: %d, return value: %d\n", array[n], intrvalue); + */ + for (n = 0; n < SIZE && (floatrvalue = getfloat(&floatarray[n])) != EOF; n++) + printf("Float from input: %g, return value: %f\n", floatarray[n], floatrvalue); + + return 0; +} + +#define BUFSIZE 100 + +/* use int type for buf array to handle EOF + * Because EOF is frequently -1 and convesion to char result to 1 */ +int buf[BUFSIZE]; /* buffer for ungetch */ +int bufp = 0; /* next free position in buf */ + +int getch(void) /* get a (possibly pushed back) character */ +{ +#if defined(DEBUG) + int c; + + if (bufp > 0) + c = buf[--bufp]; + else + c = getchar(); + + printf("DEBUG: getch - Character read: '%c', ascii value: %d\n", c, c); + + return c; +#endif +#if !defined(DEBUG) + return (bufp > 0) ? buf[--bufp] : getchar(); +#endif +} + +void ungetch(int c) /* push character back on input */ +{ + if(bufp >= BUFSIZE) + printf("ungetch: too many characters\n"); + else + buf[bufp++] = c; +#ifdef DEBUG + printf("DEBUG: ungetch - Push back character: '%c', ascii value: %d\n", c, c); +#endif +} + +/* getint: get next integer from input into *pn */ +int getint(int *pn) +{ + int c, sign; + + while (isspace(c = getch())) /* skip white space */ + ; + if (!isdigit(c) && c != EOF && c != '+' && c != '-') { + ungetch(c); /* it is not a number */ + return 0; + } + sign = (c == '-') ? -1 : 1; + if (c == '+' || c == '-') { + c = getch(); + if (!isdigit(c)) { + ungetch((sign == -1) ? '-' : '+'); + return 0; + } + } + for (*pn = 0; isdigit(c); c = getch()) + *pn = 10 * *pn + (c - '0'); + *pn *= sign; + if (c != EOF) + ungetch(c); + return c; +} + +/* getfloat: get next float from input into *pn */ +int getfloat(float *pn) +{ + int c, sign, power; + + while (isspace(c = getch())) /* skip white space */ + ; + if (!isdigit(c) && c != EOF && c != '+' && c != '-') { + ungetch(c); /* it is not a number */ + return 0; + } + sign = (c == '-') ? -1 : 1; + if (c == '+' || c == '-') { + c = getch(); + if (!isdigit(c)) { + ungetch((sign == -1) ? '-' : '+'); + return 0; + } + } + for (*pn = 0.0; isdigit(c); c = getch()) + *pn = 10.0 * *pn + (c - '0'); + if (c == '.') + c = getch(); + for (power = 1; isdigit(c); c = getch()) { + *pn = 10.0 * *pn + (c - '0'); + power *= 10; + } + *pn = sign * *pn / power; + if (c != EOF) + ungetch(c); + return c; +} diff --git a/c_programming/ex_5-03-06_pointers_characters.c b/c_programming/ex_5-03-06_pointers_characters.c new file mode 100644 index 0000000..da37154 --- /dev/null +++ b/c_programming/ex_5-03-06_pointers_characters.c @@ -0,0 +1,167 @@ +/* + * ex_5-03-06_pointers_characters.c -- Ex KnR book + * + * Ex 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 . + * Ex 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. + * Ex 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. + * Full descriptions are in Appendix B. + * Ex 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). + * + * + * Written by Harold André + * E-mail + * + * Started on Sun Oct 27 00:14:44 2013 Harold André + * Last update Tue Nov 12 14:18:58 2013 Harold André + * + * gcc -Wall -o ex_5-03-06_pointers_characters ex_5-03-06_pointers_characters.c + * + * + */ + +#include + +//#define DEBUG + +#define SIZE 20 + +void my_strcat(char *, char*); +int strend(char *, char *); +void my_strncpy(char *, char *, int); +int my_getline(char line[], int max); +int strindex(char source[], char searchfor[]); + +char pattern[] = "ould"; /* pattern to search for */ + +int main(void) +{ + char array_src[] = "Salut"; + char array_dest[SIZE] = "yo !"; + + char array_1[] = "Salut"; + char array_2[] = "ut"; + + char my_strncpy_array_src[] = "Saluttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt"; + char my_strncpy_array_dest[SIZE] = "ut"; + int n = SIZE - 1; + + char line[SIZE]; + int found = 0; + + my_strcat(array_dest, array_src); + printf("Concatened string: %s\n", array_dest); + + if (strend(array_1, array_2)) + printf("strend: string 2 occurs at the end of string 1.\n"); + else + printf("strend: string 2 does not occurs at the end of string 1.\n"); + + my_strncpy(my_strncpy_array_dest, my_strncpy_array_src, n); + printf("my_strncpy copied at max %d characters of string \"%s\": \"%s\"\n", n, my_strncpy_array_src, my_strncpy_array_dest); + + printf("Looking for pattern \"%s\", enter a line, ^D to quit.\n", pattern); + while (my_getline(line, SIZE) > 0) + if (strindex(line, pattern) >= 0) { + printf("%s", line); + found++; + } + printf("Number of found patterns: %d\n", found); + + return 0; +} + +/* my_strcat: concatenate src to end of dest; dest must be big enough */ +void my_strcat(char *dest, char *src) +{ + while (*dest) + dest++; + while (*dest++ = *src++) + ; +} + +/* strend: return 1 if string t occurs at the end of s */ +int strend(char *s, char *t) +{ + char *start_s = s, *start_t = t; + + while (*s) + s++; + while (*t) + t++; + /* In answer book, the test is executed only once, is better */ + while (t >= start_t) { + if (*s != *t || s < start_s) + return 0; + s--; + t--; + } + return 1; +} + +void my_strncpy(char *dest, char *src, int n) +{ + int i = 0; + + while (*dest++ = *src++) { + i++; /* number of copied character */ + if (i == n) { + *dest = '\0'; + break; + } + } +} + +/* my_getline: get line into s, return length */ +int my_getline(char *s, int lim) +{ + int c; + char *bs = s; /* remember begin of s */ + + while (--lim > 0 && (c=getchar()) != EOF && c != '\n') + *s++ = c; + if (c == '\n') + *s++ = c; + *s = '\0'; + printf("my_getline - length of s: %ld\n", (s - bs - 1)); + return (s - bs - 1); +} + +/* strindex: return index of t in s, -1 if none */ +int strindex(char *s, char *t) +{ + /* + int i, j, k; + for (i = 0; s[i] != '\0'; i++) { + for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++) + ; + if (k > 0 && t[k] == '\0') + return i; + } + */ + + char *index_s = NULL; + char *bs = s; + char *bt = t; + + while (*s++) { + for (index_s = s; *t != '\0' && *index_s == *t; index_s++, t++) + ; + if ((t - bt) > 0 && *t == '\0') { + printf("Index of pattern \"%s\" in string \"%s\": %ld\n", bt, bs, s - bs); + return s - bs; + } + } + return -1; +} diff --git a/c_programming/getopt.c b/c_programming/getopt.c new file mode 100644 index 0000000..436247b --- /dev/null +++ b/c_programming/getopt.c @@ -0,0 +1,166 @@ +/* + * getopt.c -- example of command-line parsing via getopt + * + * Written by Harold André + * E-mail + * + * Started on Sat Jul 13 15:15:02 2013 Harold André + * Last update Mon Jul 15 18:07:57 2013 Harold André + * + * gcc -Wall -o getopt getopt.c + * + */ + +#include +#include +#include +#include + +#define AUTHOR "Harold André" +#define VERSION "1.0" + +/* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +enum +{ + HELP_OPTION = CHAR_MAX + 1, + VERSION_OPTION +}; + +/* global variable debug for the example */ +int debug = 0; + +/* print how display help on failure status, usage and help otherwise */ +void usage(int status, char *program_name) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, "Try \"%s --help\" for more information.\n", + program_name); + else { + printf("Usage: %s [-dmp] -f fname [-s sname] name [name]...\n", + program_name); + fputs ("\ +Short program description, ex: copy file fname to name.\n\ +blah blah blah blah blah.\n\ +\n\ +", stdout); + fputs ("\ +Mandatory arguments to long options are mandatory for short options too.\n\ +", stdout); + fputs ("\ + -d, --debug enable debug mode\n\ + -f, --file NAME file to work on\n\ + -m, --modification-time indicate modification time to blah blah blah\n\ + blah blah\n\ + -p, --preserve-permissions preserve permissions for file\n\ + -s, --second-name NAME copy with the name NAME\n\ +", stdout); + fputs ("\ + --help display this help and exit\n\ + --version output version information and exit\n\ +", stdout); + } + + /* always quit the program after print usage */ + exit(status); +} + +int main(int argc, char *argv[]) +{ + /* when an option take a parameter optarg point on the parameter */ + extern char *optarg; + /* if there are other arguments on the command-line there are not options + optind is an index on this remaining non-option ARGV-elements */ + extern int optind; + int c, option_index=0; + int mflag=0, pflag=0, fflag=0; + char *sname = "default_sname", *fname = NULL; + char *program_name = argv[0]; + + /* informations on longs options: + name, + is argument required or not for the option, + flag, (see man 3 getopt), + value to return when long option is encountered, here return the short + option's character, if exist, corresponding to the long option */ + static struct option long_options[] = { + {"debug", no_argument, NULL, 'd'}, + {"file", required_argument, NULL, 'f'}, + {"modification-time", no_argument, NULL, 'm'}, + {"preserve-permissions", no_argument, NULL, 'p'}, + {"second-name", required_argument, NULL, 's'}, + {"help", no_argument, NULL, HELP_OPTION}, + {"version", no_argument, NULL, VERSION_OPTION}, + {NULL, 0, NULL, 0 } + }; + + /* when all options are parsed, getopt* return -1 + if an option letter is followed by a colon, this option requires + an argument */ + while ((c = getopt_long(argc, argv, "df:mps:", + long_options, &option_index)) != -1) { + switch (c) { + case 'd': + debug = 1; + break; + case 'm': + mflag = 1; + break; + case 'p': + pflag = 1; + break; + case 'f': + fflag = 1; + fname = optarg; + break; + case 's': + sname = optarg; + break; + case HELP_OPTION: + usage(EXIT_SUCCESS, program_name); + break; + case VERSION_OPTION: + printf("%s %s\n", program_name, VERSION); + printf("Written by %s\n", AUTHOR); + exit(EXIT_SUCCESS); + break; + case '?': + default: + usage(EXIT_FAILURE, program_name); + } + } + + if (fflag == 0) { /* -f was mandatory */ + fprintf(stderr, "%s: missing -f option\n", program_name); + usage(EXIT_FAILURE, program_name); + } else if ((optind+1) > argc) { + /* need at least one argument (change +1 to +2 for two, etc. as needeed) */ + printf("optind = %d, argc = %d\n", optind, argc); + fprintf(stderr, "%s: missing name\n", program_name); + usage(EXIT_FAILURE, program_name); + } + + /* see what we have */ + printf("debug = %d\n", debug); + printf("pflag = %d\n", pflag); + printf("mflag = %d\n", mflag); + printf("fname = \"%s\"\n", fname); + printf("sname = \"%s\"\n", sname); + + /* these are the arguments after the command-line options */ + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + if (optind < argc) + for (;optind < argc; optind++) + printf("argument: \"%s\"\n", argv[optind]); + else { + printf("no arguments left to process\n"); + } + + return 0; +} diff --git a/c_programming/signed_char_conversion.c b/c_programming/signed_char_conversion.c new file mode 100644 index 0000000..4e70bb9 --- /dev/null +++ b/c_programming/signed_char_conversion.c @@ -0,0 +1,37 @@ +/* + * signed_char_conversion.c -- conversion error with signed char + * + * Written by Harold André + * E-mail + * + * Started on Wed Jul 10 20:00:42 2013 Harold André + * Last update Sat Jul 13 14:29:22 2013 Harold André + * + * gcc -Wall -o signed_char_conversion signed_char_conversion.c + * + */ + +/* + * when add 1 to 127, c gives -128 and conversion to an unsigned int give + * -128 + UINT_MAX + 1 + * warning: printf convert arguments too... %u, %d... + * + */ + + +#include + +int main(int argc, char *argv[]) +{ + char c; + + c = -1; + + do { + ++c; + printf("c : %u\tc : %u\tc : %u\tc : %d\n", (unsigned int)(unsigned char)c, (unsigned int)c, (unsigned char)c, c); + } + while (c + 1 != 0); + + return 0; +}