はじめての C

C programming note*1
あとは、それぞれの 関数を 組み立てていきます。 今回は 1つの ファイルに 納めましたが、長くなるようなら、別々に コンパイルするという 方法も あります。

/* ce3r.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_SIZE (80 + 1 + 1) /* plus '\n' + '\0' */
#define WIDTH 80
#define YES 1
#define NO 0
#define ISBLANK(c) ((c) == ' ' || (c) == '\t')

int carte();
void center();
void remove_pre_blank();
void remove_pos_blank();
int alldigit();
void usage();
void cant();

int width = WIDTH;

main(int argc, char **argv)
{
FILE *fp;
char *s;
int r;

/* オプション指定の 解析 */
while (--argc > 0 && **++argv == '-') {
for (s = *argv + 1; *s != '\0'; s++) {
switch (*s) {
case 'w':
if (alldigit(s + 1) == NO)
usage(); /* no return */
width = atoi(s + 1);
while (*(++s + 1))
;
break;
default:
usage(); /* no return */
}
}
}
if (width <= 0 || WIDTH < width)
usage(); /* no return */

if (argc == 0) {
if(carte(stdin) != 0)
return 1;
}
else {
while (argc--) {
if )((fp = fopen(*argv, "r"))( == NULL)
cant(*argv); /* no return */
r = carte(fp);
fclose(fp);
if (r != 0)
return 1;
argv++;
}
}
return 0;
}

int carte(FILE *fp)
{
char buf[MAX_SIZE];

while (fgets(buf, MAX_SIZE, fp) != NULL) {
remove_pre_blank(buf);
remove_pos_blank(buf);
center(buf, width);
if (fputs(buf, stdout) == EOF) {
fprintf(stderr, "ce3r: write error\n");
return -1;
}
}
return 0;
}

void center(char buf[], int w)
{
int n;
int off;
int i;

n = strlen(buf) - 1; /* -1 for '\n' */
if (w < n)
return;
off = (w - n + 1) / 2;
for (i = n + 1; i >= 0; i--)
buf[i + off] = buf[i];
while (off--)
buf[off] = ' ';
}

void remove_pre_blank(char *buf)
{
int n;
char *p;
char *q;

for (p = buf; ISBLANK(*p); p++)
;
q = buf;
n = strlen(p) + 1;
while (n--)
*q++ = *p++;
}

void remove_pos_blank(char *buf)
{
char *q;

if (*buf == '\0')
return;
q = buf + strlen(buf) - 1; /* -1 for '\n' */
while (q > buf && ISBLANK(*(q - 1)))
--q;
*q = '\n';
*(q + 1) = '\0';
}

int alldigit(char *s)
{
if (*s == '\0')
return NO;
for ( ; *s != '\0'; s++) {
if (!isdigit(*s))
return NO;
}
return YES;
}

void usage(void)
{
fprintf(stderr, "Usage: ce3r [-wNN] {file ... ]\n");
exit(1);
}

void cant(char *name)
{
fprintf(stderr, "can't open %s\n", name);
exit(1);
}

コンパイルが 終わったら、さっそく 使ってみます。 その前に、menu.txt を 作成、
* menu *
curried rice
stew
plain omelet
beer
coffee
diary lunch
まず、幅を 30 にして 中央揃えに、
$ ./ce3r -w30 menu.txt
以前 つくった cat4r と 組み合わせてみます、
$ ./ce3r -w30 menu.txt | ./cat4r -n
行番号が プラスされました。 大文字に するなら、
$ ./ce3r -w30 menu.txt | ./cat4r -c -n
中央揃えする 関数 center() は、次のように 書くことも できます、
void center(char buf[], int w)
{
int n;
int off;

n = strlen[buf] - 1;
if (w < n)
return;
off = (w - n + 1) / 2;
n += 2; /* +2 for '\n' + '\0' */
while (n--)
buf[n + off] = buf[n];
while (off--)
buf[off] = ' ';
}

ここの ところが 替えてありますね ↓
n += 2;
while (n--)
buf[n + off] = buf[n];

*1:「作ってわかる Cプログラミング」