فهرست مندرجات

تابع ()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