├── README.md ├── cap1 ├── exerc_1.1.c ├── exerc_1.10.c ├── exerc_1.12.c ├── exerc_1.13.c ├── exerc_1.14.c ├── exerc_1.15.c ├── exerc_1.16.c ├── exerc_1.17.c ├── exerc_1.18.c ├── exerc_1.19.c ├── exerc_1.2.c ├── exerc_1.20-detab.c ├── exerc_1.21-entab.c ├── exerc_1.3.c ├── exerc_1.4.c ├── exerc_1.5.c ├── exerc_1.6.c ├── exerc_1.7.c ├── exerc_1.8.c └── exerc_1.9.c ├── cap2 ├── exercise_2.1.c ├── exercise_2.10.c ├── exercise_2.2.c ├── exercise_2.3.c ├── exercise_2.4.c ├── exercise_2.5.c ├── exercise_2.6.c ├── exercise_2.7.c ├── exercise_2.8.c └── exercise_2.9.c ├── cap3 ├── exercise_3.1.c ├── exercise_3.2.c ├── exercise_3.3.c ├── exercise_3.4.c ├── exercise_3.5.c └── exercise_3.6.c ├── cap4 ├── exercise.4.1.c ├── exercise.4.10.c ├── exercise.4.11.c ├── exercise.4.12.c ├── exercise.4.13.c ├── exercise.4.14.c ├── exercise.4.2.c ├── exercise.4.3.c ├── exercise.4.4.c ├── exercise.4.5.c ├── exercise.4.6.c ├── exercise.4.7.c ├── exercise.4.8.c └── exercise.4.9.c ├── cap5 ├── dcl.c ├── exercise.5.1.c ├── exercise.5.10.c ├── exercise.5.11-part1.c ├── exercise.5.11-part2.c ├── exercise.5.12.c ├── exercise.5.13.c ├── exercise.5.14.c ├── exercise.5.15.c ├── exercise.5.2.c ├── exercise.5.3.c ├── exercise.5.4.c ├── exercise.5.5.c ├── exercise.5.6.c ├── exercise.5.7.c ├── exercise.5.8.c ├── exercise.5.9.c └── sort.c ├── cap6 ├── exercise.6.1.c ├── exercise.6.2.c ├── exercise.6.3.c ├── exercise.6.4.c ├── exercise.6.5.c └── exercise.6.6.c ├── cap7 ├── exercise7.1.c ├── exercise7.2.c ├── exercise7.3.c ├── exercise7.4.c ├── exercise7.5.c ├── exercise7.6.c ├── exercise7.7.c ├── exercise7.8.c └── exercise7.9.c └── cap8 ├── cat_std_version.c ├── exercise.8.1.c ├── exercise.8.3.c ├── exercise.8.4.c └── fopen.c /README.md: -------------------------------------------------------------------------------- 1 | # KnR_The_C_Programming_Language 2 | 3 | My solutions for the exercises of the book *The C Programming Language (K&R)* 4 | -------------------------------------------------------------------------------- /cap1/exerc_1.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 14:26:21 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | main () 11 | { 12 | printf ("hello, world\n"); 13 | } 14 | -------------------------------------------------------------------------------- /cap1/exerc_1.10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 18:50:44 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercises 1-10: Write a program to copy its input to its output, replacing each tab by \t, each backspace by \b, and 9 | * backslash by \\. This makes tabs and backspaces visible in an unambiguous way 10 | */ 11 | 12 | #include 13 | 14 | main () { 15 | int c; 16 | while ((c = getchar()) != EOF){ 17 | if (c == '\t') 18 | printf ("\\t"); 19 | else if (c == '\b') 20 | printf ("\\b"); 21 | else if (c == '\\') 22 | printf ("\\"); 23 | else 24 | putchar(c); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cap1/exerc_1.12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 19:22:03 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-12. Write a program that prints its input one word per line. */ 9 | 10 | #include 11 | 12 | #define OUT 0 13 | #define IN 1 14 | 15 | main () 16 | { 17 | int c, state; 18 | 19 | state == OUT; 20 | while ((c = getchar()) != EOF){ 21 | if (state == IN){ 22 | if (c == ' ' || c == '\t' || c == '\n'){ 23 | state = OUT; 24 | putchar ('\n'); 25 | } else 26 | putchar(c); 27 | } else { 28 | if (c != ' ' && c != '\t' && c != '\n'){ 29 | state = IN; 30 | putchar(c); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cap1/exerc_1.13.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 20:05:13 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | /* Exercise 1-13. Write a program to print a histogram of the lengths of words in its input. It is 11 | * easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. 12 | */ 13 | main () 14 | { 15 | 16 | int freq[20], c, count, i, j; 17 | 18 | count = 0; 19 | 20 | for (i = 0; i < 20; i++) freq[i] = 0; 21 | 22 | while ((c = getchar()) != EOF) { 23 | if (count == 0) { 24 | if (c != ' ' && c != '\t' && c != '\n') { 25 | count++; 26 | } 27 | } else { 28 | count++; 29 | if (c == ' ' || c == '\t' || c == '\n') { 30 | if (count > 20) 31 | freq[19]++; 32 | else 33 | freq[count - 2]++; 34 | count = 0; 35 | } 36 | } 37 | } 38 | 39 | for (i = 0; i < 19; i++){ 40 | printf ("%02d: ", i + 1); 41 | for (j = 0; j < freq[i]; j++) 42 | putchar('.'); 43 | printf ("%d\n", freq[i]); 44 | } 45 | 46 | printf ("20 or more: "); 47 | for (j = 0; j < freq[19]; j++) 48 | putchar('.'); 49 | printf ("%d\n", freq[19]); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /cap1/exerc_1.14.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 20:30:54 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-14. Write a program to print a histogram of the frequencies of different characters 9 | in its input. */ 10 | 11 | #include 12 | 13 | #define OTHER 26 14 | 15 | main () 16 | { 17 | int freq[27], c, i, j; 18 | 19 | for (i = 0; i < 27; i++) freq[i] = 0; 20 | 21 | while ((c = getchar()) != EOF){ 22 | if (c >= 'A' && c <= 'Z') 23 | c = c + 32; 24 | 25 | if (c >= 'a' && c <= 'z') 26 | freq[c - 'a']++; 27 | else 28 | freq[OTHER]++; 29 | } 30 | 31 | for (i = 0; i < 26; i++){ 32 | printf ("%c: ", i + 'a'); 33 | for (j = 0; j < freq[i]; j++) 34 | putchar('.'); 35 | printf ("%d\n", freq[i]); 36 | } 37 | 38 | printf ("other: "); 39 | for (j = 0; j < freq[OTHER]; j++) 40 | putchar('.'); 41 | printf ("%d\n", freq[OTHER]); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /cap1/exerc_1.15.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 21:28:45 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | float fahr2cels(float fahr){ 11 | return (5.0 / 9.0) * (fahr - 32.0); 12 | } 13 | 14 | main () 15 | { 16 | float fahr, celsius; 17 | int lower, upper, step; 18 | 19 | lower = 0; 20 | upper = 300; 21 | step = 20; 22 | 23 | fahr = lower; 24 | while (fahr <= upper){ 25 | printf("%3.0f %6.1f\n", fahr, fahr2cels(fahr)); 26 | fahr = fahr + step; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cap1/exerc_1.16.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 22:22:25 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-16. Revise the main routine of the longest-line program so it will correctly print the 9 | length of arbitrary long input lines, and as much as possible of the text. */ 10 | 11 | #include 12 | 13 | //#define MAXLINE 1000 14 | #define MAXLINE 4 15 | 16 | int _getline (char line[], int maxline); 17 | void copy(char to[], char from[]); 18 | 19 | int main () 20 | { 21 | int len, maxlen; 22 | int sum; 23 | char line[MAXLINE], temp[MAXLINE]; 24 | char longest[MAXLINE]; 25 | 26 | maxlen = sum = 0; 27 | while ((len = _getline(line, MAXLINE)) > 0){ 28 | if (line[len - 1] == '\n'){ 29 | if (len + sum > maxlen){ 30 | maxlen = len + sum; 31 | if (sum != 0){ 32 | copy(longest, temp); 33 | } else { 34 | copy(longest, line); 35 | } 36 | } 37 | sum = 0; 38 | } else { 39 | if (sum == 0){ 40 | copy(temp, line); 41 | sum = len; 42 | } else { 43 | sum += len; 44 | } 45 | } 46 | } 47 | 48 | if (maxlen > 0) 49 | printf ("%s -- size %d\n", longest, maxlen); 50 | 51 | return 0; 52 | } 53 | 54 | _getline(char s[], int lim){ 55 | int c, i; 56 | 57 | for (i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; i++) 58 | s[i] = c; 59 | if (c == '\n'){ 60 | s[i] = c; 61 | ++i; 62 | } 63 | s[i] = '\0'; 64 | return i; 65 | } 66 | 67 | void copy(char to[], char from[]){ 68 | int i; 69 | 70 | i = 0; 71 | while ((to[i] = from[i]) != '\0') i++; 72 | } 73 | -------------------------------------------------------------------------------- /cap1/exerc_1.17.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Ter 28 Dez 2010 13:38:45 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define MAXLINE 1000 11 | 12 | int _getline(char line[], int maxline); 13 | void putline(char line[]); 14 | 15 | main () 16 | { 17 | int len; 18 | char line[MAXLINE]; 19 | while ((len = _getline(line, MAXLINE)) > 0){ 20 | if (len > 80) 21 | _putline(line); 22 | } 23 | return 0; 24 | } 25 | 26 | int _getline(char line[], int maxlen){ 27 | int i; 28 | 29 | for (i = 0; i < maxlen - 1 && (line[i] = getchar()) != EOF && line[i] != '\n'; i++) ; 30 | 31 | if (line[i] == '\n') 32 | i++; 33 | 34 | line[i] = '\0'; 35 | 36 | return i; 37 | } 38 | 39 | int _putline(char line[]){ 40 | int i; 41 | 42 | for (i = 0; line[i] != '\0'; i++) 43 | putchar(line[i]); 44 | } 45 | -------------------------------------------------------------------------------- /cap1/exerc_1.18.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Ter 28 Dez 2010 14:00:00 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | /* Exercise 1-18: Write a program to remove thrailing blanks and tabs from each line of input, and to delete 11 | * entirely blank lines */ 12 | 13 | #define MAXLINE 1000 14 | 15 | int _getline(char line[], int maxline); 16 | 17 | int main () 18 | { 19 | int state, i; 20 | char line[MAXLINE]; 21 | 22 | state = 0; 23 | while (_getline(line, MAXLINE) > 0){ 24 | 25 | if (line[0] == '\n'){ 26 | printf("kill line\n"); 27 | continue; 28 | } 29 | 30 | for (i = 0; line[i] != '\0'; i++){ 31 | if (state == 0){ 32 | if (line[i] == '\t' || line[i] == ' '){ 33 | state = 1; 34 | if (line[i] == '\t') 35 | printf("\\t"); 36 | else 37 | printf("\\b"); 38 | } else 39 | putchar(line[i]); 40 | } else { 41 | if (line[i] != '\t' && line[i] != ' '){ 42 | putchar(line[i]); 43 | state = 0; 44 | } 45 | } 46 | } 47 | } 48 | return 0; 49 | } 50 | 51 | int _getline(char line[], int maxline){ 52 | int i; 53 | for (i = 0; i < maxline - 1 && (line[i] = getchar()) != EOF && line[i] != '\n'; i++) ; 54 | if (line[i] == '\n') 55 | i++; 56 | line[i] = '\0'; 57 | return i; 58 | } 59 | -------------------------------------------------------------------------------- /cap1/exerc_1.19.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Ter 28 Dez 2010 15:51:08 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define MAXLINE 1000 11 | 12 | void reverse(char line[], int len); 13 | int _getline(char line[], int limits); 14 | void swap(char line[], int i, int j); 15 | void putline(char line[]); 16 | 17 | int main () 18 | { 19 | char line[MAXLINE]; 20 | int len; 21 | 22 | while ((len = _getline(line, MAXLINE)) > 0){ 23 | reverse(line, len); 24 | putline(line); 25 | } 26 | return 0; 27 | } 28 | 29 | int _getline(char line[], int limits){ 30 | int i; 31 | for (i = 0; i < limits -1 && (line[i] = getchar()) != EOF && line[i] != '\n'; i++) ; 32 | if (line[i] == '\n') 33 | i++; 34 | line[i] = '\0'; 35 | return i; 36 | } 37 | 38 | void reverse(char line[], int len){ 39 | int i, j; 40 | for (i = 0, j = len -1; i < j; i++, j--) 41 | swap(line, i, j); 42 | } 43 | 44 | void swap(char line[], int i, int j){ 45 | int aux; 46 | aux = line[i]; 47 | line[i] = line[j]; 48 | line[j] = aux; 49 | } 50 | 51 | void putline(char line[]){ 52 | int i; 53 | for (i = 0; line[i] != '\0'; i++) 54 | putchar(line[i]); 55 | } 56 | -------------------------------------------------------------------------------- /cap1/exerc_1.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Sex 24 Dez 2010 20:00:20 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | main () 11 | { 12 | printf ("hello, world\n"); 13 | } 14 | -------------------------------------------------------------------------------- /cap1/exerc_1.20-detab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Ter 28 Dez 2010 16:17:29 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define MAXLINE 1000 11 | #define TAB 8 12 | 13 | int tab(int pos); 14 | int _getline(char line[], int limits); 15 | 16 | 17 | int main () 18 | { 19 | char line[MAXLINE]; 20 | int pos, i; 21 | 22 | while (_getline(line, MAXLINE) > 0) { 23 | for (i = 0, pos= 0; line[i] != '\0'; i++, pos++){ 24 | if (line[i] == '\t') 25 | pos = tab(pos); 26 | else 27 | putchar(line[i]); 28 | } 29 | } 30 | } 31 | 32 | int tab(int pos){ 33 | for ( ; pos % TAB != 0; pos++) 34 | putchar(' '); 35 | return pos - 1; 36 | } 37 | 38 | int _getline(char line[], int limits){ 39 | int i; 40 | 41 | for (i = 0; line[i] < limits - 1 && (line[i] = getchar()) != EOF && line[i] != '\n'; i++) ; 42 | if (line[i] == '\n') 43 | i++; 44 | 45 | line[i] = '\0'; 46 | return i; 47 | } 48 | -------------------------------------------------------------------------------- /cap1/exerc_1.21-entab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Ter 28 Dez 2010 16:49:52 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define MAXLINE 1000 11 | #define TAB 4 12 | 13 | int _getline(char line[], int limits); 14 | int tab(char line[], int i, int j); 15 | 16 | int main () 17 | { 18 | char line[MAXLINE]; 19 | int i, j; 20 | 21 | while (_getline(line, MAXLINE) > 0){ 22 | 23 | for (i = 0; line[i] != '\0'; i++){ 24 | if (line[i] != ' ') 25 | putchar(line[i]); 26 | else { 27 | j = i + 1; 28 | while (line[j] == ' ') j++; 29 | i = tab(line, i, j); 30 | while (i < j){ 31 | putchar(line[i]); 32 | i++; 33 | } 34 | i--; 35 | } 36 | } 37 | 38 | } 39 | return 0; 40 | } 41 | 42 | int tab (char line[], int i, int j){ 43 | int cur = i; 44 | i++; 45 | while (i <= j){ 46 | if (i % TAB == 0){ 47 | cur = i; 48 | putchar('\t'); 49 | } 50 | i++; 51 | } 52 | return cur; 53 | } 54 | 55 | int _getline(char line[], int limits){ 56 | int i; 57 | for (i = 0; i < limits - 1 && (line[i] = getchar()) != EOF && line[i] != '\n'; i++) ; 58 | if (line[i] == '\n') 59 | i++; 60 | line[i] = '\0'; 61 | return i; 62 | } 63 | -------------------------------------------------------------------------------- /cap1/exerc_1.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 14:36:30 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-3: Modify the temperature conversion program to print a 9 | heading above the table */ 10 | 11 | #include 12 | 13 | /* print Fahrenheit-Celsius table 14 | * for fahr = 0, 20, ..., 300; floating-point version */ 15 | 16 | main(){ 17 | 18 | float fahr, celsius; 19 | int lower, upper, step; 20 | 21 | lower = 0; 22 | upper = 300; 23 | step = 20; 24 | 25 | fahr = lower; 26 | 27 | printf ("\nConversion Table - Fahrenheit to Celsius\n"); 28 | printf ("-----------------------------------------\n\n"); 29 | while (fahr <= upper) { 30 | celsius = (5.0 / 9.0) * (fahr - 32.0); 31 | printf ("%3.0f %6.1f\n", fahr, celsius); 32 | fahr = fahr + step; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cap1/exerc_1.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 14:48:54 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-4: Write a program to print the corresponding Celsius to 9 | * Fahrenheit table */ 10 | 11 | #include 12 | 13 | main () 14 | { 15 | float fahr, celsius; 16 | int step, lower, upper; 17 | 18 | lower = 0; 19 | upper = 300; 20 | step = 20; 21 | 22 | celsius = lower; 23 | while (celsius <= 300){ 24 | fahr = 9.0 / 5.0 * celsius + 32; 25 | printf ("%3.0f %6.1f\n", celsius, fahr); 26 | celsius = celsius + 20; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cap1/exerc_1.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 15:01:28 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-5: Modify the temperature conversion program to print the table 9 | * in reverse order, that is, from 300 degrees to 0 */ 10 | 11 | #include 12 | 13 | /* print Fahrenheit-Celsius table 14 | * for fahr = 300, 280, ..., 0; floating-point version */ 15 | 16 | main(){ 17 | 18 | float fahr, celsius; 19 | int lower, upper, step; 20 | 21 | lower = 0; 22 | upper = 300; 23 | step = 20; 24 | 25 | fahr = upper; 26 | 27 | printf ("\nConversion Table - Fahrenheit to Celsius\n"); 28 | printf ("-----------------------------------------\n\n"); 29 | while (fahr >= lower) { 30 | celsius = (5.0 / 9.0) * (fahr - 32.0); 31 | printf ("%3.0f %6.1f\n", fahr, celsius); 32 | fahr = fahr - step; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cap1/exerc_1.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 15:05:24 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | main (){ 11 | while (1) printf ("getchar() != EOF: %d\n", getchar() != EOF); 12 | } 13 | -------------------------------------------------------------------------------- /cap1/exerc_1.7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 15:08:37 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | main () 11 | { 12 | printf ("%d\n", EOF); 13 | } 14 | -------------------------------------------------------------------------------- /cap1/exerc_1.8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 15:15:46 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 1-8: Write a program to count blanks, tabs, and newlines; */ 9 | 10 | #include 11 | 12 | main () 13 | { 14 | int c; 15 | int nblanks, ntabs, nl; 16 | 17 | nblanks = ntabs = nl = 0; 18 | 19 | while ((c = getchar()) != EOF){ 20 | if (c == ' ') 21 | nblanks++; 22 | else if (c == '\n') 23 | nl++; 24 | else if (c == '\t') 25 | ntabs++; 26 | } 27 | 28 | printf("\nNumber of Blanks: %d\n", nblanks); 29 | printf("Number of Tabs: %d\n", ntabs); 30 | printf("Number of New Lines: %d\n\n", nl); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /cap1/exerc_1.9.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 27 Dez 2010 15:25:14 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define BLANK 0 11 | #define NOBLANK 1 12 | 13 | main () 14 | { 15 | int c, state; 16 | 17 | state = NOBLANK; 18 | while ((c = getchar()) != EOF){ 19 | if (state == BLANK){ 20 | if (c != ' ') { 21 | putchar(c); 22 | state = NOBLANK; 23 | } 24 | } else { 25 | putchar (c); 26 | if (c == ' ') 27 | state = BLANK; 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /cap2/exercise_2.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 15:31:55 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-1: Write a program to determine the gantes of char, short, 9 | int, and long variables, both signed and unsigned, by printing appropriate 10 | values from standard headers and by direct computation. Harder if you 11 | compute them: determine the ganges of the various floating-point types */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | int main () 18 | { 19 | printf ("signed char\tmin: %hhd\tmax: %hhd\n", SCHAR_MIN, SCHAR_MAX); 20 | printf ("unsigned char\tmin: %hhd\tmax: %hhu\n", 0, UCHAR_MAX); 21 | printf ("char\tmin: %hhd\tmax: %hhd\n", CHAR_MIN, CHAR_MAX); 22 | 23 | printf ("signed short\tmin: %hd\tmax: %hd\n", SHRT_MIN, SHRT_MAX); 24 | printf ("unsigned short\tmin: %hu\tmax: %hu\n", 0, USHRT_MAX); 25 | 26 | printf ("signed int\tmin: %d\tmax: %d\n", INT_MIN, INT_MAX); 27 | printf ("unsigned int\tmin: %u\tmax: %u\n", 0, UINT_MAX); 28 | 29 | printf ("signed long\tmin: %ld\tmax: %ld\n", LONG_MIN, LONG_MAX); 30 | printf ("unsigned long\tmin: %lu\tmax: %lu\n", 0ul, ULONG_MAX); 31 | 32 | printf("\n"); 33 | 34 | printf ("float \tmin: %e\tmax: %e\n", FLT_MIN, FLT_MAX); 35 | printf ("double\tmin: %e\tmax: %e\n", DBL_MIN, DBL_MAX); 36 | printf ("long double\tmin: %Le\tmax: %Le\n", LDBL_MIN, LDBL_MAX); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /cap2/exercise_2.10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 30 Dez 2010 12:01:42 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-10: Rewrite the function lower, which converts upper case letters 9 | * to lower case, with a conditional expresssion instead of if-else */ 10 | 11 | #include 12 | 13 | int lower(int c){ 14 | return (c >= 'A' && c <= 'Z')? c + 'a' - 'A': c; 15 | } 16 | 17 | int main () 18 | { 19 | printf("%c\n", lower('A')); 20 | printf("%c\n", lower('f')); 21 | printf("%c\n", lower('Z')); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /cap2/exercise_2.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 17:28:44 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | int stopcondition = 0; 9 | 10 | while (!stopcondition){ 11 | if (i < lim - 1){ 12 | c = getchar(); 13 | if (c != '\n'){ 14 | if (c != EOF){ 15 | ... 16 | } else 17 | stopcondition = 1; 18 | } else 19 | stopcondition = 1; 20 | } else 21 | stopcondition = 1; 22 | } 23 | -------------------------------------------------------------------------------- /cap2/exercise_2.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 18:34:33 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-3: Write a function htoi(s), which converts a string of 9 | hexadecimal digits (including an optional 0x or 0X) into its equivalent 10 | interger value. The allowable digits are 0 through 9, a through f, 11 | and A through F. */ 12 | 13 | #include 14 | 15 | int htoi(char s[]) { 16 | int i, val, dec; 17 | 18 | if (s[1] == 'x' || s[1] == 'X') 19 | i = 2; 20 | else 21 | i = 0; 22 | 23 | val = 0; 24 | for ( ; s[i] != '\0'; i++) { 25 | if (s[i] >= '0' && s[i] <= '9') 26 | dec = s[i] - '0'; 27 | else if (s[i] >= 'A' && s[i] <= 'Z') 28 | dec = s[i] - 'A' + 10; 29 | else 30 | dec = s[i] - 'a' + 10; 31 | val = val * 16 + dec; 32 | } 33 | 34 | return val; 35 | } 36 | 37 | int main () 38 | { 39 | printf ("%d\n", htoi("aF")); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /cap2/exercise_2.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 19:07:32 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #define TRUE 1 11 | #define FALSE 0 12 | 13 | void squeeze(char s1[], char s2[]){ 14 | int i, j, k; 15 | char finded; 16 | 17 | for (i = 0, k = 0; s1[i] != '\0'; i++){ 18 | finded = FALSE; 19 | for (j = 0; s2[j] != '\0' && !finded; j++){ 20 | if (s1[i] == s2[j]){ 21 | finded = TRUE; 22 | } 23 | } 24 | if (!finded) 25 | s1[k++] = s1[i]; 26 | } 27 | s1[k] = '\0'; 28 | } 29 | 30 | int main () 31 | { 32 | char s[] = "mtyayb"; 33 | squeeze(s, "may"); 34 | printf("%s\n", s); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /cap2/exercise_2.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 21:15:27 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-5: Write the function any(s1, s2), which returns the first location in a string s1 where any character from the string s2 occurs, or -1 if s1 contains no characters from s2. */ 9 | 10 | #include 11 | 12 | int any(char s1[], char s2[]){ 13 | int i, j; 14 | for (i = 0; s1[i] != '\0'; i++){ 15 | for (j = 0; s2[j] != '\0'; j++){ 16 | if (s1[i] == s2[j]) 17 | return i; 18 | } 19 | } 20 | return -1; 21 | } 22 | 23 | 24 | int main () 25 | { 26 | printf("%d\n", any("maycon", "kkkk")); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /cap2/exercise_2.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 22:45:29 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-6: Write a function setbits (x, p, n, y) that returns x with 9 | * the n bits that begin at position p set to the rightmost n bits of y, leaving 10 | * the other bits unchanged. */ 11 | 12 | #include 13 | 14 | unsigned setbits(unsigned x, unsigned p, unsigned n, unsigned y){ 15 | return (x & ~(~(~0 << n) << (p -n + 1))) | ((y & ~(~0 << n)) << (p - n + 1)); 16 | } 17 | 18 | int main () 19 | { 20 | printf ("%x\n", setbits(0xff, 4, 5, 0x0c)); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /cap2/exercise_2.7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 29 Dez 2010 23:17:34 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-7: Write a function invert(x, p, n) that returns x with the n bits that begin 9 | * at position p inverted (i.e. 1 canged into 0 and vice versa), leaving the others unchanged */ 10 | 11 | #include 12 | 13 | unsigned invert(unsigned x, unsigned p, unsigned n){ 14 | int newbits; 15 | 16 | newbits = (~x >> (p + 1 - n) & ~(~0 << n)) << (p + 1 -n); 17 | x = ~(~(~0 << n) << (p + 1 - n)) & x; 18 | 19 | return x | newbits; 20 | } 21 | 22 | int main () 23 | { 24 | printf("%x\n", invert(0xfbf, 7, 8)); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /cap2/exercise_2.8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 30 Dez 2010 00:03:27 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-8: Write a function rightrot(x, n) that returns the value 9 | of the integer x rotated to the right by n positions. */ 10 | 11 | #include 12 | 13 | unsigned rightrot(unsigned x, unsigned n){ 14 | unsigned fall = ((~(~0 << n)) & x) << (32 - n); 15 | x = x >> n; 16 | return fall | x; 17 | } 18 | 19 | int main () 20 | { 21 | printf("%x\n", rightrot(0xbcd0000a, 24)); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /cap2/exercise_2.9.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 30 Dez 2010 11:47:26 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 2-9: In a two's complement number system, x &= (x - 1) deletes the 9 | * rightmost 1-bit in x. Explain why. Use this observation to write a faster version of bitcont. 10 | */ 11 | 12 | 13 | /* 14 | + Suponha que n é um número com 6 bits 15 | + (x - 1) pode ser escrito como (x + (-1)) 16 | + A representação de -1 com 6 bits em complemento de dois é: 111111 17 | + Quando fizermos x + (-1) o primeiro bit setado para 1 em x será setado para 0 pois: 18 | 19 | (vai um) 1 <- 1 20 | + 1 21 | ---- 22 | 0 23 | 24 | + Se o bit da esquerda for 0 o valor desse bit será mantido pois: 25 | (vai um) 1 <- 1 <- (bit enviado pelo bit da direita) 26 | 0 27 | + 1 28 | ---- 29 | 0 30 | 31 | + Se o bit da esquerda for 1 o valor desse bit será mantido pois: 32 | (vai um) 1 <- 1 <- (bit enviado pelo bit da direita) 33 | 1 34 | + 1 35 | ---- 36 | 1 37 | + e assim sucessivamente 38 | + Desta forma após zerar o primeiro bit setado para 1 os bits da esquerda desse bit serão copiados 39 | para o resultado 40 | + Após isso é efetivada x & (x -1) 41 | 42 | */ 43 | 44 | #include 45 | 46 | int bitcount(unsigned x){ 47 | int b; 48 | for (b = 0; x != 0; x&= x - 1) 49 | b++; 50 | return b; 51 | } 52 | 53 | int main () 54 | { 55 | printf("%d\n", bitcount(0x588f)); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /cap3/exercise_3.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 30 Dez 2010 14:18:01 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-1: Our binary search makes two test inside the loop, when one 9 | would suffice (at the price of more tests outside.) Write a version with 10 | only one test inside the loop and measure the difference in run-time. */ 11 | 12 | /* time: 13 | * 14 | * function | not optimized | -O2 optimized | 15 | * ----------------------------------------------------- 16 | * bisearch_1test | 0.24s | 0.09s | 17 | * bisearch_2test | 0.24s | 0.1s | 18 | * ------------------------------------------------------ 19 | */ 20 | 21 | #include 22 | 23 | #define VETSIZE 1000000 24 | 25 | int binsearch_2test(int x, int v[], int n) { 26 | int low, high, mid; 27 | 28 | low = 0; 29 | high = n - 1; 30 | while (low <= high){ 31 | mid = (low + high) / 2; 32 | if (x < v[mid]) 33 | high = mid - 1; 34 | else if (x > v[mid]) 35 | low = mid + 1; 36 | else /* found match */ 37 | return mid; 38 | } 39 | return -1; /* no match */ 40 | } 41 | 42 | int binsearch_1test(int x, int v[], int n){ 43 | int low, high, mid; 44 | 45 | low = 0; 46 | high = n - 1; 47 | while (low < high){ 48 | mid = (low + high) / 2; 49 | if (x <= v[mid]) 50 | high = mid; 51 | else 52 | low = mid + 1; 53 | } 54 | return (low == high)? low: -1; 55 | } 56 | 57 | 58 | int main () 59 | { 60 | int v[VETSIZE]; 61 | int i; 62 | 63 | for (i = 0; i < VETSIZE; i++) 64 | v[i] = i; 65 | for (i = 0; i < VETSIZE; i++){ 66 | printf ("search %d -- Found: %d\n", i, binsearch_1test(i, v, VETSIZE)); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /cap3/exercise_3.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Dom 02 Jan 2011 17:10:25 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-2: Write a function escape(s, t) that converts characters like 9 | newline and tab into visible escape sequences like \n and \t as it copies 10 | the string t to s. Use a switch. Write a function for the other direction 11 | as well, converting escape sequences into the real characters. */ 12 | 13 | #include 14 | 15 | void escape(char s[], char t[]){ 16 | int i, j; 17 | for (i = 0, j = 0; t[i] != '\0'; i++){ 18 | switch (t[i]){ 19 | default: 20 | s[j] = t[i]; 21 | break; 22 | case '\t': 23 | s[j++] = '\\'; 24 | s[j] = 't'; 25 | break; 26 | case '\n': 27 | s[j++] = '\\'; 28 | s[j] = 'n'; 29 | break; 30 | case '\%': 31 | s [j++] = '\\'; 32 | s [j] = '\%'; 33 | break; 34 | case '\\': 35 | s[j++] = '\\'; 36 | s [j] = '\\'; 37 | break; 38 | } 39 | j++; 40 | } 41 | s[j] = '\0'; 42 | } 43 | 44 | void rev_escape(char s[], char t[]){ 45 | int i, j; 46 | char esc = 0; 47 | 48 | for (i = 0, j = 0; t[i] != '\0'; i++){ 49 | switch(t[i]){ 50 | case '\\': 51 | if (!esc){ 52 | esc = 1; 53 | j--; 54 | } else { 55 | esc = 0; 56 | s[j] = '\\'; 57 | } 58 | break; 59 | case 't': 60 | s[j] = (esc)? '\t': 't'; 61 | esc = 0; 62 | break; 63 | case 'n': 64 | s[j] = (esc)? '\n': 'n'; 65 | esc = 0; 66 | break; 67 | case '\%': 68 | s[j] = (esc)? '\%': 0; 69 | esc = 0; 70 | break; 71 | default: 72 | s[j] = t[i]; 73 | } 74 | j++; 75 | } 76 | s[j] = '\0'; 77 | } 78 | 79 | 80 | int main () 81 | { 82 | char t[255], u[255]; 83 | escape(t, "\\ -- \% maycon\t\tsambinelli\nCientista \\ da Computacao\t\tformado\t\t2010"); 84 | printf("%s\n", t); 85 | rev_escape(u, t); 86 | printf("%s\n", u); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /cap3/exercise_3.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 00:08:53 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-3: Write a function expand(s1, s2) that expands shorthand notations like a-z in the string s1 into 9 | * the equivalent complete list abc...xyz in s2. Allow for letters of either case and digits, and be prepared to 10 | * handle cases like a-b-c and a-z0-9 and -a-z. Arrange that a leading or trailing - is taken literally 11 | */ 12 | 13 | #include 14 | 15 | #define MAXLEN 1000 16 | 17 | void expand(char s1[], char s2[]){ 18 | int i, j, prev, k; 19 | 20 | for (i = 0, j = 0, prev = -1; s1[i] != '\0'; i++){ 21 | if (s1[i] == '-'){ 22 | if (prev == -1 || s1[i + 1] == '\0') 23 | s2[j++] = s1[i]; 24 | else { 25 | for (k = prev + 1; k <= s1[i + 1]; k++) 26 | s2[j++] = k; 27 | prev = s1[i + 1]; 28 | i++; 29 | } 30 | } else { 31 | prev = s2[j++] = s1[i]; 32 | } 33 | } 34 | s2[j] = '\0'; 35 | } 36 | 37 | int main (int argc, char const* argv[]) 38 | { 39 | char out[MAXLEN]; 40 | 41 | expand("0-9abc-zA-F-M-Z-", out); 42 | printf("%s\n", out); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /cap3/exercise_3.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 13:50:40 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-4: In a two's complement nuumber representation, our version of itoa does not handle the largest 9 | * negative number, that is, the value of n equal to -(2^(wordsize-1)). Expain why not. Modify it to print that 10 | * value correctly, regardless of the machine on wich it runs. */ 11 | 12 | /* 13 | 14 | Digamos que a máquina em questão tenha o tamanho de palavra igual a 3. Desta forma podemos representar os seguintes 15 | numeros positivos: 16 | 17 | 321 | valor decimal 18 | ----+-------------- 19 | 000 | 0 20 | 001 | 1 21 | 010 | 2 22 | 011 | 3 23 | ----+-------------- 24 | 25 | A representação desses valores em complemento de dois é: 26 | 27 | 321 | valor decimal 28 | ----+-------------- 29 | 000 | - 0 30 | 111 | - 1 31 | 110 | - 2 32 | 101 | - 3 33 | 100 | - 4 34 | ----+-------------- 35 | 36 | Desta forma, o intervalo representado é: [-4, 3]. Assim, não podemos representar o menor número negativo na sua forma 37 | absoluta. 38 | 39 | */ 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | void reverse(char s[]){ 46 | int i, j, aux; 47 | for (i = 0, j = strlen(s) - 1; i < j; i++, j--){ 48 | aux = s[i]; 49 | s[i] = s[j]; 50 | s[j] = aux; 51 | } 52 | } 53 | 54 | /* itoa: convert n to characters in s */ 55 | void itoa(int n, char s[]){ 56 | int i, sign; 57 | 58 | sign = n; 59 | i = 0; 60 | 61 | do { 62 | s[i++] = (n % 10 < 0)? -(n % 10) + '0': n % 10 + '0'; 63 | } while ((n /= 10) != 0); 64 | 65 | if (sign < 0) 66 | s[i++] = '-'; 67 | s[i] = '\0'; 68 | reverse(s); 69 | } 70 | 71 | int main () 72 | { 73 | char s[100]; 74 | itoa(INT_MIN, s); 75 | 76 | printf("%s %d\n", s, INT_MIN); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /cap3/exercise_3.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 15:05:50 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-5: Write the function itob(n, s, b) that converts the integer n into a base b character representation 9 | * in the string s. In particular, itob(n, s, 16) formats s as a hexadecimal 10 | * integer in s. */ 11 | 12 | #include 13 | #include 14 | 15 | void reverse(char s[]){ 16 | int i, j, aux; 17 | 18 | for (i = 0, j = strlen(s) - 1; i < j; i++, j--){ 19 | aux = s[i]; 20 | s[i] = s[j]; 21 | s[j] = aux; 22 | } 23 | } 24 | 25 | char num2char(int n){ 26 | switch(n){ 27 | case 10: 28 | case 11: 29 | case 12: 30 | case 13: 31 | case 14: 32 | case 15: 33 | return n - 10 + 'A'; 34 | default: 35 | return n + '0'; 36 | } 37 | } 38 | 39 | void itob(int n, char s[], int b){ 40 | int i, sign; 41 | 42 | sign = n; 43 | 44 | i = 0; 45 | do { 46 | s[i++] = num2char((n % b < 0)? -(n % b): n % b); 47 | } while ((n /= b) != 0); 48 | 49 | if (b == 16){ 50 | s[i++] = 'x'; 51 | s[i++] = '0'; 52 | } 53 | 54 | if (sign < 0) 55 | s[i++] = '-'; 56 | s[i] = '\0'; 57 | reverse(s); 58 | } 59 | 60 | int main (int argc, char const* argv[]) 61 | { 62 | char s[50]; 63 | itob(255, s, 4); 64 | printf("%s\n", s); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /cap3/exercise_3.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 15:37:43 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 3-6: Write a version of itoa that accepts three arguments instead of 9 | * two. The third argument is a minimum field width; the converted number must 10 | * be padded with blanks on the left if necessary to make it wide enough */ 11 | 12 | #include 13 | #include 14 | 15 | void reverse(char s[]){ 16 | int i, j, aux; 17 | for (i = 0, j = strlen(s) - 1; i < j; i++, j--){ 18 | aux = s[i]; 19 | s[i] = s[j]; 20 | s[j] = aux; 21 | } 22 | } 23 | 24 | /* itoa: convert n to characters in s */ 25 | void itoa(int n, char s[], int f){ 26 | int i, sign; 27 | 28 | sign = n; 29 | i = 0; 30 | 31 | do { 32 | s[i++] = (n % 10 < 0)? -(n % 10) + '0': n % 10 + '0'; 33 | } while ((n /= 10) != 0); 34 | 35 | if (sign < 0) 36 | s[i++] = '-'; 37 | 38 | while (i < f) 39 | s[i++] = ' '; 40 | 41 | s[i] = '\0'; 42 | reverse(s); 43 | } 44 | 45 | int main () 46 | { 47 | char s[100]; 48 | 49 | itoa(1000007, s, 18); 50 | printf("%s\n", s); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /cap4/exercise.4.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 20:28:26 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-1. Write the function strindex(s, t) which returns the position 9 | * of the rightmost occurrence of t in s, or -1 if there is none */ 10 | 11 | 12 | #include 13 | #include 14 | 15 | #define MAXLINE 1000 16 | 17 | int _getline(char s[], int max); 18 | int strindex(char source[], char searchfor[]); 19 | 20 | char pattern[] = "ould"; 21 | 22 | int main () 23 | { 24 | char line[MAXLINE]; 25 | int found = 0, pos; 26 | 27 | while (_getline(line, MAXLINE) > 0){ 28 | if ((pos = strindex(line, pattern)) >= 0) { 29 | printf ("%s -- %d col", line, pos); 30 | found++; 31 | } 32 | } 33 | return found; 34 | } 35 | 36 | int _getline(char s[], int lim){ 37 | int c, i; 38 | 39 | i = 0; 40 | 41 | while (--lim > 0 && (c = getchar()) != EOF && c != '\n') 42 | s[i++] = c; 43 | if (c == '\n') 44 | s[i++] = c; 45 | s[i] = '\0'; 46 | return i; 47 | } 48 | 49 | int strindex(char s[], char t[]){ 50 | int i, j, k; 51 | 52 | for (i = strlen(s) - strlen(t); i >= 0; i--){ 53 | for (j = i, k = 0; t[k] != '\0' && t[k] == s[j]; j++, k++) ; 54 | if (t[k] == '\0') 55 | return i; 56 | } 57 | return -1; 58 | } 59 | -------------------------------------------------------------------------------- /cap4/exercise.4.10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 22:53:21 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-10: An alternate organization uses getline toread an entire input line; this makes 9 | * getch and ungetch unnecessary. Revise the calculator to use this approach */ 10 | 11 | #include 12 | #include /* for atof() */ 13 | #include 14 | #include 15 | 16 | #define MAXOP 100 /* max size of operand or operator */ 17 | #define NUMBER '0' /* signal that a number was found */ 18 | #define NVAR 26 19 | #define SIN '1' 20 | #define COS '2' 21 | #define EXP '3' 22 | #define POW '4' 23 | #define VAR_SET '5' 24 | #define VAR_GET '6' 25 | 26 | int getop(char []); 27 | void push(double); 28 | double pop(void); 29 | double top(void); 30 | int strcmp(char s1[], char s2[]); 31 | int _getline(int s[], int limit); 32 | 33 | double var[NVAR]; 34 | 35 | int carrier = 0; 36 | int command[MAXOP]; 37 | 38 | /* reverse Polish Calculator */ 39 | int main() 40 | { 41 | int type; 42 | double op2; 43 | char s[MAXOP]; 44 | _getline(command, MAXOP); 45 | 46 | while ((type = getop(s)) != EOF) { 47 | switch(type){ 48 | case NUMBER: 49 | push(atof(s)); 50 | break; 51 | case '+': 52 | push(pop() + pop()); 53 | break; 54 | case '*': 55 | push(pop() * pop()); 56 | break; 57 | case '-': 58 | op2 = pop(); 59 | push(pop() - op2); 60 | break; 61 | case '/': 62 | op2 = pop(); 63 | if (op2 != 0.0) 64 | push(pop() / op2); 65 | else 66 | printf("error: zero divisor\n"); 67 | break; 68 | case '%': 69 | op2 = pop(); 70 | push ((int) pop() % (int) op2); 71 | break; 72 | case SIN: 73 | push(sin(pop())); 74 | break; 75 | case COS: 76 | push(cos(pop())); 77 | break; 78 | case EXP: 79 | push(exp(pop())); 80 | break; 81 | case POW: 82 | op2 = pop(); 83 | push(pow(pop(), op2)); 84 | break; 85 | case VAR_SET: 86 | var[s[0] - 'A'] = top(); 87 | break; 88 | case VAR_GET: 89 | push(var[s[0] - 'a']); 90 | break; 91 | case '\n': 92 | printf ("\t%.8g\n", op2 = pop()); 93 | var['R' - 'A'] = op2; 94 | _getline(command, MAXOP); 95 | carrier = 0; 96 | break; 97 | default: 98 | printf ("error: unknown command %s", s); 99 | break; 100 | } 101 | } 102 | return 0; 103 | } 104 | 105 | #define MAXVAL 100 /* maximum depth of val stack */ 106 | 107 | int sp = 0; /* next free stack position */ 108 | double val[MAXVAL]; /* value stack */ 109 | 110 | /* push: push f onto value stack */ 111 | void push(double f){ 112 | if (sp < MAXVAL) 113 | val[sp++] = f; 114 | else 115 | printf("error: stack full, can't push %g\n", f); 116 | } 117 | 118 | double pop(void){ 119 | if (sp > 0) 120 | return val[--sp]; 121 | else { 122 | printf("error: stack empty\n"); 123 | return 0.0; 124 | } 125 | } 126 | 127 | double top(void){ 128 | if (sp > 0){ 129 | return val[sp - 1]; 130 | } else{ 131 | printf("error: stack empty\n"); 132 | return 0.0; 133 | } 134 | } 135 | 136 | #include 137 | 138 | /* getop: get next character or numeric operand */ 139 | int getop(char s[]){ 140 | 141 | int c, next, i; 142 | 143 | while ((s[0] = c = command[carrier++]) == ' ' || c == '\t') ; 144 | 145 | if (c == '\n' || c == EOF) 146 | return c; 147 | 148 | next = command[carrier]; 149 | 150 | if (isdigit(c) || (( c == '+' || c == '-') && isdigit(next))){ 151 | s[i = 0] = c; 152 | while (isdigit(s[++i] = c = command[carrier++])) ; 153 | if (c == '.'){ 154 | while (isdigit(s[++i] = c = command[carrier++])) ; 155 | } 156 | carrier--; 157 | s[i] = '\0'; 158 | c = NUMBER; 159 | } else if (isalpha(c)){ 160 | i = 0; 161 | while (isalpha(s[++i] = c = command[carrier++])) ; 162 | carrier--; 163 | s[i] = '\0'; 164 | if (i > 1){ 165 | if (!strcmp(s, "SIN")){ 166 | return SIN; 167 | } else if (!strcmp(s, "COS")){ 168 | return COS; 169 | } else if (!strcmp(s, "EXP")){ 170 | return EXP; 171 | } else if (!strcmp(s, "POW")){ 172 | return POW; 173 | } else { 174 | printf("error: unknow functions %s\n", s); 175 | } 176 | } else { 177 | if (islower(s[0])) 178 | return VAR_GET; 179 | else 180 | return VAR_SET; 181 | } 182 | } else { 183 | s[0] = c; 184 | s[1] = '\0'; 185 | } 186 | return c; 187 | } 188 | 189 | int strcmp(char s1[], char s2[]){ 190 | int i, c; 191 | for (i = 0; (c = s1[i] - s2[i]) == 0 && s1[i] != '\0'; i++); 192 | return c; 193 | } 194 | 195 | int _getline(int s[], int limit){ 196 | int i, c; 197 | for (i = 0; i < limit - 2 && (c = getchar()) != EOF && c != '\n'; i++) 198 | s[i] = c; 199 | s[i++] = c; 200 | s[i] = '\0'; 201 | return i; 202 | } 203 | -------------------------------------------------------------------------------- /cap4/exercise.4.11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-06T20:52:38 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 4-11: Modify getop so that it doesn't need to use ungetch. Hint 8 | use an internal static variable */ 9 | 10 | #include 11 | #include 12 | #include /* for atof() */ 13 | #include 14 | #include 15 | 16 | #define MAXOP 100 /* max size of operand or operator */ 17 | #define NUMBER '0' /* signal that a number was found */ 18 | #define NVAR 26 19 | #define SIN '1' 20 | #define COS '2' 21 | #define EXP '3' 22 | #define POW '4' 23 | #define VAR_SET '5' 24 | #define VAR_GET '6' 25 | #define EMPTY -2 26 | 27 | int getop(char []); 28 | void push(double); 29 | double pop(void); 30 | double top(void); 31 | int strcmp(char s1[], char s2[]); 32 | int strlen(char s[]); 33 | 34 | double var[NVAR]; 35 | 36 | int getop(char s[]){ 37 | static int c = EMPTY; 38 | 39 | int i = 0; 40 | if (c == EMPTY) 41 | c = getchar(); 42 | s[0] = c; 43 | while (c == ' ' || c == '\t') 44 | s[0] = c = getchar(); 45 | 46 | if (c == '+' || c == '-' || isdigit(c)){ 47 | while (isdigit(s[++i] = c = getchar())) ; 48 | if (c == '.') 49 | while (isdigit(s[++i] = c = getchar())) ; 50 | s[i] = '\0'; 51 | if (strlen(s) == 1 && !isdigit(s[0])) 52 | return s[0]; 53 | else 54 | return NUMBER; 55 | } else if (isalpha(c)){ 56 | while (isalpha(s[++i] = c = getchar())) ; 57 | s[i] ='\0'; 58 | if (!strcmp(s, "SIN")) 59 | return SIN; 60 | else if (!strcmp(s, "COS")) 61 | return COS; 62 | else if (!strcmp(s, "EXP")) 63 | return EXP; 64 | else if (!strcmp(s, "POW")) 65 | return POW; 66 | else if (strlen(s) == 1){ /* is a variable */ 67 | return (islower(s[0])) ? VAR_GET : VAR_SET; 68 | } else 69 | printf ("error: unknow function %s\n", s); 70 | } else { 71 | c = EMPTY; 72 | s[1] = '\0'; 73 | return s[0]; 74 | } 75 | } 76 | 77 | 78 | #define MAXVAL 100 /* maximum depth of val stack */ 79 | 80 | int sp = 0; /* next free stack position */ 81 | double val[MAXVAL]; /* value stack */ 82 | 83 | /* push: push f onto value stack */ 84 | void push(double f){ 85 | if (sp < MAXVAL) 86 | val[sp++] = f; 87 | else 88 | printf("error: stack full, can't push %g\n", f); 89 | } 90 | 91 | double pop(void){ 92 | if (sp > 0) 93 | return val[--sp]; 94 | else { 95 | printf("error: stack empty\n"); 96 | return 0.0; 97 | } 98 | } 99 | 100 | double top(void){ 101 | if (sp > 0){ 102 | return val[sp - 1]; 103 | } else{ 104 | printf("error: stack empty\n"); 105 | return 0.0; 106 | } 107 | } 108 | 109 | #include 110 | 111 | int getch(void); 112 | void ungetch(int); 113 | 114 | /* reverse Polish Calculator */ 115 | int main() 116 | { 117 | int type; 118 | double op2; 119 | char s[MAXOP]; 120 | 121 | while ((type = getop(s)) != EOF) { 122 | switch(type){ 123 | case NUMBER: 124 | push(atof(s)); 125 | break; 126 | case '+': 127 | push(pop() + pop()); 128 | break; 129 | case '*': 130 | push(pop() * pop()); 131 | break; 132 | case '-': 133 | op2 = pop(); 134 | push(pop() - op2); 135 | break; 136 | case '/': 137 | op2 = pop(); 138 | if (op2 != 0.0) 139 | push(pop() / op2); 140 | else 141 | printf("error: zero divisor\n"); 142 | break; 143 | case '%': 144 | op2 = pop(); 145 | push ((int) pop() % (int) op2); 146 | break; 147 | case SIN: 148 | push(sin(pop())); 149 | break; 150 | case COS: 151 | push(cos(pop())); 152 | break; 153 | case EXP: 154 | push(exp(pop())); 155 | break; 156 | case POW: 157 | op2 = pop(); 158 | push(pow(pop(), op2)); 159 | break; 160 | case VAR_SET: 161 | var[s[0] - 'A'] = top(); 162 | break; 163 | case VAR_GET: 164 | push(var[s[0] - 'a']); 165 | break; 166 | case '\n': 167 | printf ("\t%.8g\n", op2 = pop()); 168 | var['R' - 'A'] = op2; 169 | break; 170 | default: 171 | printf ("error: unknown command %s", s); 172 | break; 173 | } 174 | } 175 | return 0; 176 | } 177 | 178 | #define BUFSIZE 100 179 | 180 | char buf[BUFSIZE]; /* buffer for ungetch */ 181 | int bufp = 0; /* next gree position in buf */ 182 | 183 | int getch(void) /* get a (possibly pushed-back) character */ 184 | { 185 | return (bufp > 0) ? buf[--bufp] : getchar(); 186 | } 187 | 188 | void ungetch(int c) /* get character back on input */ 189 | { 190 | if (bufp >= BUFSIZE) 191 | printf("ungetch: too many characters\n"); 192 | else 193 | buf[bufp++] = c; 194 | } 195 | 196 | int strcmp(char s1[], char s2[]){ 197 | int i, c; 198 | for (i = 0; (c = s1[i] - s2[i]) == 0 && s1[i] != '\0'; i++); 199 | return c; 200 | } 201 | 202 | int strlen(char s[]){ 203 | int i; 204 | for (i = 0; s[i] != '\0'; i++); 205 | return i; 206 | } 207 | -------------------------------------------------------------------------------- /cap4/exercise.4.12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-06T23:28:34 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 4-12: Adapt the ideas of printd to write a recusive version of itoa; 8 | * that is, covert an integer into a string by calling a recursive routine */ 9 | 10 | #include 11 | 12 | int do_itoa(char s[], int n, int index) 13 | { 14 | if (n < 0) { 15 | s[index++] = '-'; 16 | n = -n; 17 | } 18 | 19 | if ( n / 10 ) { 20 | index = do_itoa(s, n / 10, index); 21 | } 22 | s[index++] = (n % 10) + '0'; 23 | return index; 24 | } 25 | 26 | void itoa(char s[], int n) 27 | { 28 | int i = do_itoa (s, n, 0); 29 | s[i] = '\0'; 30 | } 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | char s[255]; 35 | itoa(s, -7845); 36 | printf ("%s\n", s); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /cap4/exercise.4.13.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-06T23:37:41 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 4-13: Write a recursive version of the function reverse (s), which reverses 8 | * the string s in place. */ 9 | 10 | #include 11 | #include 12 | 13 | void do_reverse(char s[], int left, int right){ 14 | int aux; 15 | if (left < right){ 16 | aux = s[left]; 17 | s[left] = s[right]; 18 | s[right] = aux; 19 | do_reverse (s, left + 1, right - 1); 20 | } 21 | } 22 | 23 | void reverse(char s[]){ 24 | do_reverse(s, 0, strlen(s) - 1); 25 | } 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | char s[] = "Maycon Sambinelli"; 30 | printf ("%s\n", s); 31 | reverse(s); 32 | printf ("%s\n", s); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /cap4/exercise.4.14.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-07T00:02:47 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 4-14: Define a macro swap(t, x, y) that interchanges two arguments of type t. 8 | * (Block strucutre will help). */ 9 | 10 | #include 11 | 12 | #define swap(t, x, y) {t aux; aux = x; x = y; y = aux;} 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int a = 13, b = 15; 17 | swap(int, a, b); 18 | printf ("a: %d\tb: %d\n", a, b); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /cap4/exercise.4.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 21:40:11 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-2: Extend atof to handle scientific notation of the form: 9 | * 10 | * 123.45e-6 11 | * 12 | * Where a floating-point number may be followed by e or E and an optionally 13 | * signed exponent 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | double atof(char s[]){ 20 | int i, sign, valexp; 21 | double val, power, exp; 22 | 23 | for (i = 0; isspace(s[i]); i++) ; 24 | sign = (s[i] == '-')? -1: 1; 25 | if (s[i] == '+' || s[i] == '-') 26 | i++; 27 | for (val = 0.0; isdigit(s[i]); i++) 28 | val = val * 10 + (s[i] - '0'); 29 | 30 | if (s[i] == '.'){ 31 | i++; 32 | for (power = 1.0; isdigit(s[i]); i++){ 33 | val = val * 10 + (s[i] - '0'); 34 | power *= 10; 35 | } 36 | val = val / power; 37 | } 38 | 39 | if (s[i] == 'e' || s[i] == 'E'){ 40 | i++; 41 | exp = (s[i] == '-')? 1.0 / 10 : 10; 42 | if (s[i] == '-' || s[i] == '+') 43 | i++; 44 | for (valexp = 0; isdigit(s[i]); i++) 45 | valexp = 10 * valexp + (s[i] - '0'); 46 | for (i = 0; i < valexp; i++) 47 | val *= exp; 48 | } 49 | 50 | return val; 51 | } 52 | 53 | int main () 54 | { 55 | printf("%g\n", atof(".534E3")); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /cap4/exercise.4.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 22:53:21 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-3: Given the basic framework, it's straighforward to extend the calculator. 9 | * Add the modulus (%) operator and provisions for negative numbers. */ 10 | 11 | #include 12 | #include /* for atof() */ 13 | 14 | #define MAXOP 100 /* max size of operand or operator */ 15 | #define NUMBER '0' /* signal that a number was found */ 16 | 17 | int getop(char []); 18 | void push(double); 19 | double pop(void); 20 | 21 | /* reverse Polish Calculator */ 22 | main() 23 | { 24 | int type; 25 | double op2; 26 | char s[MAXOP]; 27 | 28 | while ((type = getop(s)) != EOF) { 29 | switch(type){ 30 | case NUMBER: 31 | push(atof(s)); 32 | break; 33 | case '+': 34 | push(pop() + pop()); 35 | break; 36 | case '*': 37 | push(pop() * pop()); 38 | break; 39 | case '-': 40 | op2 = pop(); 41 | push(pop() - op2); 42 | break; 43 | case '/': 44 | op2 = pop(); 45 | if (op2 != 0.0) 46 | push(pop() / op2); 47 | else 48 | printf("error: zero divisor\n"); 49 | break; 50 | case '%': 51 | op2 = pop(); 52 | push ((int) pop() % (int) op2); 53 | break; 54 | case '\n': 55 | printf ("\t%.8g\n", pop()); 56 | break; 57 | default: 58 | printf ("error: unknown command %s", s); 59 | break; 60 | } 61 | } 62 | return 0; 63 | } 64 | 65 | #define MAXVAL 100 /* maximum depth of val stack */ 66 | 67 | int sp = 0; /* next free stack position */ 68 | double val[MAXVAL]; /* value stack */ 69 | 70 | /* push: push f onto value stack */ 71 | void push(double f){ 72 | if (sp < MAXVAL) 73 | val[sp++] = f; 74 | else 75 | printf("error: stack full, can't push %g\n", f); 76 | } 77 | 78 | double pop(void){ 79 | if (sp > 0) 80 | return val[--sp]; 81 | else { 82 | printf("error: stack empty\n"); 83 | return 0.0; 84 | } 85 | } 86 | 87 | #include 88 | 89 | int getch(void); 90 | void ungetch(int); 91 | 92 | /* getop: get next character or numeric operand */ 93 | int getop(char s[]){ 94 | 95 | int c, next, i; 96 | 97 | while ((s[0] = c = getch()) == ' ' || c == '\t') ; 98 | 99 | if (c == '\n' || c == EOF) 100 | return c; 101 | 102 | next = getch(); 103 | ungetch(next); 104 | if (isdigit(c) || (( c == '+' || c == '-') && isdigit(next))){ 105 | s[i = 0] = c; 106 | while (isdigit(s[++i] = c = getch())) ; 107 | if (c == '.'){ 108 | while (isdigit(s[++i] = c = getch())) ; 109 | } else { 110 | ungetch(c); 111 | } 112 | s[i] = '\0'; 113 | c = NUMBER; 114 | } else { 115 | s[0] = c; 116 | s[1] = '\0'; 117 | } 118 | 119 | return c; 120 | } 121 | 122 | #define BUFSIZE 100 123 | 124 | char buf[BUFSIZE]; /* buffer for ungetch */ 125 | int bufp = 0; /* next gree position in buf */ 126 | 127 | int getch(void) /* get a (possibly pushed-back) character */ 128 | { 129 | return (bufp > 0) ? buf[--bufp] : getchar(); 130 | } 131 | 132 | void ungetch(int c) /* get character back on input */ 133 | { 134 | if (bufp >= BUFSIZE) 135 | printf("ungetch: too many characters\n"); 136 | else 137 | buf[bufp++] = c; 138 | } 139 | -------------------------------------------------------------------------------- /cap4/exercise.4.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 05 Jan 2011 14:16:03 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-4: Add the commands to print the top elements of the stack without poppin, to duplicate it, and to 9 | * swap the top two elements. Add a command to clear the stack */ 10 | 11 | #include 12 | 13 | #define MAXVAL 100 /* maximum depth of val stack */ 14 | 15 | int sp = 0; /* next free stack position */ 16 | double val[MAXVAL]; /* value stack */ 17 | 18 | /* push: push f onto value stack */ 19 | void push(double f){ 20 | if (sp < MAXVAL) 21 | val[sp++] = f; 22 | else 23 | printf("error: stack full, can't push %g\n", f); 24 | } 25 | 26 | double pop(void){ 27 | if (sp > 0) 28 | return val[--sp]; 29 | else { 30 | printf("error: stack empty\n"); 31 | return 0.0; 32 | } 33 | } 34 | 35 | double top(void){ 36 | if (sp > 0) 37 | return val[sp - 1]; 38 | else 39 | printf("error: stack empty\n"); 40 | } 41 | 42 | void duplicate(void){ 43 | int i; 44 | i = sp - 1; 45 | val[sp++] = val[i]; 46 | } 47 | 48 | void swap(void){ 49 | int aux = val[sp - 2]; 50 | val[sp - 2] = val[sp - 1]; 51 | val[sp - 1] = aux; 52 | } 53 | 54 | void clear(void){ 55 | sp = 0; 56 | } 57 | 58 | int main (int argc, char const* argv[]) 59 | { 60 | push(1.0); 61 | push(2.0); 62 | push(3.0); 63 | push(4.0); 64 | push(5.0); 65 | push(6.0); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /cap4/exercise.4.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 22:53:21 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-3: Given the basic framework, it's straighforward to extend the calculator. 9 | * Add the modulus (%) operator and provisions for negative numbers. */ 10 | 11 | #include 12 | #include /* for atof() */ 13 | #include 14 | #include 15 | 16 | #define MAXOP 100 /* max size of operand or operator */ 17 | #define NUMBER '0' /* signal that a number was found */ 18 | #define SIN '1' 19 | #define COS '2' 20 | #define EXP '3' 21 | #define POW '4' 22 | 23 | int getop(char []); 24 | void push(double); 25 | double pop(void); 26 | int strcmp(char s1[], char s2[]); 27 | 28 | /* reverse Polish Calculator */ 29 | main() 30 | { 31 | int type; 32 | double op2; 33 | char s[MAXOP]; 34 | 35 | while ((type = getop(s)) != EOF) { 36 | switch(type){ 37 | case NUMBER: 38 | push(atof(s)); 39 | break; 40 | case '+': 41 | push(pop() + pop()); 42 | break; 43 | case '*': 44 | push(pop() * pop()); 45 | break; 46 | case '-': 47 | op2 = pop(); 48 | push(pop() - op2); 49 | break; 50 | case '/': 51 | op2 = pop(); 52 | if (op2 != 0.0) 53 | push(pop() / op2); 54 | else 55 | printf("error: zero divisor\n"); 56 | break; 57 | case '%': 58 | op2 = pop(); 59 | push ((int) pop() % (int) op2); 60 | break; 61 | case SIN: 62 | push(sin(pop())); 63 | break; 64 | case COS: 65 | push(cos(pop())); 66 | break; 67 | case EXP: 68 | push(exp(pop())); 69 | break; 70 | case POW: 71 | op2 = pop(); 72 | push(pow(pop(), op2)); 73 | break; 74 | case '\n': 75 | printf ("\t%.8g\n", pop()); 76 | break; 77 | default: 78 | printf ("error: unknown command %s", s); 79 | break; 80 | } 81 | } 82 | return 0; 83 | } 84 | 85 | #define MAXVAL 100 /* maximum depth of val stack */ 86 | 87 | int sp = 0; /* next free stack position */ 88 | double val[MAXVAL]; /* value stack */ 89 | 90 | /* push: push f onto value stack */ 91 | void push(double f){ 92 | if (sp < MAXVAL) 93 | val[sp++] = f; 94 | else 95 | printf("error: stack full, can't push %g\n", f); 96 | } 97 | 98 | double pop(void){ 99 | if (sp > 0) 100 | return val[--sp]; 101 | else { 102 | printf("error: stack empty\n"); 103 | return 0.0; 104 | } 105 | } 106 | 107 | #include 108 | 109 | int getch(void); 110 | void ungetch(int); 111 | 112 | /* getop: get next character or numeric operand */ 113 | int getop(char s[]){ 114 | 115 | int c, next, i; 116 | 117 | while ((s[0] = c = getch()) == ' ' || c == '\t') ; 118 | 119 | if (c == '\n' || c == EOF) 120 | return c; 121 | 122 | next = getch(); 123 | ungetch(next); 124 | 125 | if (isdigit(c) || (( c == '+' || c == '-') && isdigit(next))){ 126 | s[i = 0] = c; 127 | while (isdigit(s[++i] = c = getch())) ; 128 | if (c == '.'){ 129 | i++; 130 | while (isdigit(s[++i] = c = getch())) ; 131 | } else { 132 | ungetch(c); 133 | } 134 | s[i] = '\0'; 135 | c = NUMBER; 136 | } else if (c >= 'A' && c <= 'Z'){ 137 | i = 0; 138 | while (isalpha(s[++i] = c = getch())) ; 139 | ungetch(c); 140 | s[i] = '\0'; 141 | if (!strcmp(s, "SIN")){ 142 | return SIN; 143 | } else if (!strcmp(s, "COS")){ 144 | return COS; 145 | } else if (!strcmp(s, "EXP")){ 146 | return EXP; 147 | } else if (!strcmp(s, "POW")){ 148 | return POW; 149 | } else { 150 | printf("error: unknow functions %s\n", s); 151 | } 152 | } else { 153 | s[0] = c; 154 | s[1] = '\0'; 155 | } 156 | return c; 157 | } 158 | 159 | #define BUFSIZE 100 160 | 161 | char buf[BUFSIZE]; /* buffer for ungetch */ 162 | int bufp = 0; /* next gree position in buf */ 163 | 164 | int getch(void) /* get a (possibly pushed-back) character */ 165 | { 166 | return (bufp > 0) ? buf[--bufp] : getchar(); 167 | } 168 | 169 | void ungetch(int c) /* get character back on input */ 170 | { 171 | if (bufp >= BUFSIZE) 172 | printf("ungetch: too many characters\n"); 173 | else 174 | buf[bufp++] = c; 175 | } 176 | 177 | int strcmp(char s1[], char s2[]){ 178 | int i, c; 179 | for (i = 0; (c = s1[i] - s2[i]) == 0 && s1[i] != '\0'; i++); 180 | return c; 181 | } 182 | -------------------------------------------------------------------------------- /cap4/exercise.4.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Seg 03 Jan 2011 22:53:21 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-6: Add commands for handling variables. (It's easy to privide twenty-six variables with 9 | * single-letter names) Add a variable for the most recently printed value. */ 10 | 11 | #include 12 | #include /* for atof() */ 13 | #include 14 | #include 15 | 16 | #define MAXOP 100 /* max size of operand or operator */ 17 | #define NUMBER '0' /* signal that a number was found */ 18 | #define NVAR 26 19 | #define SIN '1' 20 | #define COS '2' 21 | #define EXP '3' 22 | #define POW '4' 23 | #define VAR_SET '5' 24 | #define VAR_GET '6' 25 | 26 | int getop(char []); 27 | void push(double); 28 | double pop(void); 29 | double top(void); 30 | int strcmp(char s1[], char s2[]); 31 | 32 | double var[NVAR]; 33 | 34 | /* reverse Polish Calculator */ 35 | main() 36 | { 37 | int type; 38 | double op2; 39 | char s[MAXOP]; 40 | 41 | while ((type = getop(s)) != EOF) { 42 | switch(type){ 43 | case NUMBER: 44 | push(atof(s)); 45 | break; 46 | case '+': 47 | push(pop() + pop()); 48 | break; 49 | case '*': 50 | push(pop() * pop()); 51 | break; 52 | case '-': 53 | op2 = pop(); 54 | push(pop() - op2); 55 | break; 56 | case '/': 57 | op2 = pop(); 58 | if (op2 != 0.0) 59 | push(pop() / op2); 60 | else 61 | printf("error: zero divisor\n"); 62 | break; 63 | case '%': 64 | op2 = pop(); 65 | push ((int) pop() % (int) op2); 66 | break; 67 | case SIN: 68 | push(sin(pop())); 69 | break; 70 | case COS: 71 | push(cos(pop())); 72 | break; 73 | case EXP: 74 | push(exp(pop())); 75 | break; 76 | case POW: 77 | op2 = pop(); 78 | push(pow(pop(), op2)); 79 | break; 80 | case VAR_SET: 81 | var[s[0] - 'A'] = top(); 82 | break; 83 | case VAR_GET: 84 | push(var[s[0] - 'a']); 85 | break; 86 | case '\n': 87 | printf ("\t%.8g\n", op2 = pop()); 88 | var['R' - 'A'] = op2; 89 | break; 90 | default: 91 | printf ("error: unknown command %s", s); 92 | break; 93 | } 94 | } 95 | return 0; 96 | } 97 | 98 | #define MAXVAL 100 /* maximum depth of val stack */ 99 | 100 | int sp = 0; /* next free stack position */ 101 | double val[MAXVAL]; /* value stack */ 102 | 103 | /* push: push f onto value stack */ 104 | void push(double f){ 105 | if (sp < MAXVAL) 106 | val[sp++] = f; 107 | else 108 | printf("error: stack full, can't push %g\n", f); 109 | } 110 | 111 | double pop(void){ 112 | if (sp > 0) 113 | return val[--sp]; 114 | else { 115 | printf("error: stack empty\n"); 116 | return 0.0; 117 | } 118 | } 119 | 120 | double top(void){ 121 | if (sp > 0){ 122 | return val[sp - 1]; 123 | } else{ 124 | printf("error: stack empty\n"); 125 | return 0.0; 126 | } 127 | } 128 | 129 | #include 130 | 131 | int getch(void); 132 | void ungetch(int); 133 | 134 | /* getop: get next character or numeric operand */ 135 | int getop(char s[]){ 136 | 137 | int c, next, i; 138 | 139 | while ((s[0] = c = getch()) == ' ' || c == '\t') ; 140 | 141 | if (c == '\n' || c == EOF) 142 | return c; 143 | 144 | next = getch(); 145 | ungetch(next); 146 | 147 | if (isdigit(c) || (( c == '+' || c == '-') && isdigit(next))){ 148 | s[i = 0] = c; 149 | while (isdigit(s[++i] = c = getch())) ; 150 | if (c == '.'){ 151 | while (isdigit(s[++i] = c = getch())) ; 152 | } else { 153 | ungetch(c); 154 | } 155 | s[i] = '\0'; 156 | c = NUMBER; 157 | } else if (isalpha(c)){ 158 | i = 0; 159 | while (isalpha(s[++i] = c = getch())) ; 160 | ungetch(c); 161 | s[i] = '\0'; 162 | if (i > 1){ 163 | if (!strcmp(s, "SIN")){ 164 | return SIN; 165 | } else if (!strcmp(s, "COS")){ 166 | return COS; 167 | } else if (!strcmp(s, "EXP")){ 168 | return EXP; 169 | } else if (!strcmp(s, "POW")){ 170 | return POW; 171 | } else { 172 | printf("error: unknow functions %s\n", s); 173 | } 174 | } else { 175 | if (islower(s[0])) 176 | return VAR_GET; 177 | else 178 | return VAR_SET; 179 | } 180 | } else { 181 | s[0] = c; 182 | s[1] = '\0'; 183 | } 184 | return c; 185 | } 186 | 187 | #define BUFSIZE 100 188 | 189 | char buf[BUFSIZE]; /* buffer for ungetch */ 190 | int bufp = 0; /* next gree position in buf */ 191 | 192 | int getch(void) /* get a (possibly pushed-back) character */ 193 | { 194 | return (bufp > 0) ? buf[--bufp] : getchar(); 195 | } 196 | 197 | void ungetch(int c) /* get character back on input */ 198 | { 199 | if (bufp >= BUFSIZE) 200 | printf("ungetch: too many characters\n"); 201 | else 202 | buf[bufp++] = c; 203 | } 204 | 205 | int strcmp(char s1[], char s2[]){ 206 | int i, c; 207 | for (i = 0; (c = s1[i] - s2[i]) == 0 && s1[i] != '\0'; i++); 208 | return c; 209 | } 210 | -------------------------------------------------------------------------------- /cap4/exercise.4.7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 05 Jan 2011 15:42:53 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | int getch(void); 12 | 13 | void _gets(char s[]) { 14 | int i = 0, c; 15 | while ((s[i++] = c = getch()) != '\n' && c != EOF) ; 16 | s[i] = '\0'; 17 | } 18 | 19 | #define BUFSIZE 100 20 | 21 | char buf[BUFSIZE]; /* buffer for ungetch */ 22 | int bufp = 0; /* next gree position in buf */ 23 | 24 | int getch(void) /* get a (possibly pushed-back) character */ 25 | { 26 | return (bufp > 0) ? buf[--bufp] : getchar(); 27 | } 28 | 29 | void ungetch(int c) /* get character back on input */ 30 | { 31 | if (bufp >= BUFSIZE) 32 | printf("ungetch: too many characters\n"); 33 | else 34 | buf[bufp++] = c; 35 | } 36 | 37 | void un_gets(char s[]){ 38 | int i; 39 | if (BUFSIZE - bufp < strlen(s)) { 40 | printf("un_gets: too many characters\n"); 41 | } else{ 42 | for (i = strlen(s) - 1; i >= 0 && bufp < BUFSIZE; i--){ 43 | buf[bufp++] = s[i]; 44 | } 45 | } 46 | } 47 | 48 | int main (int argc, char const* argv[]) 49 | { 50 | char s[255]; 51 | 52 | _gets(s); 53 | printf("%s", s); 54 | un_gets(s); 55 | _gets(s); 56 | printf("%s", s); 57 | _gets(s); 58 | printf("%s", s); 59 | un_gets(s); 60 | _gets(s); 61 | printf("%s", s); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /cap4/exercise.4.8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 05 Jan 2011 16:09:36 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | 9 | /* Exercise 4-8: Suppose that thre will never be more than on character of 10 | * pushback. Modify getch and ungetch accordingly. */ 11 | 12 | 13 | #define EMPTY -2 14 | 15 | int buf = EMPTY; 16 | 17 | int getch(void){ 18 | int c; 19 | c = (buf != EMPTY)? buf : getchar(); 20 | buf = EMPTY; 21 | return c; 22 | } 23 | 24 | void ungetch(int c){ 25 | buf = c; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /cap4/exercise.4.9.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qua 05 Jan 2011 16:19:28 BRST 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 4-9: Our getch and ungetch do not handle a pushed-back EOF 9 | * correctly. Decide what their properties ought to be if an EOF is pushed 10 | * back, then implement your design */ 11 | 12 | #define BUFSIZE 100 13 | 14 | int buf[BUFSIZE]; 15 | int bufp = 0; 16 | 17 | int getch(void){ 18 | return (buf > 0) ? buf[--bufp] : getchar(); 19 | } 20 | 21 | void ungetch(int c){ 22 | if (bufp >= BUFSIZE) 23 | printf("ungetch: too many characters\n"); 24 | else 25 | buf[bufp++] = c; 26 | } 27 | -------------------------------------------------------------------------------- /cap5/dcl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-19T14:44:52 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAXTOKEN 100 12 | 13 | enum {NAME, PARENS, BRACKETS}; 14 | 15 | int tokentype; /* type of last token */ 16 | char token[MAXTOKEN]; /* last token string */ 17 | char name[MAXTOKEN]; /* identifier namme */ 18 | char datatype[MAXTOKEN]; /* data type = char, int , etc. */ 19 | char out[1000]; 20 | 21 | #define BUFSIZE 100 22 | 23 | int buffer[BUFSIZE]; 24 | int bufp = 0; 25 | 26 | int getch(void) 27 | { 28 | return (bufp > 0) ? buffer[--bufp] : getchar(); 29 | } 30 | 31 | void ungetch(int c) 32 | { 33 | if (bufp < BUFSIZE) 34 | buffer[bufp++] = c; 35 | else 36 | printf ("error: buffer is full\n"); 37 | } 38 | 39 | int gettoken(void) /* return next token */ 40 | { 41 | int c; 42 | char *p = token; 43 | 44 | while ((c = getch()) == ' ' || c == '\t') ; 45 | 46 | if (c == '(') { 47 | if ((c = getch()) == ')') { 48 | strcpy(token, "()"); 49 | return tokentype = PARENS; 50 | } else { 51 | ungetch(c); 52 | return tokentype = '('; 53 | } 54 | } else if (c == '[') { 55 | for (*p++ = c; (*p++ = getch()) != ']'; ) ; 56 | *p = '\0'; 57 | return tokentype = BRACKETS; 58 | } else if (isalpha(c)) { 59 | for (*p++ = c; isalnum(c = getch()); ) 60 | *p++ = c; 61 | *p = '\0'; 62 | ungetch(c); 63 | return tokentype = NAME; 64 | } else 65 | return tokentype = c; 66 | } 67 | 68 | void dirdcl(void); 69 | 70 | /* dcl: parse a declarator */ 71 | void dcl(void) 72 | { 73 | int ns; 74 | 75 | for (ns = 0; gettoken() == '*'; ) /* count *'s */ 76 | ns++; 77 | dirdcl(); 78 | while (ns-- > 0) 79 | strcat(out, " pointer to"); 80 | } 81 | 82 | /* dirdcl: parse a direct declarator */ 83 | void dirdcl(void) 84 | { 85 | int type; 86 | 87 | if (tokentype == '(') { /* (dcl) */ 88 | dcl(); 89 | if (tokentype != ')') 90 | printf ("error: missing )\n"); 91 | } else if (tokentype == NAME) { 92 | strcpy(name, token); 93 | } else { 94 | printf ("error: expected name or (dcl)\n"); 95 | } 96 | 97 | while ((type = gettoken()) == PARENS || type == BRACKETS) 98 | if (type == PARENS) 99 | strcat(out, " function returning"); 100 | else { 101 | strcat(out, " array"); 102 | strcat(out, token); 103 | strcat(out, " of"); 104 | } 105 | } 106 | 107 | 108 | int main(int argc, char *argv[]) 109 | { 110 | while (gettoken() != EOF) { /* 1st token on line */ 111 | strcpy(datatype, token); /* is the datatype */ 112 | out[0] = '\0'; 113 | dcl(); /* parse rest of line */ 114 | if (tokentype != '\n') 115 | printf ("syntax error\n"); 116 | printf ("%s: %s %s\n", name, out, datatype); 117 | } 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /cap5/exercise.5.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-07T17:13:39 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* As written, getint treats a + or - not followed by a digit as a valid 8 | * representation of zero. Fiz it to push such a character back on the input. */ 9 | 10 | #include 11 | #include 12 | 13 | int getch(void); 14 | void ungetch(int); 15 | 16 | /* getint: get next integer from input int *pn */ 17 | int getint (int *pn) 18 | { 19 | int c, sign, aux; 20 | 21 | while (isspace(c = getch())) ; 22 | 23 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 24 | ungetch (c); 25 | return 0; 26 | } 27 | 28 | sign = (c == '-') ? -1 : 1; 29 | if (c == '+' || c == '-') { 30 | aux = c; 31 | while (isspace(c = getch())) ; 32 | if (!isdigit(c)) { 33 | ungetch(c); 34 | ungetch(aux); 35 | return 0; 36 | } 37 | } 38 | 39 | for (*pn = 0; isdigit(c); c = getch()) 40 | *pn = 10 * *pn + (c - '0'); 41 | *pn *= sign; 42 | if (c != EOF) 43 | ungetch(c); 44 | return c; 45 | } 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | int n, c; 50 | while ((c = getint(&n)) != EOF && c != 0) 51 | printf ("%d\n", n); 52 | if (!c) 53 | printf ("error: input is not a number\n"); 54 | return 0; 55 | } 56 | 57 | 58 | #define BUFSIZE 100 59 | 60 | int buffer[BUFSIZE]; 61 | int bufp = 0; 62 | 63 | int getch(void) 64 | { 65 | return (bufp > 0) ? buffer[--bufp] : getchar(); 66 | } 67 | 68 | void ungetch(int c) 69 | { 70 | if (bufp < BUFSIZE) 71 | buffer[bufp++] = c; 72 | else 73 | printf ("error: buffer is full\n"); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /cap5/exercise.5.10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T19:06:34 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-10: Write the program expr, which evaluates a reverse Polish 8 | * expression from the command line, where each operator or operand is a separate argument. */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #define NUMBER '0' 15 | 16 | double pop(void); 17 | void push(double); 18 | int getop(char *); 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | int c; 23 | double op2; 24 | 25 | while (--argc > 0) { 26 | switch (c = getop(*++argv)) { 27 | case NUMBER: 28 | push(atof(*argv)); 29 | break; 30 | case '+': 31 | push(pop() + pop()); 32 | break; 33 | case '*': 34 | push(pop() * pop()); 35 | break; 36 | case '-': 37 | op2 = pop(); 38 | push(pop() - op2); 39 | break; 40 | case '/': 41 | op2 = pop(); 42 | if (op2 != 0) 43 | push(pop() / op2); 44 | else 45 | printf ("error: division by zero\n"); 46 | break; 47 | default: 48 | printf ("error: invalid operation %c\n", c); 49 | return 1; 50 | break; 51 | } 52 | } 53 | printf ("\t%f\n", pop()); 54 | return 0; 55 | } 56 | 57 | int getop(char *s) 58 | { 59 | if (!isdigit(s[0]) && s[1] == '\0') 60 | return s[0]; 61 | return NUMBER; 62 | } 63 | 64 | #define STACKSIZE 10000 65 | 66 | double val[STACKSIZE]; /* stack value */ 67 | int sp = 0; /* stack position: next free position */ 68 | 69 | double pop(void) 70 | { 71 | if (sp > 0) 72 | return val[--sp]; 73 | else 74 | printf ("error: empty stack\n"); 75 | return 0.0; 76 | } 77 | 78 | void push(double f) 79 | { 80 | if (sp < STACKSIZE) 81 | val[sp++] = f; 82 | else 83 | printf ("error: full stack\n"); 84 | } 85 | -------------------------------------------------------------------------------- /cap5/exercise.5.11-part1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T20:07:31 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-11: Modify the program entab and detab (written as exercises in 8 | * Chapter 1) to accept a list of tab stops as arguments. Use the default tab settings 9 | * if there are no arguments */ 10 | 11 | #include 12 | #include 13 | 14 | void insert_ts(int ts); 15 | 16 | #define MAXLEN 1000 17 | 18 | void display_line(char *); 19 | 20 | int _getline(char s[], int limits) 21 | { 22 | int i, c; 23 | for (i = 0; i < limits - 1 && (c = s[i] = getchar()) != EOF && c != '\n'; ++i) ; 24 | if (c == '\n') 25 | i++; 26 | s[i] = '\0'; 27 | return i; 28 | } 29 | 30 | 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | char line[MAXLEN]; 35 | 36 | while (--argc > 0) 37 | insert_ts(atoi(*++argv)); 38 | while (_getline(line, MAXLEN) > 0) { 39 | display_line(line); 40 | } 41 | return 0; 42 | } 43 | 44 | int insert_tab(int); 45 | 46 | void display_line(char *s) 47 | { 48 | int i, cur; 49 | for (i = 0, cur = 0; s[i] != '\0'; i++){ 50 | if (s[i] == '\t') 51 | cur = insert_tab(cur); 52 | else { 53 | putchar(s[i]); 54 | cur++; 55 | } 56 | } 57 | } 58 | 59 | #define MAXTS 100 60 | int tab_stop[MAXTS]; 61 | int nts = 0; /* next free tab stop index */ 62 | 63 | void insert_ts(int ts) 64 | { 65 | tab_stop[nts++] = ts; 66 | } 67 | 68 | #define DEFAULT_TS 4; 69 | 70 | int insert_tab(int cur) 71 | { 72 | int i, ts; 73 | 74 | for (i = 0; i < nts && tab_stop[i] <= cur; i++) ; 75 | 76 | ts = tab_stop[i]; 77 | if (nts == i){ 78 | ts = (nts != 0) ? tab_stop[nts - 1] : 0; 79 | while (ts <= cur) 80 | ts += DEFAULT_TS; 81 | } 82 | 83 | for (; cur < ts; cur++) 84 | putchar(' '); 85 | return cur; 86 | } 87 | -------------------------------------------------------------------------------- /cap5/exercise.5.11-part2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T22:13:27 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-11: Modify the program entab and detab (written as exercises in 8 | * Chapter 1) to accept a list of tab stops as arguments. Use the default tab settings 9 | * if there are no arguments */ 10 | 11 | #include 12 | #include 13 | 14 | void insert_ts(int ts); 15 | 16 | #define MAXLEN 1000 17 | 18 | void display_line(char *); 19 | 20 | int _getline(char s[], int limits) 21 | { 22 | int i, c; 23 | for (i = 0; i < limits - 1 && (c = s[i] = getchar()) != EOF && c != '\n'; ++i) ; 24 | if (c == '\n') 25 | i++; 26 | s[i] = '\0'; 27 | return i; 28 | } 29 | 30 | int next_ts(int cur); 31 | 32 | void detab(char *s) 33 | { 34 | int i, j, k, ts; 35 | 36 | for (i = 0, j = 0; s[i] != '\0'; j++) { 37 | if (s[i] != ' ') { 38 | s[j] = s[i++]; 39 | } else { 40 | k = i + 1; 41 | while (s[k] == ' ') k++; 42 | while ((ts = next_ts(i)) <= k) { 43 | i = ts; 44 | s[j++] = '\t'; 45 | } 46 | for (; i < k; ++i) { 47 | s[j++] = ' '; 48 | } 49 | j--; 50 | } 51 | } 52 | s[j] = '\0'; 53 | } 54 | 55 | void show_line(char *s) 56 | { 57 | int i; 58 | for (i = 0; s[i] != '\0'; ++i) { 59 | if (s[i] == '\t') 60 | printf ("\\t"); 61 | else 62 | putchar(s[i]); 63 | } 64 | } 65 | 66 | int main(int argc, char *argv[]) 67 | { 68 | char line[MAXLEN]; 69 | 70 | while (--argc > 0) 71 | insert_ts(atoi(*++argv)); 72 | while (_getline(line, MAXLEN) > 0) { 73 | detab(line); 74 | show_line(line); 75 | } 76 | return 0; 77 | } 78 | 79 | 80 | 81 | #define MAXTS 100 82 | int tab_stop[MAXTS]; 83 | int nts = 0; /* next free tab stop index */ 84 | 85 | void insert_ts(int ts) 86 | { 87 | tab_stop[nts++] = ts; 88 | } 89 | 90 | #define DEFAULT_TS 4 91 | 92 | int next_ts(int cur) 93 | { 94 | int i, ts; 95 | for (i = 0; i < nts && tab_stop[i] <= cur; i++) ; 96 | 97 | ts = tab_stop[i]; 98 | if (i == nts) { 99 | ts = (nts == 0) ? 0 : tab_stop[nts - 1]; 100 | for ( ; ts <= cur; ts += DEFAULT_TS ); 101 | } 102 | return ts; 103 | } 104 | -------------------------------------------------------------------------------- /cap5/exercise.5.12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T23:16:10 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-12: Extend entab and detab to accept the shorthand 8 | * 9 | * entab -m +n 10 | * 11 | * to mean tab stops every n columns, starting at column m. Choose convenient (for the user) 12 | * default behavior */ 13 | 14 | #include 15 | #include 16 | 17 | #define MAXTS 100 18 | 19 | int col_start = 2000; 20 | int ts_step; 21 | int tab_stop[MAXTS]; 22 | int nts = 0; 23 | 24 | void getopt(int argc, char *argv[]) 25 | { 26 | while (--argc > 0) { 27 | switch ((*++argv)[0]) { 28 | case '-': 29 | col_start = atoi(*argv + 1); 30 | break; 31 | case '+': 32 | ts_step = atoi(*argv + 1); 33 | break; 34 | default: 35 | tab_stop[nts++] = atoi(*argv); 36 | break; 37 | } 38 | } 39 | } 40 | 41 | int _getline(char s[], int limits) 42 | { 43 | int i; 44 | for (i = 0; i < limits - 1 && (s[i] = getchar()) != EOF && s[i] != '\n'; i++) ; 45 | s[i] = '\0'; 46 | return i; 47 | } 48 | 49 | #define TS 4 50 | 51 | int next_ts(int cur) 52 | { 53 | int i, ts; 54 | 55 | for (i = 0; i < nts && tab_stop[i] <= cur; i++); 56 | 57 | if (i < nts) 58 | return tab_stop[i]; 59 | 60 | if (cur < col_start) { 61 | ts = (nts == 0) ? 0 : tab_stop[nts - 1]; 62 | for ( ; ts < cur; ts += TS); 63 | } else { 64 | ts = (nts == 0) ? 0 : tab_stop[nts - 1]; 65 | for ( ; ts < col_start; ts += TS) ; 66 | for ( ; ts <= cur; ts += ts_step) ; 67 | } 68 | return ts; 69 | } 70 | 71 | void printline(char s[]) 72 | { 73 | int cur, newcur; 74 | int i; 75 | 76 | for (i = 0, cur = 0; s[i] != '\0'; ++i) { 77 | if (s[i] == '\t') 78 | for (newcur = next_ts(cur); cur < newcur; cur++) 79 | putchar(' '); 80 | else { 81 | putchar(s[i]); 82 | cur++; 83 | } 84 | } 85 | putchar('\n'); 86 | } 87 | 88 | #define MAXLEN 1000 89 | 90 | int main(int argc, char *argv[]) 91 | { 92 | char line[MAXLEN]; 93 | 94 | getopt(argc, argv); 95 | while (_getline(line, MAXLEN) > 0) 96 | printline(line); 97 | return 0; 98 | } 99 | 100 | -------------------------------------------------------------------------------- /cap5/exercise.5.13.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-18T15:35:23 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | 8 | /* Exercise 5-13: Write a program tail, which prints the last n line of its input. 9 | * By default, n is set to 10, let us say, but it can be changed by an optional 10 | * argument so that 11 | 12 | tail -n 13 | 14 | * prints the last n lines. The program should behave rationally no matter how unreasonable 15 | * the input or the value of n. Write the program so it makes the best use of available storage; lines 16 | * should be stored as in the sorting program of Section 5.6, not in a two-dimensional array of fixed 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define MAXLINES 1000 24 | 25 | char *readline(void); 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | int nlines = 10; 30 | char *lines[MAXLINES]; 31 | char *line; 32 | int i; 33 | 34 | if (argc == 2) { 35 | nlines = atoi (argv[1]); 36 | nlines = -nlines; 37 | } 38 | 39 | while ((line = readline()) != NULL) { 40 | 41 | free(lines[0]); 42 | for (i = 0; i < nlines - 1; i++) { 43 | lines[i] = lines[i + 1]; 44 | } 45 | lines[nlines - 1] = line; 46 | } 47 | 48 | for (i = 0; i < nlines; i++) 49 | if (lines[i] != NULL) 50 | printf ("%s", lines[i]); 51 | return 0; 52 | } 53 | 54 | int _getline(char s[], int limits) 55 | { 56 | int i; 57 | for (i = 0; i < limits - 1 && (s[i] = getchar()) != EOF && s[i] != '\n'; i++) ; 58 | if (s[i] == '\n') 59 | i++; 60 | s[i] = '\0'; 61 | return i; 62 | } 63 | 64 | #define MAXLEN 1000 65 | 66 | char *readline(void) 67 | { 68 | char buf[MAXLEN]; 69 | int len; 70 | char *line; 71 | 72 | len = _getline(buf, MAXLEN); 73 | 74 | if (len == 0) 75 | return NULL; 76 | 77 | line = malloc((len + 1) * sizeof(char)); 78 | strcpy(line, buf); 79 | return line; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /cap5/exercise.5.14.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-18T18:16:45 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-14: Modify the sort program to handle a -r flag, which indicates 8 | * sorting in reverse (decreasing) order. Be sure that -r works with -n. */ 9 | 10 | #include 11 | #include 12 | 13 | #define MAXLINES 500 /* max #lines to be sorted */ 14 | 15 | char *lineptr[MAXLINES]; /* pointers to text lines */ 16 | 17 | int readlines(char *lineptr[], int nlines); 18 | void writelines(char *lineptr[], int nlines); 19 | 20 | void _qsort(void *lineptr[], int left, int right, int (*comp) (void *, void *)); 21 | 22 | int numcmp(char *, char *); 23 | int rnumcmp(char *s1, char *s2); 24 | int rstrcmp(char *s1, char *s2); 25 | 26 | void getop(int argc, char *argv[], int *n, int *r) 27 | { 28 | int c; 29 | while (--argc > 0) { 30 | if ((*++argv)[0] == '-') { 31 | while ( (c = *++argv[0]) != '\0') { 32 | switch(c){ 33 | case 'r': 34 | *r = 1; 35 | break; 36 | case 'n': 37 | *n = 1; 38 | break; 39 | default: 40 | printf ("error: unknow option %c\n", c); 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | /* sort input lines */ 49 | int main(int argc, char *argv[]) 50 | { 51 | int nlines; /* number of input lines read */ 52 | int numeric = 0; /* 1 if numeric sort */ 53 | int reverse = 0; /* 1 if reverset sort */ 54 | 55 | getop(argc, argv, &numeric, &reverse); 56 | 57 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 58 | if (numeric){ 59 | if (reverse) { 60 | _qsort((void**) lineptr, 0, nlines - 1, (int (*) (void *, void *)) rnumcmp); 61 | } else { 62 | _qsort((void**) lineptr, 0, nlines - 1, (int (*) (void *, void *)) numcmp); 63 | } 64 | } else { 65 | if (reverse) { 66 | _qsort((void**) lineptr, 0, nlines - 1, (int (*) (void *, void *)) rstrcmp); 67 | } else { 68 | _qsort((void**) lineptr, 0, nlines - 1, (int (*) (void *, void *)) strcmp); 69 | } 70 | } 71 | 72 | writelines (lineptr, nlines); 73 | return 0; 74 | } else { 75 | printf ("input too big to sort\n"); 76 | return 1; 77 | } 78 | } 79 | 80 | /* qsort: sort v[left]...v[right] into increasing order */ 81 | void _qsort(void *v[], int left, int right, int (*comp) (void *, void *)) 82 | { 83 | int i, last; 84 | void swap(void *v[], int, int); 85 | 86 | if (left >= right) /* do nothing if array contains */ 87 | return ; /* fewer than two elements */ 88 | swap(v, left, (left + right) / 2); 89 | last = left; 90 | for (i = left + 1; i <= right; i++) { 91 | if ((*comp) (v[i], v[left]) < 0) 92 | swap(v, ++last, i); 93 | } 94 | swap(v, left, last); 95 | _qsort(v, left, last - 1, comp); 96 | _qsort(v, last + 1, right, comp); 97 | } 98 | 99 | void swap(void *v[], int i, int j) 100 | { 101 | void *temp; 102 | 103 | temp = v[i]; 104 | v[i] = v[j]; 105 | v[j] = temp; 106 | } 107 | 108 | #include 109 | 110 | /* numcmp: compare s1 and s2 numerically */ 111 | int numcmp(char *s1, char *s2) 112 | { 113 | double v1, v2; 114 | v1 = atof(s1); 115 | v2 = atof(s2); 116 | return v1 - v2; 117 | } 118 | 119 | int rnumcmp(char *s1, char *s2) 120 | { 121 | return -numcmp(s1, s2); 122 | 123 | } 124 | 125 | int rstrcmp(char *s1, char *s2) 126 | { 127 | return -strcmp(s1, s2); 128 | } 129 | 130 | int _getline(char s[], int limits) 131 | { 132 | int i; 133 | for (i = 0; i < limits - 1 && (s[i] = getchar()) != EOF && s[i] != '\n'; i++) ; 134 | if (s[i] == '\n') 135 | i++; 136 | s[i] = '\0'; 137 | return i; 138 | } 139 | 140 | #define MAXLEN 1000 141 | 142 | char *alloc(int n); 143 | 144 | /* readlines: read input lines */ 145 | int readlines(char *lineptr[], int maxlines) 146 | { 147 | int len, nlines; 148 | char *p, line[MAXLEN]; 149 | 150 | nlines = 0; 151 | while ((len = _getline(line, MAXLEN)) > 0) 152 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 153 | return -1; 154 | else { 155 | line[len - 1] = '\0'; /* delete newline */ 156 | strcpy (p, line); 157 | lineptr[nlines++] = p; 158 | } 159 | return nlines; 160 | } 161 | 162 | /* writelines: write output lines */ 163 | void writelines(char *lineptr[], int nlines) 164 | { 165 | int i; 166 | for (i = 0; i < nlines; i++) 167 | printf ("%s\n", lineptr[i]); 168 | } 169 | 170 | #define ALLOCSIZE 10000 /* size of available space */ 171 | 172 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 173 | static char *allocp = allocbuf; /* next free position */ 174 | 175 | char *alloc(int n) /* return pointer to n characters */ 176 | { 177 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 178 | allocp += n; 179 | return allocp - n; /* old p */ 180 | } else 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /cap5/exercise.5.15.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-18T20:00:23 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-15: Add the option -f to fold upper and lower case together, 8 | * so that casa distinctions are not made during sorting; for example, a and 9 | * A compare equal */ 10 | 11 | #include 12 | #include 13 | 14 | #define MAXLINES 500 /* max #lines to be sorted */ 15 | 16 | char *lineptr[MAXLINES]; /* pointers to text lines */ 17 | 18 | int readlines(char *lineptr[], int nlines); 19 | void writelines(char *lineptr[], int nlines); 20 | 21 | void _qsort(void *lineptr[], int left, int right, int (*comp) (void *, void *)); 22 | 23 | int numcmp(char *, char *); 24 | int rnumcmp(char *s1, char *s2); 25 | int rstrcmp(char *s1, char *s2); 26 | int fstrcmp(char *s1, char *s2); 27 | int rfstrcmp(char *s1, char *s2); 28 | 29 | void getop(int argc, char *argv[], int *n, int *r, int *f) 30 | { 31 | int c; 32 | 33 | *n = *r = *f = 0; 34 | 35 | while (--argc > 0) { 36 | if ((*++argv)[0] == '-') { 37 | while ( (c = *++argv[0]) != '\0') { 38 | switch(c){ 39 | case 'r': 40 | *r = 1; 41 | break; 42 | case 'n': 43 | *n = 1; 44 | break; 45 | case 'f': 46 | *f = 1; 47 | break; 48 | default: 49 | printf ("error: unknow option %c\n", c); 50 | break; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | void* select_function(int n, int r, int f) 58 | { 59 | 60 | if (n) { 61 | return (r) ? rnumcmp : numcmp; 62 | } else { 63 | if (!f) { 64 | return (r) ? rstrcmp : (int (*) (char *, char *)) strcmp; 65 | } else { 66 | return (r) ? rfstrcmp : fstrcmp; 67 | } 68 | } 69 | } 70 | 71 | 72 | /* sort input lines */ 73 | int main(int argc, char *argv[]) 74 | { 75 | int nlines; /* number of input lines read */ 76 | int numeric = 0; /* 1 if numeric sort */ 77 | int reverse = 0; /* 1 if reverset sort */ 78 | int fold; 79 | 80 | getop(argc, argv, &numeric, &reverse, &fold); 81 | 82 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 83 | _qsort((void**) lineptr, 0, nlines - 1, select_function(numeric, reverse, fold)); 84 | writelines (lineptr, nlines); 85 | return 0; 86 | } else { 87 | printf ("input too big to sort\n"); 88 | return 1; 89 | } 90 | } 91 | 92 | /* qsort: sort v[left]...v[right] into increasing order */ 93 | void _qsort(void *v[], int left, int right, int (*comp) (void *, void *)) 94 | { 95 | int i, last; 96 | void swap(void *v[], int, int); 97 | 98 | if (left >= right) /* do nothing if array contains */ 99 | return ; /* fewer than two elements */ 100 | swap(v, left, (left + right) / 2); 101 | last = left; 102 | for (i = left + 1; i <= right; i++) { 103 | if ((*comp) (v[i], v[left]) < 0) 104 | swap(v, ++last, i); 105 | } 106 | swap(v, left, last); 107 | _qsort(v, left, last - 1, comp); 108 | _qsort(v, last + 1, right, comp); 109 | } 110 | 111 | void swap(void *v[], int i, int j) 112 | { 113 | void *temp; 114 | 115 | temp = v[i]; 116 | v[i] = v[j]; 117 | v[j] = temp; 118 | } 119 | 120 | #include 121 | 122 | /* numcmp: compare s1 and s2 numerically */ 123 | int numcmp(char *s1, char *s2) 124 | { 125 | double v1, v2; 126 | v1 = atof(s1); 127 | v2 = atof(s2); 128 | return v1 - v2; 129 | } 130 | 131 | int rnumcmp(char *s1, char *s2) 132 | { 133 | return -numcmp(s1, s2); 134 | 135 | } 136 | 137 | int rstrcmp(char *s1, char *s2) 138 | { 139 | return -strcmp(s1, s2); 140 | } 141 | 142 | #include 143 | 144 | int fstrcmp(char *s1, char *s2) 145 | { 146 | for ( ; *s1 != '\0' && tolower(*s1) == tolower(*s2); s1++, s2++) ; 147 | return tolower(*s1) - tolower(*s2); 148 | } 149 | 150 | int rfstrcmp(char *s1, char *s2) 151 | { 152 | return -fstrcmp(s1, s2); 153 | } 154 | 155 | int _getline(char s[], int limits) 156 | { 157 | int i; 158 | for (i = 0; i < limits - 1 && (s[i] = getchar()) != EOF && s[i] != '\n'; i++) ; 159 | if (s[i] == '\n') 160 | i++; 161 | s[i] = '\0'; 162 | return i; 163 | } 164 | 165 | #define MAXLEN 1000 166 | 167 | char *alloc(int n); 168 | 169 | /* readlines: read input lines */ 170 | int readlines(char *lineptr[], int maxlines) 171 | { 172 | int len, nlines; 173 | char *p, line[MAXLEN]; 174 | 175 | nlines = 0; 176 | while ((len = _getline(line, MAXLEN)) > 0) 177 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 178 | return -1; 179 | else { 180 | line[len - 1] = '\0'; /* delete newline */ 181 | strcpy (p, line); 182 | lineptr[nlines++] = p; 183 | } 184 | return nlines; 185 | } 186 | 187 | /* writelines: write output lines */ 188 | void writelines(char *lineptr[], int nlines) 189 | { 190 | int i; 191 | for (i = 0; i < nlines; i++) 192 | printf ("%s\n", lineptr[i]); 193 | } 194 | 195 | #define ALLOCSIZE 10000 /* size of available space */ 196 | 197 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 198 | static char *allocp = allocbuf; /* next free position */ 199 | 200 | char *alloc(int n) /* return pointer to n characters */ 201 | { 202 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 203 | allocp += n; 204 | return allocp - n; /* old p */ 205 | } else 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /cap5/exercise.5.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-07T17:50:38 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-2: Write getfloat, the floating-point analog of getint. What type does getfloat 8 | * returns as its function value? */ 9 | 10 | #include 11 | #include 12 | 13 | void ungetch(int); 14 | int getch(void); 15 | 16 | int getfloat(double *n) { 17 | int c, signal, exp, expsign; 18 | double p; 19 | 20 | while (isspace (c = getch())) ; 21 | 22 | if (!isdigit(c) && c != EOF && c != '.' && c != '+' && c != '-') { 23 | ungetch(c); 24 | return 0; 25 | } 26 | 27 | signal = ( c == '-' ) ? -1 : 1; 28 | if (c == '+' || c == '-') 29 | c = getch(); 30 | 31 | for (*n = 0.0; isdigit(c); c = getch()) 32 | *n = *n * 10 + (c - '0'); 33 | 34 | if (c == '.') 35 | c = getch(); 36 | 37 | for (p = 1.0; isdigit(c); c = getch()) { 38 | *n = *n * 10 + (c - '0'); 39 | p *= 10; 40 | } 41 | 42 | *n /= p; 43 | 44 | if (c == 'e' || c == 'E') { 45 | c = getch(); 46 | expsign = (c == '-') ? -1 : 1; 47 | if (c == '-' || c == '+') 48 | c = getch(); 49 | for (exp = 0; isdigit(c); c = getch()) 50 | exp = exp * 10 + (c - '0'); 51 | 52 | *n *= pow(10, exp * expsign); 53 | } 54 | 55 | if (c != EOF) 56 | ungetch(c); 57 | return c; 58 | } 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | int c; 63 | double num; 64 | while ((c = getfloat(&num)) != EOF && c != 0) 65 | printf ("%f\n", num); 66 | if (c == 0) 67 | printf ("error: input is not a number\n"); 68 | return 0; 69 | } 70 | 71 | #define BUFSIZE 100 72 | 73 | int buffer[BUFSIZE]; 74 | int bufp = 0; 75 | 76 | int getch(void) 77 | { 78 | return (bufp > 0) ? buffer[--bufp] : getchar(); 79 | } 80 | 81 | void ungetch(int c) 82 | { 83 | if (bufp < BUFSIZE) 84 | buffer[bufp++] = c; 85 | else 86 | printf ("error: buffer is full\n"); 87 | } 88 | -------------------------------------------------------------------------------- /cap5/exercise.5.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-08T17:29:21 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-3: Write a poiter version of the function strcat that we showed in Chapter 2: 8 | * strcat (s, t) copies the string t to the end of s. */ 9 | 10 | #include 11 | 12 | 13 | void _strcat (char *s, char *t) 14 | { 15 | while (*s != '\0') s++; 16 | while ((*s++ = *t++)) ; 17 | } 18 | 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | char first[50] = "maycon"; 23 | char last[50] = " sambinelli"; 24 | _strcat (first, last); 25 | printf ("%s\n", first); 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /cap5/exercise.5.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-08T17:48:16 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5.4: Write the function strend(s, t), which returns 1 if the string 8 | * t occurs at the end of the string s, and zero otherwise. */ 9 | 10 | #include 11 | 12 | int strend(char *s, char *t) 13 | { 14 | char *p = t; 15 | int nchar; 16 | 17 | while (*p != '\0') p++; 18 | nchar = p - t; 19 | p = s; 20 | while (*p != '\0') 21 | p++; 22 | p = p - nchar; 23 | if ( p < s ) 24 | return 0; 25 | for ( ; *t != '\0'; t++, p++) 26 | if (*t != *p) 27 | return 0; 28 | return 1; 29 | } 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | if (strend("maycon", "maycon")) 34 | printf ("ocorre\n"); 35 | else 36 | printf ("nao ocorre\n"); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /cap5/exercise.5.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-08T19:18:29 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exircise 5-5: Write versions of the library functions strncpy, strncat, and strncmp, which operate on at most 8 | * the first n characters of their argument strings. For example, strncpy(s, t, n) copies at most n characters 9 | * of t to s. Full descriptions are in Appendix B. */ 10 | 11 | #include 12 | 13 | void _strncat(char *s, char *t, int n) 14 | { 15 | int i, c; 16 | while (*s != '\0') s++; 17 | for (i = 0; i < n && (c = *s++ = *t++) != '\0'; i++) ; 18 | 19 | if (c != '\0') 20 | *s = '\0'; 21 | } 22 | 23 | void _strncpy(char *s, char *t, int n) 24 | { 25 | int i, c; 26 | for (i = 0; i < n && (c = *s++ = *t++) != '\0'; i++) ; 27 | if (c != '\0') 28 | *s = '\0'; 29 | } 30 | 31 | int _strncmp(char *s, char *t, int n) 32 | { 33 | int i; 34 | for (i = 0; i < n && *s != '\0'; i++) 35 | if (*s ++ != *t++) 36 | return *--s - *--t; 37 | return (*s == *t) ? 0 : *s - *t; 38 | } 39 | 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | char first[50] = "maycon"; 44 | char last[50] = "maycx"; 45 | int c; 46 | if ((c = _strncmp("z", "yayc", 10)) == 0) 47 | printf ("igual\n"); 48 | else 49 | printf ("diferente\n"); 50 | printf ("diferenca: %d\n", c); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /cap5/exercise.5.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-08T20:06:11 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | 8 | /* Exercise 5-6: Rewrite appropriate programs from earlier chapter and exercises with pointers instead 9 | * of array indexing. Good possibilities include getline (chapter 1 and 4), atoi, itoa, and 10 | * theirs variants (Chapter 2, 3 and 4). reverse (chapter 3), and strindex and getop (chapter 4). */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | void _getline(char *line) 18 | { 19 | int c; 20 | while (( c = *line++ = getchar()) != '\n' && c != EOF) ; 21 | *--line = '\0'; 22 | } 23 | 24 | void do_reverse(char *i, char *j) 25 | { 26 | if ( i < j ) { 27 | int aux = *i; 28 | *i = *j; 29 | *j = aux; 30 | do_reverse(i + 1, j - 1); 31 | } 32 | } 33 | 34 | void reverse(char *s) 35 | { 36 | char *p; 37 | for (p = s; *p != '\0'; p++) ; 38 | do_reverse(s, p - 1); 39 | } 40 | 41 | int _atoi(char *s) 42 | { 43 | int n; 44 | for (n = 0; *s != '\0'; s++) 45 | n = n * 10 + (*s - '0'); 46 | return n; 47 | } 48 | 49 | void itoa(char *s, int n) 50 | { 51 | char *p = s; 52 | int sign = n; 53 | 54 | do { 55 | *p++ = abs(n % 10) + '0'; 56 | } while ((n /= 10)); 57 | 58 | if (sign < 0) 59 | *p++ = '-'; 60 | *p = '\0'; 61 | reverse(s); 62 | } 63 | 64 | char* strindex(char *s, char *t) 65 | { 66 | char *p = s; 67 | while (*p != '\0') 68 | p++; 69 | int nchars = strlen(t); 70 | for (p -= nchars; p >= s; p--) 71 | if (!strncmp(p, t, nchars)) 72 | return p; 73 | return NULL; 74 | } 75 | 76 | char* any(char *s1, char *s2) 77 | { 78 | char *p; 79 | while (*s1 != '\0') { 80 | for (p = s2; *p != '\0' ; p++) { 81 | if (*s1 == *p) { 82 | return s1; 83 | } 84 | } 85 | s1++; 86 | } 87 | return NULL; 88 | } 89 | 90 | double _atof(char *s){ 91 | int i, sign, valexp; 92 | double val, power, exp; 93 | 94 | while (isspace(*s)) 95 | s++; 96 | sign = (*s == '-')? -1: 1; 97 | if (*s == '+' || *s == '-') 98 | s++; 99 | 100 | val = 0.0; 101 | while (isdigit(*s)) 102 | val = val * 10 + (*s++ - '0'); 103 | 104 | if (*s == '.'){ 105 | s++; 106 | power = 1.0; 107 | while (isdigit(*s)){ 108 | val = val * 10 + (*s++ - '0'); 109 | power *= 10; 110 | } 111 | val /= power; 112 | } 113 | 114 | if (*s == 'e' || *s == 'E'){ 115 | s++; 116 | exp = (*s == '-')? 1.0 / 10 : 10; 117 | if (*s == '-' || *s == '+') 118 | s++; 119 | valexp = 0; 120 | while (isdigit(*s)) 121 | valexp = 10 * valexp + (*s++ - '0'); 122 | for (i = 0; i < valexp; i++) 123 | val *= exp; 124 | } 125 | 126 | return val; 127 | } 128 | 129 | 130 | int main(int argc, char *argv[]) 131 | { 132 | char s[50] = " 45e2 abc"; 133 | printf ("%f\n", _atof(s)); 134 | return 0; 135 | } 136 | 137 | -------------------------------------------------------------------------------- /cap5/exercise.5.7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T14:50:22 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Rewrite readline to store lines in an array supplied main, rather than calling alloc 8 | * to maintain storage. How much faster is the program? */ 9 | 10 | #include 11 | #include 12 | 13 | #define MAXLINES 5000 /* max #lines to be sorted */ 14 | 15 | char *lineptr[MAXLINES]; /* pointers to text lines */ 16 | 17 | int readlines(char *lineptr[], char buffer[], int nlines); 18 | void writelines(char *lineptr[], int nlines); 19 | 20 | void qsort(char *lineptr[], int left, int right); 21 | 22 | #define BUFSIZE 1000 /* size of available space */ 23 | 24 | /* sort input lines */ 25 | int main() 26 | { 27 | int nlines; /* number of input lines read */ 28 | char allocbuf[BUFSIZE]; /* storage for alloc */ 29 | 30 | if ((nlines = readlines(lineptr, allocbuf, MAXLINES)) >= 0) { 31 | qsort (lineptr, 0, nlines - 1); 32 | writelines(lineptr, nlines); 33 | return 0; 34 | } else { 35 | printf ("error: input too big to sort\n"); 36 | return 1; 37 | } 38 | } 39 | 40 | /* swap: interchanges v[i] and v[j] */ 41 | void swap (char *v[], int i, int j) 42 | { 43 | char *temp; 44 | 45 | temp = v[i]; 46 | v[i] = v[j]; 47 | v[j] = temp; 48 | } 49 | 50 | /* qsort: sort v[left]...v[right] int increasing order */ 51 | void qsort(char *v[], int left, int right) 52 | { 53 | int i, last; 54 | void swap(char *v[], int i, int j); 55 | 56 | if (left >= right) /* do nothing if array contains */ 57 | return; /* fewer than two elements */ 58 | 59 | swap (v, left, (left + right) / 2); 60 | last = left; 61 | 62 | for (i = left + 1; i <= right; i++) 63 | if (strcmp(v[i], v[left]) < 0) 64 | swap (v, ++last, i); 65 | swap(v, left, last); 66 | qsort(v, left, last - 1); 67 | qsort(v, last + 1, right); 68 | } 69 | 70 | 71 | #define MAXLEN 1000 /* max length of any input line */ 72 | int _getline(char *, int); 73 | 74 | 75 | /* readlines: read input lines */ 76 | int readlines(char *lineptr[], char buffer[], int maxlines) 77 | { 78 | int nlines, len; 79 | char *bufp; /* next free position */ 80 | char line[MAXLEN]; 81 | 82 | nlines = 0; 83 | bufp = buffer; 84 | 85 | while ((len = _getline(line, MAXLEN)) > 0){ 86 | if (buffer + BUFSIZE - bufp < len) 87 | return -1; 88 | line[len - 1] = '\0'; 89 | strcpy(bufp, line); 90 | lineptr[nlines++] = bufp; 91 | bufp += len; 92 | } 93 | return nlines; 94 | } 95 | 96 | /* writelines: write output lines */ 97 | void writelines(char *lineptr[], int nlines) 98 | { 99 | int i; 100 | for (i = 0; i < nlines; ++i) { 101 | printf ("%s\n", lineptr[i]); 102 | } 103 | } 104 | 105 | 106 | /* getline: read a line int s, return lenght */ 107 | int _getline(char s[], int lim) 108 | { 109 | int c, i; 110 | 111 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++) 112 | s[i] = c; 113 | if (c == '\n') 114 | s[i++] = c; 115 | 116 | s[i] = '\0'; 117 | return i; 118 | } 119 | -------------------------------------------------------------------------------- /cap5/exercise.5.8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T15:45:06 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5.8: There is no error checking in day_of_year or month_day. Temedy this defect */ 8 | 9 | #include 10 | 11 | static char daytab[2][13] = { 12 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 13 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 14 | }; 15 | 16 | /* day_of_year: set day of year from month & day */ 17 | int day_of_year(int year, int month, int day) 18 | { 19 | int i, leap; 20 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 21 | 22 | if (year < 0 || month <= 0 || day <= 0 || month > 12 || day > daytab[leap][month]) 23 | return -1; 24 | 25 | for (i = 1; i < month; ++i) { 26 | day += daytab[leap][i]; 27 | } 28 | return day; 29 | } 30 | 31 | /* month_day: set month, day from day of year */ 32 | int month_day(int year, int yearday, int *pmonth, int *pday) 33 | { 34 | int i, leap; 35 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 36 | 37 | if (year < 0 || yearday <= 0 || yearday > (leap ? 366 : 365)) 38 | return -1; 39 | 40 | for (i = 1; yearday > daytab[leap][i]; ++i) { 41 | yearday -= daytab[leap][i]; 42 | } 43 | *pmonth = i; 44 | *pday = yearday; 45 | return 0; 46 | } 47 | 48 | int main(int argc, char *argv[]) 49 | { 50 | int month, pday, error; 51 | printf ("day of year %d\n", error = day_of_year(2011, 2, 29)); 52 | if (error < 0) 53 | printf ("error: invalid parameter\n"); 54 | return 0; 55 | } 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /cap5/exercise.5.9.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-16T16:40:11 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 5-9: Rewrite the routines day_of_year and month_day with pointers 8 | * instead of indexing */ 9 | 10 | #include 11 | #include 12 | 13 | static char *month_names[] = { 14 | "Illegal month", "Jan", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", 15 | "Set", "Out", "Nov", "Dec" 16 | }; 17 | 18 | static char daytab[2][13] = { 19 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 20 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 21 | }; 22 | 23 | /* ismonth: return 1 if parameter is one month, 0 otherwise */ 24 | int ismonth(char *month) 25 | { 26 | int i; 27 | for (i = 1; i < 13; i++) 28 | if (!strcmp(month, month_names[i])) 29 | return 1; 30 | return 0; 31 | } 32 | 33 | int month_idx(char *month) 34 | { 35 | int i; 36 | for (i = 1; i < 13; i++) 37 | if (!strcmp(month, month_names[i])) 38 | return i; 39 | return 0; 40 | } 41 | 42 | /* day_of_year: set day of year from month & day */ 43 | int day_of_year(int year, char *month, int day) 44 | { 45 | int i, leap, idxmonth; 46 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 47 | 48 | if (year < 0 || !ismonth(month) || day <= 0 || day > daytab[leap][(idxmonth = month_idx(month))]) 49 | return -1; 50 | 51 | for (i = 1; i < idxmonth; ++i) { 52 | day += daytab[leap][i]; 53 | } 54 | return day; 55 | } 56 | 57 | /* month_day: set month, day from day of year */ 58 | int month_day(int year, int yearday, char **pmonth, int *pday) 59 | { 60 | int i, leap; 61 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 62 | 63 | if (year < 0 || yearday <= 0 || yearday > (leap ? 366 : 365)) 64 | return -1; 65 | 66 | for (i = 1; yearday > daytab[leap][i]; ++i) { 67 | yearday -= daytab[leap][i]; 68 | } 69 | *pmonth = month_names[i]; 70 | *pday = yearday; 71 | return 1; 72 | } 73 | 74 | int main(int argc, char *argv[]) 75 | { 76 | int month, pday, error; 77 | char *smonth; 78 | printf ("day of year %d\n", error = day_of_year(2011, "MaR", 28)); 79 | if (error < 0) 80 | printf ("error: invalid parameter\n"); 81 | error = month_day(2012, 365, &smonth, &pday); 82 | printf ("month: %s day %d\n", smonth, pday); 83 | if (error < 0) 84 | printf ("error: invalid parameter\n"); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /cap5/sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-14T20:30:10 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #define MAXLINES 5000 /* max #lines to be sorted */ 11 | 12 | char *lineptr[MAXLINES]; /* pointers to text lines */ 13 | 14 | int readlines(char *lineptr[], int nlines); 15 | void writelines(char *lineptr[], int nlines); 16 | 17 | void qsort(char *lineptr[], int left, int right); 18 | 19 | /* sort input lines */ 20 | int main() 21 | { 22 | int nlines; /* number of input lines read */ 23 | 24 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 25 | qsort (lineptr, 0, nlines - 1); 26 | writelines(lineptr, nlines); 27 | return 0; 28 | } else { 29 | printf ("error: input too big to sort\n"); 30 | return 1; 31 | } 32 | } 33 | 34 | /* swap: interchanges v[i] and v[j] */ 35 | void swap (char *v[], int i, int j) 36 | { 37 | char *temp; 38 | 39 | temp = v[i]; 40 | v[i] = v[j]; 41 | v[j] = temp; 42 | } 43 | 44 | /* qsort: sort v[left]...v[right] int increasing order */ 45 | void qsort(char *v[], int left, int right) 46 | { 47 | int i, last; 48 | void swap(char *v[], int i, int j); 49 | 50 | if (left >= right) /* do nothing if array contains */ 51 | return; /* fewer than two elements */ 52 | 53 | swap (v, left, (left + right) / 2); 54 | last = left; 55 | 56 | for (i = left + 1; i <= right; i++) 57 | if (strcmp(v[i], v[left]) < 0) 58 | swap (v, ++last, i); 59 | swap(v, left, last); 60 | qsort(v, left, last - 1); 61 | qsort(v, last + 1, right); 62 | } 63 | 64 | 65 | #define MAXLEN 1000 /* max length of any input line */ 66 | int _getline(char *, int); 67 | 68 | char *alloc(int); 69 | 70 | /* readlines: read input lines */ 71 | int readlines(char *lineptr[], int maxlines) 72 | { 73 | int len, nlines; 74 | char *p, line[MAXLEN]; 75 | 76 | nlines = 0; 77 | while ((len = _getline(line, MAXLEN)) > 0) 78 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 79 | return -1; 80 | else { 81 | line[len - 1] = '\0'; 82 | strcpy(p, line); 83 | lineptr[nlines++] = p; 84 | } 85 | return nlines; 86 | } 87 | 88 | /* writelines: write output lines */ 89 | void writelines(char *lineptr[], int nlines) 90 | { 91 | int i; 92 | for (i = 0; i < nlines; ++i) { 93 | printf ("%s\n", lineptr[i]); 94 | } 95 | } 96 | 97 | 98 | /* getline: read a line int s, return lenght */ 99 | int _getline(char s[], int lim) 100 | { 101 | int c, i; 102 | 103 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++) 104 | s[i] = c; 105 | if (c == '\n') 106 | s[i++] = c; 107 | 108 | s[i] = '\0'; 109 | return i; 110 | } 111 | 112 | #define ALLOCSIZE 1000 /* size of available space */ 113 | 114 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 115 | static char *allocp = allocbuf; /* next free position */ 116 | 117 | char *alloc(int n) /* return pointer to n characters */ 118 | { 119 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 120 | allocp += n; 121 | return allocp - n; /* old p */ 122 | } else /* not enough room */ 123 | return 0; 124 | } 125 | 126 | void afree(char *p) 127 | { 128 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 129 | allocp = p; 130 | } 131 | 132 | 133 | -------------------------------------------------------------------------------- /cap6/exercise.6.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-19T16:38:24 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 6-1: Our version of getword does not properly handle underscores, 8 | * string constants, comments, or preprocessor control lines. Write a better 9 | * version */ 10 | 11 | #include 12 | #include 13 | 14 | void ungetch(int c); 15 | int getch(void); 16 | 17 | void del_space(void) 18 | { 19 | char state = 0; 20 | int c; 21 | 22 | while (state != 2) { 23 | c = getch(); 24 | switch(state) { 25 | case 0: 26 | if (c == '/') 27 | state = 1; 28 | else if (!isspace(c)) { 29 | state = 2; 30 | ungetch(c); 31 | } 32 | break; 33 | case 1: 34 | if (c == '*') 35 | state = 3; 36 | else { 37 | ungetch(c); 38 | ungetch('/'); 39 | state = 2; 40 | } 41 | break; 42 | case 3: 43 | if (c == '*') 44 | state = 4; 45 | break; 46 | case 4: 47 | if (c == '*' || c == '/') { 48 | if (c == '/') 49 | state = 0; 50 | } else 51 | state = 3; 52 | break; 53 | } 54 | } 55 | } 56 | 57 | int getword(char *word, int limits) 58 | { 59 | char *w = word, scaped; 60 | int c; 61 | 62 | del_space(); 63 | 64 | c = *w++ = getch(); 65 | 66 | if (!isalpha(c) && c != '_' && c != '#' && c != '"') { 67 | *w = '\0'; 68 | return c; 69 | } 70 | 71 | if (c != '"') { 72 | for ( ; w < word + limits && (isalnum(*w = c = getch()) || c == '_'); w++) ; 73 | *w = '\0'; 74 | ungetch(c); 75 | return word[0]; 76 | } 77 | 78 | w--; 79 | while (w < word + limits - 1) { 80 | if ((*w++ = c = getch()) == '"' && !scaped) 81 | break; 82 | scaped = 0; 83 | if (c == '\\') { 84 | scaped = 1; 85 | w--; 86 | } 87 | } 88 | 89 | *--w = '\0'; 90 | return word[0]; 91 | } 92 | 93 | int main(int argc, char *argv[]) 94 | { 95 | char word[100]; 96 | 97 | while (getword(word, 100) != EOF) 98 | printf ("%s\n", word); 99 | return 0; 100 | } 101 | 102 | 103 | #define BUFSIZE 100 104 | 105 | int buffer[BUFSIZE]; 106 | int bufp = 0; 107 | 108 | int getch(void) 109 | { 110 | return (bufp > 0) ? buffer[--bufp] : getchar(); 111 | } 112 | 113 | void ungetch(int c) 114 | { 115 | if (bufp < BUFSIZE) 116 | buffer[bufp++] = c; 117 | else 118 | printf ("error: buffer is full\n"); 119 | } 120 | -------------------------------------------------------------------------------- /cap6/exercise.6.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-20T17:45:32 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Write a program that reads a C program and prints in alphabetical 8 | * order each group of variables names that are identical in the first 6 9 | * characters, but different somewhere thereafter. Don't count words within 10 | * string and comments. Make 6 a parameter that can be set from the command line */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct tnode { 18 | struct tlist *list; 19 | char *key; 20 | struct tnode *left; 21 | struct tnode *right; 22 | }; 23 | 24 | struct tlist { 25 | struct tlist *next; 26 | char *word; 27 | }; 28 | 29 | enum { NAME, CSTRING }; 30 | 31 | /* string */ 32 | 33 | char *_strdup(char *s) /* make a duplicate of s */ 34 | { 35 | char *p; 36 | p = (char *) malloc(strlen(s) + 1); /* +1 for '\0' */ 37 | if (p != NULL) 38 | strcpy(p, s); 39 | return p; 40 | } 41 | 42 | /* list */ 43 | 44 | struct tlist *linsert(struct tlist *list, char *word) 45 | { 46 | struct tlist *newlist = (struct tlist*) malloc (sizeof(*list)); 47 | newlist->next = list; 48 | newlist->word = strdup(word); 49 | return newlist; 50 | } 51 | 52 | int lcontains(struct tlist *list, char *w) 53 | { 54 | for ( ; list != NULL; list = list->next) 55 | if (!strcmp(list->word, w)) 56 | return 1; 57 | return 0; 58 | } 59 | 60 | /* tree */ 61 | 62 | struct tnode *addtree(struct tnode *p, char *w, int n) 63 | { 64 | int cond; 65 | if (p == NULL) { 66 | p = (struct tnode*) malloc(sizeof(struct tnode)); 67 | p->list = linsert(NULL, w); 68 | p->key = (char *) malloc (n + 1); 69 | strncpy(p->key, w, n); 70 | p->left = p->right = NULL; 71 | } else if ((cond = strncmp(w, p->key, n)) == 0) { 72 | if (!lcontains(p->list, w)) 73 | p->list = linsert(p->list, w); 74 | } else { 75 | if (cond < 0) 76 | p->left = addtree(p->left, w, n); 77 | else 78 | p->right = addtree(p->right, w, n); 79 | } 80 | return p; 81 | } 82 | 83 | void ungetch(int c); 84 | int getch(void); 85 | 86 | void del_space(void) 87 | { 88 | char state = 0; 89 | int c; 90 | 91 | while (state != 2) { 92 | c = getch(); 93 | switch(state) { 94 | case 0: 95 | if (c == '/') 96 | state = 1; 97 | else if (!isspace(c)) { 98 | state = 2; 99 | ungetch(c); 100 | } 101 | break; 102 | case 1: 103 | if (c == '*') 104 | state = 3; 105 | else { 106 | ungetch(c); 107 | ungetch('/'); 108 | state = 2; 109 | } 110 | break; 111 | case 3: 112 | if (c == '*') 113 | state = 4; 114 | break; 115 | case 4: 116 | if (c == '*' || c == '/') { 117 | if (c == '/') 118 | state = 0; 119 | } else 120 | state = 3; 121 | break; 122 | } 123 | } 124 | } 125 | 126 | int getword(char *word, int limits) 127 | { 128 | char *w = word, scaped = 0; 129 | int c; 130 | 131 | del_space(); 132 | 133 | c = *w++ = getch(); 134 | 135 | if (!isalpha(c) && c != '_' && c != '#' && c != '"') { 136 | *w = '\0'; 137 | return c; 138 | } 139 | 140 | if (c != '"') { 141 | for ( ; w < word + limits && (isalnum(*w = c = getch()) || c == '_'); w++) ; 142 | *w = '\0'; 143 | ungetch(c); 144 | return NAME; 145 | } 146 | 147 | w--; 148 | while (w < word + limits - 1) { 149 | if ((*w++ = c = getch()) == '"' && !scaped) 150 | break; 151 | scaped = 0; 152 | if (c == '\\') { 153 | scaped = 1; 154 | w--; 155 | } 156 | } 157 | 158 | *--w = '\0'; 159 | return CSTRING; 160 | } 161 | 162 | 163 | void display_tree(struct tnode *t) 164 | { 165 | struct tlist *i; 166 | if (t != NULL) { 167 | display_tree(t->left); 168 | printf ("Group %s\n", t->key); 169 | printf ("-------------------\n"); 170 | for (i = t->list; i != NULL; i = i->next) { 171 | printf ("%s ", i->word); 172 | } 173 | printf ("\n\n"); 174 | display_tree(t->right); 175 | } 176 | } 177 | 178 | 179 | 180 | #define MAXWORD 1000 181 | 182 | int main(int argc, char *argv[]) 183 | { 184 | struct tnode *root = NULL; 185 | char word[MAXWORD]; 186 | int c, n = 6; 187 | 188 | if (argc > 1 && (*++argv)[0] == '-') 189 | n = atoi(++*argv); 190 | 191 | while ((c= getword(word, MAXWORD)) != EOF) { 192 | if (c == NAME){ 193 | root = addtree(root, word, n); 194 | } 195 | } 196 | display_tree(root); 197 | return 0; 198 | } 199 | 200 | #define BUFSIZE 100 201 | 202 | int buffer[BUFSIZE]; 203 | int bufp = 0; 204 | 205 | int getch(void) 206 | { 207 | return (bufp > 0) ? buffer[--bufp] : getchar(); 208 | } 209 | 210 | void ungetch(int c) 211 | { 212 | if (bufp < BUFSIZE) 213 | buffer[bufp++] = c; 214 | else 215 | printf ("error: buffer is full\n"); 216 | } 217 | 218 | -------------------------------------------------------------------------------- /cap6/exercise.6.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-21T17:41:02 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 6-3: Write a cross-reference that prints a list of all words in a document 8 | * and for each word, a list of the line numbers on which it occurs. Remove noise words 9 | * like "the", "and" ando so on. */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define MAXLINES 500 16 | 17 | struct tnode { 18 | int nlines[MAXLINES]; 19 | int nfree; 20 | char *word; 21 | struct tnode *left, *right; 22 | }; 23 | 24 | char *black_list[] = { 25 | "the", "on", "in", "is", "he", "she", "it", "we", "us", "my", "a", "an" 26 | }; 27 | 28 | #define WORD 'a' 29 | #define MAXWORD 10000 30 | 31 | void ungetch(int c); 32 | int getch(void); 33 | 34 | int line = 1; 35 | 36 | int getword(char *word, int limits) 37 | { 38 | char *w = word; 39 | int c; 40 | 41 | while (isspace(c = getch())) 42 | if (c == '\n') 43 | line++; 44 | 45 | if (!isalpha(c) && c != '_') 46 | return c; 47 | 48 | for (*w = c; (isalnum(*w) || *w == '_' || *w == '-') && w < word + MAXWORD - 1; *++w = c = getch()) ; 49 | 50 | ungetch(c); 51 | *w = '\0'; 52 | return WORD; 53 | } 54 | 55 | int blacklist(char *w) 56 | { 57 | int nelementos = sizeof black_list / sizeof (char *); 58 | int i; 59 | 60 | for (i = 0; i < nelementos; i++) 61 | if (!strcmp(w, black_list[i])) 62 | return 1; 63 | return 0; 64 | } 65 | 66 | struct tnode *addtree(struct tnode *p, char *w, int line) 67 | { 68 | int cond; 69 | 70 | if (p == NULL) { 71 | p = (struct tnode *) malloc(sizeof(struct tnode)); 72 | p->word = strdup(w); 73 | p->nfree = 1; 74 | p->nlines[0] = line; 75 | p->left = p->right = NULL; 76 | } else if ((cond = strcmp(w, p->word)) == 0) { 77 | if (p->nlines[p->nfree - 1] != line) 78 | p->nlines[p->nfree++] = line; 79 | } else if (cond < 0) { 80 | p->left = addtree(p->left, w, line); 81 | } else { 82 | p->right = addtree(p->right, w, line); 83 | } 84 | return p; 85 | } 86 | 87 | void tree_print(struct tnode *p) 88 | { 89 | int i; 90 | 91 | if (p != NULL) { 92 | tree_print(p->left); 93 | 94 | printf ("%s: ", p->word); 95 | for (i = 0; i < p->nfree; i++) 96 | printf ("%d ", p->nlines[i]); 97 | printf("\n"); 98 | 99 | tree_print(p->right); 100 | } 101 | } 102 | 103 | 104 | int main(int argc, char *argv[]) 105 | { 106 | struct tnode *root = NULL; 107 | char word[MAXWORD]; 108 | 109 | while (getword(word, MAXWORD) != EOF) { 110 | if (!blacklist(word)) 111 | root = addtree(root, word, line); 112 | } 113 | tree_print(root); 114 | return 0; 115 | } 116 | 117 | 118 | #define BUFSIZE 100 119 | 120 | int buffer[BUFSIZE]; 121 | int bufp = 0; 122 | 123 | int getch(void) 124 | { 125 | return (bufp > 0) ? buffer[--bufp] : getchar(); 126 | } 127 | 128 | void ungetch(int c) 129 | { 130 | if (bufp < BUFSIZE) 131 | buffer[bufp++] = c; 132 | else 133 | printf ("error: buffer is full\n"); 134 | } 135 | 136 | -------------------------------------------------------------------------------- /cap6/exercise.6.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-21T18:50:23 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 6-4: write a program that prints the distinct words in its input 8 | * sorted into decreasing order of frequenci of occurrence. Precede each 9 | * word by its count */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define MAXLINES 500 17 | 18 | struct tnode { 19 | int count; 20 | char *word; 21 | struct tnode *left, *right; 22 | }; 23 | 24 | #define WORD 'a' 25 | #define MAXWORD 10000 26 | 27 | void ungetch(int c); 28 | int getch(void); 29 | 30 | int getword(char *word, int limits) 31 | { 32 | char *w = word; 33 | int c; 34 | 35 | while (isspace(c = getch())) ; 36 | 37 | if (!isalpha(c) && c != '_') 38 | return c; 39 | 40 | for (*w = c; (isalnum(*w) || *w == '_' || *w == '-') && w < word + MAXWORD - 1; *++w = c = getch()) ; 41 | 42 | ungetch(c); 43 | *w = '\0'; 44 | return WORD; 45 | } 46 | 47 | struct tnode *addtree(struct tnode *p, char *w) 48 | { 49 | int cond; 50 | 51 | if (p == NULL) { 52 | p = (struct tnode *) malloc(sizeof(struct tnode)); 53 | p->word = strdup(w); 54 | p->count = 1; 55 | p->left = p->right = NULL; 56 | } else if ((cond = strcmp(w, p->word)) == 0) { 57 | p->count++; 58 | } else if (cond < 0) { 59 | p->left = addtree(p->left, w); 60 | } else { 61 | p->right = addtree(p->right, w); 62 | } 63 | return p; 64 | } 65 | 66 | void tree_print(struct tnode *v[], int n) 67 | { 68 | int i; 69 | for (i = 0; i < n; i++) { 70 | printf ("%4d: %s\n", v[i]->count, v[i]->word); 71 | } 72 | } 73 | 74 | void do_tree2vetor(struct tnode *t, struct tnode *v[], int *index) 75 | { 76 | if (t != NULL) { 77 | v[(*index)++] = t; 78 | do_tree2vetor(t->left, v, index); 79 | do_tree2vetor(t->right, v, index); 80 | } 81 | } 82 | 83 | int tree2vetor(struct tnode *t, struct tnode *v[]) 84 | { 85 | int index = 0; 86 | do_tree2vetor(t, v, &index); 87 | return index; 88 | } 89 | 90 | int compare(const void *a, const void *b) 91 | { 92 | return (* (struct tnode **) b)->count - (* (struct tnode **) a)->count; 93 | } 94 | 95 | #define MAXWORDS 10000 96 | 97 | int main(int argc, char *argv[]) 98 | { 99 | struct tnode *root = NULL; 100 | struct tnode *vetor[MAXWORDS]; 101 | int nelement = 0; 102 | 103 | char word[MAXWORD]; 104 | int c; 105 | 106 | while ((c = getword(word, MAXWORD)) != EOF) { 107 | if (c == WORD) 108 | root = addtree(root, word); 109 | } 110 | 111 | nelement = tree2vetor(root, vetor); 112 | qsort(vetor, nelement, sizeof(struct tnode *), compare); 113 | 114 | tree_print(vetor, nelement); 115 | 116 | return 0; 117 | } 118 | 119 | 120 | #define BUFSIZE 100 121 | 122 | int buffer[BUFSIZE]; 123 | int bufp = 0; 124 | 125 | int getch(void) 126 | { 127 | return (bufp > 0) ? buffer[--bufp] : getchar(); 128 | } 129 | 130 | void ungetch(int c) 131 | { 132 | if (bufp < BUFSIZE) 133 | buffer[bufp++] = c; 134 | else 135 | printf ("error: buffer is full\n"); 136 | } 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /cap6/exercise.6.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-21T20:15:00 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercises 6-5: Write a function undef that will remove a name and definition 8 | * from the table maintained by lookup and install */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | struct nlist { /* table entry: */ 15 | struct nlist *next; /* next entry in chain */ 16 | char *name; 17 | char *defn; 18 | }; 19 | 20 | #define HASHSIZE 101 21 | 22 | static struct nlist *hashtab[HASHSIZE]; /* pointer table */ 23 | 24 | /* hash: form hash value for strings s */ 25 | unsigned hash(char *s) 26 | { 27 | unsigned hashval; 28 | 29 | for (hashval = 0; *s != '\0'; s++) 30 | hashval = *s + 31 * hashval; 31 | return hashval % HASHSIZE; 32 | } 33 | 34 | /* lookup: look for s in hashtab */ 35 | struct nlist *lookup(char *s) 36 | { 37 | struct nlist *np; 38 | 39 | for (np = hashtab[hash(s)]; np != NULL; np = np->next) 40 | if (strcmp(s, np->name) == 0) 41 | return np; /* found */ 42 | return NULL; /* not found */ 43 | } 44 | 45 | /* install: put (name, defn) in hashtab */ 46 | struct nlist *install(char *name, char *defn) 47 | { 48 | struct nlist *np; 49 | unsigned hashval; 50 | 51 | if ((np = lookup(name)) == NULL) { /* not found */ 52 | np = (struct nlist*) malloc(sizeof(*np)); 53 | if (np == NULL || (np->name = strdup(name)) == NULL) 54 | return NULL; 55 | hashval = hash(name); 56 | np->next = hashtab[hashval]; 57 | hashtab[hashval] = np; 58 | } else /* already there */ 59 | free ((void *) np->defn); /* free previous defn */ 60 | if ((np->defn = strdup(defn)) == NULL) 61 | return NULL; 62 | return np; 63 | } 64 | 65 | void undef(char *s) 66 | { 67 | struct nlist **prev, *np; 68 | int hashval = hash(s); 69 | 70 | for (prev = &hashtab[hashval], np = hashtab[hashval]; 71 | np != NULL && strcmp(s, np->name); prev = &np->next, np = np->next) ; 72 | 73 | if (np == NULL) 74 | return; 75 | *prev = np->next; 76 | free(np); 77 | } 78 | 79 | void display_entry(int index) 80 | { 81 | struct nlist *np; 82 | for (np = hashtab[index]; np != NULL; np = np->next) 83 | printf ("[%2d]\tname (%s) -- defn (%s)\n", index, np->name, np->defn); 84 | } 85 | 86 | int main(int argc, char *argv[]) 87 | { 88 | int i; 89 | 90 | install("MAX_SIZE", "100"); 91 | install("MIN_SIZE", "0"); 92 | install("COUNT", "5"); 93 | install("HASHSIZE", "101"); 94 | undef("COUNT"); 95 | install("HASHSIZE", "45"); 96 | 97 | 98 | for (i = 0; i < HASHSIZE; ++i) 99 | display_entry(i); 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /cap6/exercise.6.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-21T21:10:03 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 6-6: Implement a simple version of the #define processor (i.e 8 | * no arguments) suitable for use with C programs, based on the routines of this 9 | * section. You may also find getch and ungetch helpful. */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | void ungetch(int c); 17 | int getch(void); 18 | 19 | struct nlist { /* table entry: */ 20 | struct nlist *next; /* next entry in chain */ 21 | char *name; 22 | char *defn; 23 | }; 24 | 25 | enum {NAME, DEFINE}; 26 | 27 | #define HASHSIZE 5 28 | 29 | static struct nlist *hashtab[HASHSIZE]; /* pointer table */ 30 | 31 | /* hash: form hash value for strings s */ 32 | unsigned hash(char *s) 33 | { 34 | unsigned hashval; 35 | 36 | for (hashval = 0; *s != '\0'; s++) 37 | hashval = *s + 31 * hashval; 38 | return hashval % HASHSIZE; 39 | } 40 | 41 | /* lookup: look for s in hashtab */ 42 | struct nlist *lookup(char *s) 43 | { 44 | struct nlist *np; 45 | 46 | for (np = hashtab[hash(s)]; np != NULL; np = np->next) 47 | if (strcmp(s, np->name) == 0) 48 | return np; /* found */ 49 | return NULL; /* not found */ 50 | } 51 | 52 | /* install: put (name, defn) in hashtab */ 53 | struct nlist *install(char *name, char *defn) 54 | { 55 | struct nlist *np; 56 | unsigned hashval; 57 | 58 | if ((np = lookup(name)) == NULL) { /* not found */ 59 | np = (struct nlist*) malloc(sizeof(*np)); 60 | if (np == NULL || (np->name = strdup(name)) == NULL) 61 | return NULL; 62 | hashval = hash(name); 63 | np->next = hashtab[hashval]; 64 | hashtab[hashval] = np; 65 | } else /* already there */ 66 | free ((void *) np->defn); /* free previous defn */ 67 | if ((np->defn = strdup(defn)) == NULL) 68 | return NULL; 69 | return np; 70 | } 71 | 72 | void undef(char *s) 73 | { 74 | struct nlist **prev, *np; 75 | int hashval = hash(s); 76 | 77 | for (prev = &hashtab[hashval], np = hashtab[hashval]; 78 | np != NULL && strcmp(s, np->name); prev = &np->next, np = np->next) ; 79 | 80 | if (np == NULL) 81 | return; 82 | *prev = np->next; 83 | free(np); 84 | } 85 | 86 | void display_entry(int index) 87 | { 88 | struct nlist *np; 89 | for (np = hashtab[index]; np != NULL; np = np->next) 90 | printf ("[%2d]\tname (%s) -- defn (%s)\n", index, np->name, np->defn); 91 | } 92 | 93 | int getword(char *word, int limits) 94 | { 95 | int c; 96 | char *w = word; 97 | 98 | while ((c = getch()) == ' ' || c == '\t') ; 99 | 100 | *w++ = c; 101 | if (!isalpha(c) && c != '_' && c != '#') { 102 | *w = '\0'; 103 | return c; 104 | } 105 | 106 | while (w < word + limits - 1 && (isalpha(c = *w++ = getch()) || c == '_')) ; 107 | *--w = '\0'; 108 | ungetch(c); 109 | 110 | return (!strcmp(word, "#define"))? DEFINE : NAME; 111 | } 112 | 113 | int _getline(char *line, int limits) 114 | { 115 | char *s = line; 116 | 117 | for (; s < line + limits -1 && (*s = getch()) != '\n' && *s != EOF; s++) ; 118 | *s = '\0'; 119 | return s - line; 120 | } 121 | 122 | #define MAXLEN 200 123 | 124 | int main(int argc, char *argv[]) 125 | { 126 | int i, c; 127 | char w[MAXLEN], name[MAXLEN]; 128 | char defn[MAXLEN * 15]; 129 | 130 | for (c = getword(w, MAXLEN); c != EOF; c = getword(w, MAXLEN)) { 131 | if (c == DEFINE){ 132 | c = getword(w, MAXLEN); 133 | if (c != NAME) 134 | printf ("error: name spected\n"); 135 | strcpy(name, w); 136 | _getline(defn, MAXLEN * 15); 137 | install(name, defn); 138 | } 139 | } 140 | 141 | 142 | for (i = 0; i < HASHSIZE; ++i) 143 | display_entry(i); 144 | printf ("finished\n"); 145 | return 0; 146 | } 147 | 148 | #define BUFSIZE 100 149 | 150 | int buffer[BUFSIZE]; 151 | int bufp = 0; 152 | 153 | int getch(void) 154 | { 155 | return (bufp > 0) ? buffer[--bufp] : getchar(); 156 | } 157 | 158 | void ungetch(int c) 159 | { 160 | if (bufp < BUFSIZE) 161 | buffer[bufp++] = c; 162 | else 163 | printf ("error: buffer is full\n"); 164 | } 165 | -------------------------------------------------------------------------------- /cap7/exercise7.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-23T20:03:06 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7.1: Write a program that converts upper case to lower or lower 8 | * case to upper, depending on the name it is invoked with, as found in argv[0] */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | int (*func)(int); 18 | int c; 19 | 20 | if (!strcmp(*argv, "tolower")) { 21 | func = tolower; 22 | } else if (!strcmp(*argv, "toupper")) { 23 | func = toupper; 24 | } else { 25 | printf ("error: name %s invalid\n", *argv); 26 | return 1; 27 | } 28 | 29 | while ((c = getchar()) != EOF) 30 | putchar(func(c)); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /cap7/exercise7.2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-23T20:58:07 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-2: Write a program that will print arbitray input in in a sesible 8 | * way. As minimum, it should print non-graphic characters in octal or hexadecimal 9 | * according to local custom, and break long text lines */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | char form[] = "0x%x"; 17 | int wrapcol = 80; 18 | 19 | void parseop(int argc, char *argv[]) 20 | { 21 | int c; 22 | 23 | while (--argc > 0) { 24 | if ((*++argv)[0] == '-') { 25 | while ((c = *++argv[0])) { 26 | switch (c) { 27 | case 'o': 28 | sprintf (form, "0%%%c", c); 29 | break; 30 | case 'x': 31 | sprintf (form, "0x%%%c", c); 32 | break; 33 | case 'w': 34 | wrapcol = atoi(*++argv); 35 | argc--; 36 | break; 37 | default: 38 | printf ("error: unknow parameter -%c\n", c); 39 | break; 40 | } 41 | } 42 | } else 43 | printf ("error: unknow parameter %s\n", *argv); 44 | } 45 | } 46 | 47 | 48 | int main(int argc, char *argv[]) 49 | { 50 | int col, c; 51 | 52 | parseop(argc, argv); 53 | 54 | col = 0; 55 | while ((c = getchar()) != EOF) { 56 | 57 | if(isalnum(c) || ispunct(c)) 58 | putchar(c); 59 | else if (isspace(c)) { 60 | col = (c == '\n') ? 0 : col; 61 | putchar (c); 62 | } else 63 | printf (form, c); 64 | if (col >= wrapcol) { 65 | printf ("\n»"); 66 | col = 0; 67 | } 68 | col++; 69 | } 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /cap7/exercise7.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-23T23:15:37 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7.3: Revise minprintf to handle more of the other facilities of printf */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAXFMT 500 15 | 16 | /* minprintf: minimal printf with variable argument list */ 17 | void minprintf(char *fmt, ...) 18 | { 19 | va_list ap; /* pointer to each unnamed arg in turn */ 20 | char *p, *sval; 21 | int ival; 22 | double dval; 23 | char outfmt[MAXFMT], buftmp[MAXFMT]; 24 | int minlen, prec; 25 | 26 | va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 27 | 28 | for (p = fmt; *p ; p++) { 29 | if (*p != '%') { 30 | putchar(*p); 31 | continue; 32 | } 33 | 34 | strcpy(outfmt, "%"); 35 | 36 | if (*++p == '-'){ 37 | strcat(outfmt, "-"); 38 | p++; 39 | } 40 | 41 | minlen = -1; 42 | if (isdigit(*p) || *p == '*') { 43 | if (*p == '*') { 44 | minlen = va_arg(ap, int); 45 | p++; 46 | } else { 47 | sscanf (p, "%d", &minlen); 48 | while (isdigit(*++p)) ; 49 | } 50 | } 51 | 52 | prec = -1; 53 | if (*p == '.') { 54 | if (*p == '*') { 55 | prec = va_arg(ap, int); 56 | p++; 57 | } else { 58 | p++; 59 | sscanf (p, "%d", &prec); 60 | while (isdigit(*++p)) ; 61 | } 62 | } 63 | 64 | if (minlen != -1) { 65 | sprintf (buftmp, "%d", minlen); 66 | strcat(outfmt, buftmp); 67 | } 68 | 69 | if (prec != -1) { 70 | sprintf (buftmp, ".%d", prec); 71 | strcat (outfmt, buftmp); 72 | } 73 | 74 | switch (*p) { 75 | case 'd': 76 | ival = va_arg(ap, int); 77 | strcat(outfmt, "d"); 78 | printf(outfmt, ival); 79 | break; 80 | case 'f': 81 | dval = va_arg(ap, double); 82 | strcat(outfmt, "f"); 83 | printf(outfmt, dval); 84 | break; 85 | case 's': 86 | sval = va_arg(ap, char *); 87 | strcat(outfmt, "s"); 88 | printf (outfmt, sval); 89 | break; 90 | default: 91 | putchar(*p); 92 | break; 93 | } 94 | } 95 | va_end(ap); /* clean up when done */ 96 | } 97 | 98 | int main(int argc, char *argv[]) 99 | { 100 | printf ("%*.*f\n", 10, 2, 3.14151617); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /cap7/exercise7.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-24T18:46:17 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-4: Write a private version of scanf analogous to minprintf 8 | * from the previous section */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define MAXSTRING 1000 16 | 17 | void minscanf(char *fmt, ...) 18 | { 19 | va_list ap; 20 | char *p; 21 | int c; 22 | 23 | int ival, *idest; 24 | float dval, *ddest; 25 | char cval, *cdest; 26 | char sval[MAXSTRING], *sdest; 27 | 28 | va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 29 | 30 | for (p = fmt; *p; p++) { 31 | 32 | if (isspace(*p)) 33 | continue; 34 | 35 | if (*p != '%') { 36 | while ((c = getchar()) != EOF && isspace(c)); 37 | if(c != *p) { 38 | va_end(ap); 39 | return ; 40 | } 41 | continue; 42 | } 43 | 44 | switch (*++p) { 45 | case 'd': 46 | scanf ("%d", &ival); 47 | idest = va_arg(ap, int *); 48 | *idest = ival; 49 | break; 50 | case 'f': 51 | scanf ("%f", &dval); 52 | ddest = va_arg(ap, float *); 53 | *ddest = dval; 54 | break; 55 | case 'c': 56 | cval = getchar(); 57 | cdest = va_arg(ap, char *); 58 | *cdest = cval; 59 | break; 60 | case 's': 61 | scanf ("%s", sval); 62 | sdest = va_arg(ap, char *); 63 | strcpy(sdest, sval); 64 | break; 65 | default: 66 | while ((c = getchar()) != EOF && c != *p); 67 | break; 68 | } 69 | } 70 | va_end(ap); /* clean up when done */ 71 | } 72 | 73 | int main(int argc, char *argv[]) 74 | { 75 | float f, f2; 76 | char s[50]; 77 | char c; 78 | int n1, n2; 79 | minscanf("%f %s %f %c", &f, s, &f2, &c); 80 | printf ("%f %s %F %c", f, s, f2, c); 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /cap7/exercise7.5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-26T21:11:14 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercises 7-5: Rewrite the postfix calculator of Chapter 4 to use scanf and/or 8 | * sscanf to do the input and number conversion */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | #define MAXOP 100 /* max size of operand or operator */ 18 | #define NUMBER '0' /* signal that a number was found */ 19 | #define NVAR 26 20 | #define SIN '1' 21 | #define COS '2' 22 | #define EXP '3' 23 | #define POW '4' 24 | #define VAR_SET '5' 25 | #define VAR_GET '6' 26 | #define ERROR '7' 27 | 28 | int getop(void); 29 | void push(double); 30 | double pop(void); 31 | double top(void); 32 | 33 | double var[NVAR]; 34 | char line[MAXOP]; 35 | char *ptr = NULL; 36 | double dec_opt; 37 | char c_opt; 38 | 39 | char *refill(void) 40 | { 41 | return fgets(line, MAXOP, stdin); 42 | } 43 | 44 | int getop(void) 45 | { 46 | double dval; 47 | char cval; 48 | char sval[MAXOP]; 49 | 50 | if (ptr == NULL) { 51 | if (refill() == NULL) 52 | return EOF; 53 | ptr = line; 54 | } 55 | 56 | while (*ptr == ' ' || *ptr == '\t' || *ptr == '\0') { 57 | if (*ptr == '\0') { 58 | if (refill() == NULL) 59 | return EOF; 60 | ptr = line; 61 | } else 62 | ptr++; 63 | } 64 | 65 | if ((sscanf (ptr, "%lf", &dval)) == 1) { 66 | while (isdigit(*ptr)) 67 | ptr++; 68 | if (*ptr == '.') { 69 | ptr++; 70 | while (isdigit(*ptr)) 71 | ptr++; 72 | } 73 | dec_opt = dval; 74 | return NUMBER; 75 | } 76 | 77 | sscanf(ptr, "%c", &cval); 78 | if (cval == '+' || cval == '-' || cval == '*' || cval == '/' || cval == '%' || cval == '\n') { 79 | ptr++; 80 | return cval; 81 | } 82 | 83 | sscanf (ptr, "%s", sval); 84 | while (isalpha(*ptr)) 85 | ptr++; 86 | if (!strcmp("SIN", sval)) { 87 | return SIN; 88 | } else if (!strcmp("COS", sval)) { 89 | return COS; 90 | } else if (!strcmp("EXP", sval)) { 91 | return EXP; 92 | } else if (!strcmp("POW", sval)) { 93 | return POW; 94 | } else if (strlen(sval) == 1) { 95 | c_opt = sval[0]; 96 | return (isupper(sval[0])) ? VAR_SET : VAR_GET; 97 | } else 98 | return ERROR; 99 | } 100 | 101 | /* reverse Polish Calculator */ 102 | main() 103 | { 104 | int type; 105 | double op2; 106 | 107 | while ((type = getop()) != EOF) { 108 | switch(type){ 109 | case NUMBER: 110 | push(dec_opt); 111 | break; 112 | case '+': 113 | push(pop() + pop()); 114 | break; 115 | case '*': 116 | push(pop() * pop()); 117 | break; 118 | case '-': 119 | op2 = pop(); 120 | push(pop() - op2); 121 | break; 122 | case '/': 123 | op2 = pop(); 124 | if (op2 != 0.0) 125 | push(pop() / op2); 126 | else 127 | printf("error: zero divisor\n"); 128 | break; 129 | case '%': 130 | op2 = pop(); 131 | push ((int) pop() % (int) op2); 132 | break; 133 | case SIN: 134 | push(sin(pop())); 135 | break; 136 | case COS: 137 | push(cos(pop())); 138 | break; 139 | case EXP: 140 | push(exp(pop())); 141 | break; 142 | case POW: 143 | op2 = pop(); 144 | push(pow(pop(), op2)); 145 | break; 146 | case VAR_SET: 147 | var[c_opt - 'A'] = top(); 148 | break; 149 | case VAR_GET: 150 | push(var[c_opt - 'a']); 151 | break; 152 | case '\n': 153 | printf ("\t%.8g\n", op2 = pop()); 154 | var['R' - 'A'] = op2; 155 | break; 156 | default: 157 | printf ("error: unknown command\n"); 158 | break; 159 | } 160 | } 161 | return 0; 162 | } 163 | 164 | #define MAXVAL 100 /* maximum depth of val stack */ 165 | 166 | int sp = 0; /* next free stack position */ 167 | double val[MAXVAL]; /* value stack */ 168 | 169 | /* push: push f onto value stack */ 170 | void push(double f){ 171 | if (sp < MAXVAL) 172 | val[sp++] = f; 173 | else 174 | printf("error: stack full, can't push %g\n", f); 175 | } 176 | 177 | double pop(void){ 178 | if (sp > 0) 179 | return val[--sp]; 180 | else { 181 | printf("error: stack empty\n"); 182 | return 0.0; 183 | } 184 | } 185 | 186 | double top(void) 187 | { 188 | if (sp > 0){ 189 | return val[sp - 1]; 190 | } else{ 191 | printf("error: stack empty\n"); 192 | return 0.0; 193 | } 194 | } 195 | 196 | -------------------------------------------------------------------------------- /cap7/exercise7.6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-26T14:37:27 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-6: Write a program to compare two files. Printing the first line 8 | * where they differ */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | FILE *Fopen(char *file_name, char *perm) 15 | { 16 | FILE *fd; 17 | if ((fd = fopen(file_name, perm)) == NULL) { 18 | fprintf (stderr, "error: on open file %s\n", file_name); 19 | exit(1); 20 | } 21 | return fd; 22 | } 23 | 24 | #define MAXLINE 1000 25 | #define MAXNAME 255 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | 30 | FILE *file1, *file2; 31 | char *o1, *o2; 32 | char line1[MAXLINE], line2[MAXLINE]; 33 | char file_name1[MAXNAME], file_name2[MAXNAME]; 34 | 35 | if (argc < 3) { 36 | fprintf (stderr, "%s: arguments required\n", argv[0]); 37 | exit (1); 38 | } 39 | 40 | strcpy(file_name1, *++argv); 41 | strcpy(file_name2, *++argv); 42 | 43 | file1 = Fopen(file_name1, "r"); 44 | file2 = Fopen(file_name2, "r"); 45 | 46 | while (1) { 47 | o1 = fgets(line1, MAXLINE, file1); 48 | o2 = fgets(line2, MAXLINE, file2); 49 | 50 | if (o1 == NULL || o2 == NULL) 51 | break; 52 | 53 | if (strcmp(line1, line2) != 0) { 54 | printf ("%s: %s", file_name1, line1); 55 | printf ("%s: %s", file_name2, line2); 56 | return 0; 57 | } 58 | } 59 | 60 | if (o1 != o2) { 61 | if (o1 != NULL) 62 | printf ("%s: %s", file_name1, line1); 63 | else 64 | printf ("%s: %s", file_name2, line2); 65 | } 66 | 67 | fclose (file1); 68 | fclose (file2); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /cap7/exercise7.7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-26T15:18:05 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-7: Modify the patter finding program of Chapter 5 to take its 8 | * input from a set of named files or, if no files are named as arguments, from 9 | * the standard input. Should the file name be printed when a matching line is found? */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | int status = 0; 17 | 18 | #define MAXLINE 1000 19 | 20 | void pattern_search(char *fname, char *pattern) 21 | { 22 | FILE *fd; 23 | char line[MAXLINE]; 24 | 25 | if (fname == NULL) 26 | fd = stdin; 27 | else 28 | fd = fopen(fname, "r"); 29 | 30 | if (fd == NULL) { 31 | fprintf (stderr, "error: don't open file %s\n", fname); 32 | status = 1; 33 | return ; 34 | } 35 | 36 | while (fgets(line, MAXLINE, fd) != NULL) { 37 | if (strstr(line, pattern)) { 38 | if (fname == NULL) 39 | printf ("%s", line); 40 | else 41 | printf ("%s: %s", fname, line); 42 | } 43 | } 44 | 45 | fclose(fd); 46 | } 47 | 48 | #define MAXPATTERN 1000 49 | 50 | int main(int argc, char *argv[]) 51 | { 52 | char pattern[MAXPATTERN]; 53 | 54 | if (argc < 2) { 55 | fprintf (stderr, "%s: pattern is required\n", argv[0]); 56 | exit(1); 57 | } 58 | 59 | strcpy(pattern, *++argv); 60 | 61 | if (argc > 2) { 62 | while (*++argv) 63 | pattern_search(*argv, pattern); 64 | } else 65 | pattern_search(NULL, pattern); 66 | 67 | return status; 68 | } 69 | -------------------------------------------------------------------------------- /cap7/exercise7.8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-26T16:04:18 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-8: Write a program to print a set of files, starting each new one on a 8 | * new page, with a litle and a running page count for each file. */ 9 | 10 | #include 11 | 12 | #define MAXLINE 1000 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int count = 0; 17 | FILE *fd; 18 | char line[MAXLINE]; 19 | int status = 0; 20 | 21 | while (*++argv) { 22 | fd = fopen (*argv, "r"); 23 | 24 | if (fd == NULL) { 25 | status = 1; 26 | fprintf (stderr, "error: don't open fine %s\n", *argv); 27 | continue; 28 | } 29 | 30 | printf ("title: %s\t\tpage: %d\n\n", *argv, ++count); 31 | 32 | while (fgets(line, MAXLINE, fd) != NULL) 33 | printf ("%s", line); 34 | printf ("\n\n"); 35 | fclose (fd); 36 | } 37 | return status; 38 | } 39 | -------------------------------------------------------------------------------- /cap7/exercise7.9.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: 2011-01-26T16:30:57 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | */ 6 | 7 | /* Exercise 7-9: Functions like isupper can be implemented to save space or to 8 | * save time. Explore both possibilities */ 9 | 10 | /* Desempenho: 11 | 12 | isupper_a: 13 | 14 | real 0m0.002s 15 | user 0m0.000s 16 | sys 0m0.000s 17 | 18 | isupper_b: 19 | 20 | real 0m0.003s 21 | user 0m0.000s 22 | sys 0m0.000s 23 | 24 | */ 25 | 26 | 27 | #include 28 | 29 | int upper_table[] = { 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 31 | 32 | int isupper_a(int c) /* save processing */ 33 | { 34 | return upper_table[c]; 35 | } 36 | 37 | int isupper_b(int c) 38 | { 39 | return (c >= 'A' && c <= 'Z'); 40 | } 41 | 42 | #define MAXIT 1000000 43 | 44 | int main(int argc, char *argv[]) 45 | { 46 | int i, j; 47 | for (i = 0; i < MAXIT; i++) 48 | for (j = 0; j < 256; j++) 49 | isupper_b(j); 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /cap8/cat_std_version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Dom 20 Fev 2011 12:41:29 BRT 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #define BUFZ 1000 12 | void filecopy(FILE *dest, FILE *origin) { 13 | char buff[BUFZ]; 14 | int c; 15 | 16 | while (fgets(buff, BUFZ, origin) != NULL) 17 | fputs(buff, dest); 18 | } 19 | 20 | /* cat: concatenate files, version 2 */ 21 | int main (int argc, char *argv[]) 22 | { 23 | FILE *fp; 24 | char *prog = argv[0]; 25 | 26 | if (argc == 1) 27 | filecopy(stdout, stdin); 28 | else 29 | while (--argc > 0) { 30 | if ((fp = fopen(*++argv, "r")) == NULL) { 31 | fprintf (stderr, "%s: can't open %s\n", prog, *argv); 32 | exit(1); 33 | } else { 34 | filecopy(stdout, fp); 35 | fclose(fp); 36 | } 37 | } 38 | 39 | if (ferror(stdout)) { 40 | fprintf (stderr, "%s: error writing stdout\n", prog); 41 | exit(2); 42 | } 43 | exit(0); 44 | } 45 | -------------------------------------------------------------------------------- /cap8/exercise.8.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Dom 20 Fev 2011 12:31:50 BRT 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 8-1: Rewrite the program cat from Chapter 7 using read, write, open, and 9 | * close instead of their standard library equivalents. Perform experments to determine 10 | * the relative speeds of the two versions */ 11 | 12 | /* result: 13 | * version using stdlib: 7s 14 | * version using unix interface: 7s 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | void filecopy(int dest, int orig) { 22 | char buff[BUFSIZ]; 23 | int n; 24 | 25 | while ((n = read(orig, buff, BUFSIZ)) > 0) 26 | write (dest, buff, n); 27 | } 28 | 29 | int main (int argc, char const* argv[]) 30 | { 31 | int fd; 32 | 33 | if (argc == 1) { 34 | filecopy(1, 0); 35 | } else { 36 | while (--argc > 0) { 37 | if ((fd = open(*++argv, O_RDONLY, 0)) == -1) 38 | exit (1); 39 | filecopy(1, fd); 40 | close(fd); 41 | } 42 | } 43 | exit(0); 44 | } 45 | -------------------------------------------------------------------------------- /cap8/exercise.8.3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 24 Fev 2011 18:48:07 BRT 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 8-3: Design and write _flushbuf, fflush, and fclose */ 9 | 10 | #include 11 | 12 | #define NULL 0 13 | #define EOF (-1) 14 | #define BUFSIZ 1024 15 | #define OPEN_MAX 20 /* max #files open at once */ 16 | 17 | typedef struct _iobuf { 18 | int cnt; /* characters left */ 19 | char *ptr; /* next character position */ 20 | char *base; /* location of buffer */ 21 | int flag; /* mode of file acess */ 22 | int fd; /* file descriptor */ 23 | } FILE; 24 | 25 | FILE _iob[OPEN_MAX]; 26 | 27 | #define stdin (&_iob[0]) 28 | #define stdout (&_iob[1]) 29 | #define stderr (&_iob[2]) 30 | 31 | enum _flags { 32 | _READ = 01, /* file open for reading */ 33 | _WRITE = 02, /* file open for writing */ 34 | _UNBUF = 04, /* ffile is unbuffered */ 35 | _EOF = 010, /* EOF has occurred on this file */ 36 | _ERR = 020, /* error occurred on this file */ 37 | }; 38 | 39 | int _flushbuf(int c, FILE *fp) 40 | { 41 | int bufsize; 42 | 43 | if (fp == NULL) 44 | return EOF; 45 | 46 | if ((fp->flag & (_WRITE | _ERR)) != _WRITE) { 47 | return EOF; 48 | } 49 | 50 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 51 | 52 | if (fp->base == NULL) { 53 | if ((fp->base = malloc(bufsize)) == NULL) 54 | return EOF; 55 | } else { 56 | if (write(fp->fd, fp->base, bufsize) != bufsize) { 57 | fp->flag |= _ERR; 58 | return EOF; 59 | } 60 | } 61 | 62 | fp->ptr = fp->base; 63 | fp->cnt = bufsize - 1; 64 | return (*fp->ptr++ = c); 65 | } 66 | 67 | int fflush(FILE *fp) 68 | { 69 | int bufsize, write_size; 70 | 71 | if (fp == NULL) 72 | return EOF; 73 | 74 | if ((fp->flag & (_WRITE | _ERR)) != _WRITE) 75 | return EOF; 76 | 77 | if (fp->base == NULL) 78 | return 0; 79 | 80 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 81 | write_size = bufsize - fp->cnt; 82 | 83 | if (write(fp->fd, fp->base, write_size) != write_size) { 84 | fp->flag |= _ERR; 85 | return EOF; 86 | } 87 | 88 | fp->ptr = fp->base; 89 | fp->cnt = bufsize; 90 | 91 | return 0; 92 | } 93 | 94 | int fclose(FILE *fp) 95 | { 96 | if (fp->flag & _WRITE) { 97 | if (fflush(fp) != 0) 98 | return EOF; 99 | } 100 | 101 | free(fp->base); 102 | close(fp->fd); 103 | return 0; 104 | } 105 | 106 | #define putc(x,p) ((--(p)->cnt >= 0) \ 107 | ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 108 | -------------------------------------------------------------------------------- /cap8/exercise.8.4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Qui 24 Fev 2011 20:08:00 BRT 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | /* Exercise 8-4: The standard library function 9 | * 10 | * int fseek(FILE *fp, long offset, int origin) 11 | * 12 | * Is identical to lseek execpt that fp is a file pointer instead of a file 13 | * descriptor and return value is an int status, not a position. Write fseek. 14 | * Make sure that your fseek coordinates properly with the buffering done for 15 | * the other functions of the library \ 16 | */ 17 | 18 | int fseek(FILE *stream, long offset, int origin) 19 | { 20 | int status, mode; 21 | int c; 22 | 23 | if (stream == NULL) 24 | return 1; 25 | 26 | switch(origin){ 27 | case SEEK_SET: 28 | mode = 0; 29 | break; 30 | case SEEK_CUR: 31 | mode = 1; 32 | break; 33 | case SEEK_END: 34 | mode = 2; 35 | break; 36 | default: 37 | return 1; 38 | break; 39 | } 40 | 41 | status = lseek(stream->fd; offset, mode); 42 | 43 | if (status == -1) 44 | return 1; 45 | 46 | if (stream->flag & _READ) { 47 | c = _fillbuf(stream); 48 | ungetch(c, stream); 49 | } else { /* write */ 50 | fflush(stream); 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /cap8/fopen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Created: Dom 20 Fev 2011 14:38:58 BRT 3 | * 4 | * Author: Maycon Sambinelli, msambinelli@gmail.com 5 | * 6 | */ 7 | 8 | #define NULL 0 9 | #define EOF (-1) 10 | #define BUFSIZ 1024 11 | #define OPEN_MAX 20 /* max #files open at once */ 12 | 13 | typedef struct _iobuf { 14 | int cnt; /* characters left */ 15 | char *ptr; /* next character position */ 16 | char *base; /* location of buffer */ 17 | int flag; /* mode of file acess */ 18 | int fd; /* file descriptor */ 19 | } FILE; 20 | 21 | FILE _iob[OPEN_MAX]; 22 | 23 | #define stdin (&_iob[0]) 24 | #define stdout (&_iob[1]) 25 | #define stderr (&_iob[2]) 26 | 27 | enum _flags { 28 | _READ = 01, /* file open for reading */ 29 | _WRITE = 02, /* file open for writing */ 30 | _UNBUF = 04, /* ffile is unbuffered */ 31 | _EOF = 010, /* EOF has occurred on this file */ 32 | _ERR = 020, /* error occurred on this file */ 33 | }; 34 | 35 | int _fillbuf(FILE *); 36 | //int _flushbuf(int, FILE *); 37 | 38 | #define feof(p) (((p)->flag & _EOF) != 0) 39 | #define ferror(p) (((p)->flag & _ERR) != 0) 40 | #define fileno(p) ((p)->fd) 41 | 42 | #define getc(p) (--(p)->cnt >= 0 \ 43 | ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) 44 | 45 | #define putchar(c) (write(stdout, &(c), 1)) 46 | 47 | #include 48 | #define PERM 0666 49 | 50 | FILE *fopen(char *name, char *mode) 51 | { 52 | int fd; 53 | FILE *fp; 54 | 55 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 56 | return NULL; 57 | 58 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 59 | if ((fp->flag & (_READ | _WRITE)) == 0) 60 | break; /* found free slot */ 61 | if (fp >= _iob + OPEN_MAX) 62 | return NULL; 63 | 64 | if (*mode == 'w') 65 | fd = creat(name, PERM); 66 | else if (*mode == 'a') { 67 | if ((fd = open(name, O_WRONLY, 0) == -1)) 68 | fd = creat(name, PERM); 69 | lseek(fd, 0L, 2); 70 | } else 71 | fd = open(name, O_RDONLY, 0); 72 | 73 | if (fd == -1) 74 | return NULL; 75 | 76 | fp->fd = fd; 77 | fp->cnt = 0; 78 | fp->base = NULL; 79 | fp->flag = (*mode == 'r') ? _READ : _WRITE; 80 | return fp; 81 | } 82 | 83 | #include 84 | 85 | /* _fillbuf: allocate and fill input buffer */ 86 | int _fillbuf(FILE *fp) 87 | { 88 | int bufsize; 89 | 90 | if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) 91 | return EOF; 92 | 93 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 94 | if (fp->base == NULL) { 95 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 96 | return EOF; /* can't get buffer */ 97 | } 98 | fp->ptr = fp->base; 99 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 100 | if (--fp->cnt < 0) { 101 | if (fp->cnt == -1) 102 | fp->flag |= _EOF; 103 | else 104 | fp->flag |= _ERR; 105 | fp->cnt = 0; 106 | return EOF; 107 | } 108 | return (unsigned char) *fp->ptr++; 109 | } 110 | 111 | int main (int argc, char const* argv[]) 112 | { 113 | FILE *fp = fopen("/tmp/teste.txt", "r"); 114 | 115 | while (feof(fp)) { 116 | int c = getc(fp); 117 | putchar(c); 118 | } 119 | close(fp->fd); 120 | return 0; 121 | } 122 | --------------------------------------------------------------------------------