c-system-programming:fgets
تابع ()fgets - خواندن از stdin به شکل pipe-friendly
Section 1
// man 3 fgets /* fgets() reads in at most one less than size characters from stream and stores them into the * buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is * stored into the buffer. A terminating null byte ('\0') is stored after the last character in * the buffer. * fgets() returns s on success, and NULL on error or when end of file occurs while no characters * have been read. */ #include <stdio.h> char *fgets(char *s, int size, FILE *stream); // man 3 memset /* memset - fills the first n bytes of the memory area pointed to by s with the constant byte c */ #include <string.h> void *memset(void s[.n], int c, size_t n);
/* case-changer.c */ #include <stdio.h> #include <string.h> int main(void) { char c[20] = { 0 }; char newcase[20] = { 0 }; int i; while(fgets(c, sizeof(c), stdin) != NULL) { for(i=0; i<=sizeof(c); i++) { /* Upper case to lower case */ if ( (c[i] >= 65) && (c[i] <= 90) ) { newcase[i] = c[i] + 32; } /* Lower case to upper case */ if ( (c[i] >= 97 && c[i] <= 122) ) { newcase[i] = c[i] - 32; } } printf("%s\n", newcase); /* zero out the arrays so there are no left-overs in the next run */ memset(c, 0, sizeof(c)); memset(newcase, 0, sizeof(newcase)); } return 0; }
$ make case-changer cc case-changer.c -o case-changer
$ ./case-changer hello HELLO AbCdEf aBcDeF
$ ls / | head -n 5 | ./case-changer BIN BOOT COMMAND DEV ETC
$ man ls | egrep '^[A-Z]+$' | ./case-changer name synopsis description author copyright
/* ascii-table.c */ #include <stdio.h> int main(void) { char c; for (c = 65; c<=90; c++) { printf("%c = %d ", c, c); /* upper case */ printf("%c = %d\n", c+32, c+32); /* lower case */ } return 0; }
$ make ascii-table cc ascii-table.c -o ascii-table
$ ./ascii-table A = 65 a = 97 B = 66 b = 98 C = 67 c = 99 D = 68 d = 100 E = 69 e = 101 F = 70 f = 102 G = 71 g = 103 H = 72 h = 104 I = 73 i = 105 J = 74 j = 106 K = 75 k = 107 L = 76 l = 108 M = 77 m = 109 N = 78 n = 110 O = 79 o = 111 P = 80 p = 112 Q = 81 q = 113 R = 82 r = 114 S = 83 s = 115 T = 84 t = 116 U = 85 u = 117 V = 86 v = 118 W = 87 w = 119 X = 88 x = 120 Y = 89 y = 121 Z = 90 z = 122
Section 2
// man 3 strspn /* The strspn() function returns the number of bytes in the initial segment of s which consist * only of bytes from accept. */ #include <string.h> size_t strspn(const char *s, const char *accept); // man 3 strlen /* The strlen() function calculates the length of the string pointed to by s, excluding the * terminating null byte ('\0'). */ #include <string.h> size_t strlen(const char *s);
/* mph-to-kph.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char mph[10] = { 0 }; while(fgets(mph, sizeof(mph), stdin) != NULL) { /* Check if mph is numeric * (and do conversion) */ if( strspn(mph, "0123456789.-\n") == strlen(mph) ) { printf("%.1f\n", (atof(mph)*1.60934) ); } /* If mph is NOT numeric, print error * and return */ else { fprintf(stderr, "Found non-numeric" " value\n"); return 1; } } return 0; }
$ make mph-to-kph cc mph-to-kph.c -o mph-to-kph
$ ./mph-to-kph 50 80.5 60 96.6 100 160.9 hello Found non-numeric value
$ echo $? 1
$ ./mph-to-kph 50 80.5 <ctrl-D>
$ echo $? 0
$ cat avg.txt 10-minute average: 61 mph 30-minute average: 55 mph 45-minute average: 54 mph 60-minute average: 52 mph 90-minute average: 52 mph 99-minute average: nn mph
$ awk '{print $3}' avg.txt
61
55
54
52
52
nn
$ awk '{print $3}' avg.txt | ./mph-to-kph
98.2
88.5
86.9
83.7
83.7
Found non-numeric value
$ awk '{print $3}' avg.txt | ./mph-to-kph 2> /dev/null | sed -e 's,$, km/h,'
98.2 km/h
88.5 km/h
86.9 km/h
83.7 km/h
83.7 km/h
Section 3
/* mph-to-kph_v2.c */ #define _XOPEN_SOURCE 500 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void printHelp(FILE *stream, char progname[]); int main(int argc, char *argv[]) { char mph[10] = { 0 }; int opt; int cont = 0; /* Parse command-line options */ while ((opt = getopt(argc, argv, "ch")) != -1) { switch(opt) { case 'h': printHelp(stdout, argv[0]); return 0; case 'c': cont = 1; break; default: printHelp(stderr, argv[0]); return 1; } } while(fgets(mph, sizeof(mph), stdin) != NULL) { /* Check if mph is numeric * (and do conversion) */ if( strspn(mph, "0123456789.-\n") == strlen(mph) ) { printf("%.1f\n", (atof(mph)*1.60934) ); } /* If mph is NOT numeric, print error * and return */ else { fprintf(stderr, "Found non-numeric " "value\n"); if (cont == 1) /* Check if -c is set */ { continue; /* Skip and continue if * -c is set */ } else { return 1; /* Abort if -c is not set */ } } } return 0; } void printHelp(FILE *stream, char progname[]) { fprintf(stream, "%s [-c] [-h]\n", progname); fprintf(stream, " -c continues even though a non" "-numeric value was detected in the input\n" " -h print help\n"); }
$ make mph-to-kph_v2 cc mph-to-kph_v2.c -o mph-to-kph_v2
$ ./mph-to-kph_v2 60 96.6 40 64.4 hello Found non-numeric value
$ ./mph-to-kph_v2 -c 50 80.5 90 144.8 hello Found non-numeric value 10 16.1 20 32.2 <ctrl-d>
$ cat avg-with-garbage.txt 10-minute average: 61 mph 30-minute average: 55 mph 45-minute average: 54 mph 60-minute average: 52 mph 90-minute average: 52 mph 99-minute average: nn mph 120-minute average: 49 mph 160-minute average: 47 mph 180-minute average: nn mph error reading data from interface 200-minute average: 43 mph
$ awk '{print $3}' avg-with-garbage.txt
61
55
54
52
52
nn
49
47
nn
data
43
$ awk '{print $3}' avg-with-garbage.txt | ./mph-to-kph_v2 -c
98.2
88.5
86.9
83.7
83.7
Found non-numeric value
78.9
75.6
Found non-numeric value
Found non-numeric value
69.2
$ awk '{print $3}' avg-with-garbage.txt | ./mph-to-kph_v2 -c 2> errors.txt 1> output.txt
$ cat output.txt
98.2
88.5
86.9
83.7
83.7
78.9
75.6
69.2
$ cat errors.txt
Found non-numeric value
Found non-numeric value
Found non-numeric value
c-system-programming/fgets.txt · آخرین ویرایش: 2024/06/18 01:22 توسط pejman
