Skip to content

Commit 636d08d

Browse files
Add -n option
1 parent 814770e commit 636d08d

File tree

1 file changed

+121
-25
lines changed

1 file changed

+121
-25
lines changed

cat/masatora-cat.c

Lines changed: 121 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,141 @@
77
#define E_NOT_FOUND 0
88
#define E_DIRECTORY 1
99
#define E_PERMISSION 2
10+
#define E_INVALID_ARG 3
1011

11-
void print(int file);
12+
typedef struct options {
13+
int number;
14+
} Options;
15+
16+
void print(int file, Options options);
17+
void itoa(int n, char s[]);
18+
void reverse(char s[]);
1219
void error(int e_type, char *name);
1320

1421
int main(int argc, char *argv[])
1522
{
16-
int file;
23+
int file, c;
24+
int number = 0;
25+
Options options = { 0 };
1726
struct stat stduf;
1827

19-
if (--argc > 0) {
20-
while (*++argv) {
21-
stat(*argv, &stduf);
22-
if ((stduf.st_mode & S_IFMT) == S_IFDIR) {
23-
error(E_DIRECTORY, *argv);
24-
break;
28+
// 引数がない場合は標準入力から読み込んで出力
29+
if (argc > 1) {
30+
while (--argc > 0 && (*++argv)[0] == '-') {
31+
//引数がハイフンだけだった場合は標準入力から読み込んで出力
32+
if (*++argv[0] == NULL) {
33+
print(0, options);
34+
return 0;
2535
}
26-
if (access(*argv, F_OK) != 0) {
27-
error(E_NOT_FOUND, *argv);
28-
break;
29-
} else {
30-
if (access(*argv, R_OK) != 0) {
31-
error(E_PERMISSION, *argv);
32-
break;
36+
while ((c = *argv[0]++)) {
37+
switch (c) {
38+
case 'n':
39+
options.number = 1;
40+
break;
41+
default:
42+
// cat -[invalid arguments]とした場合、エラーメッセージには一番最初の不正なオプションのみを表示する
43+
// (例) cat -aho の場合、cat: illegal option -- a
44+
argv[0]--;
45+
(*argv)[1] = '\0';
46+
error(E_INVALID_ARG, *argv);
47+
return 1;
3348
}
3449
}
35-
36-
file = open(*argv, O_RDONLY, 0);
37-
print(file);
38-
close(file);
3950
}
51+
52+
// オプションだけ指定した場合は標準入力から読み込んで出力
53+
if (argc > 0) {
54+
while (*argv) {
55+
stat(*argv, &stduf);
56+
if ((stduf.st_mode & S_IFMT) == S_IFDIR) {
57+
error(E_DIRECTORY, *argv);
58+
break;
59+
}
60+
if (access(*argv, F_OK) != 0) {
61+
error(E_NOT_FOUND, *argv);
62+
break;
63+
} else {
64+
if (access(*argv, R_OK) != 0) {
65+
error(E_PERMISSION, *argv);
66+
break;
67+
}
68+
}
69+
70+
file = open(*argv, O_RDONLY, 0);
71+
print(file, options);
72+
close(file);
73+
argv++;
74+
}
75+
} else
76+
print(0, options);
4077
} else
41-
print(0);
78+
print(0, options);
4279
return 0;
4380
}
4481

4582
#define BUFSIZE 1000
83+
#define MAXSIZE 1000
84+
85+
void print(int file, Options options)
86+
{
87+
// -nオプション
88+
if (options.number) {
89+
char c;
90+
int n, i = 0, lc = 1;
91+
char line[MAXSIZE], lc_char[10];
92+
93+
while ((n = read(file, &c, 1)) == 1) {
94+
line[i] = c;
95+
i++;
96+
if (c == '\n') {
97+
itoa(lc++, lc_char);
98+
line[i] = '\0';
99+
100+
write(1, " ", strlen(" "));
101+
write(1, lc_char, strlen(lc_char));
102+
write(1, " ", strlen(" "));
103+
write(1, line, strlen(line));
104+
105+
i = 0;
106+
}
107+
}
108+
} else {
109+
char buf[BUFSIZE];
110+
int n;
111+
112+
while ((n = read(file, buf, BUFSIZE)) > 0)
113+
write(1, buf, n);
114+
}
46115

47-
void print(int file)
116+
117+
}
118+
119+
void itoa(int n, char s[])
48120
{
49-
char buf[BUFSIZE];
50-
int n;
121+
int i, sign;
122+
123+
if ((sign = n) < 0)
124+
n = -n;
125+
i = 0;
126+
do {
127+
s[i++] = n % 10 + '0';
128+
} while ((n /= 10) > 0);
51129

52-
while ((n = read(file, buf, BUFSIZE)) > 0)
53-
write(1, buf, n);
130+
if (sign < 0)
131+
s[i++] = '-';
132+
s[i] = '\0';
133+
reverse(s);
134+
}
135+
136+
void reverse(char s[])
137+
{
138+
int c, i, j;
139+
140+
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
141+
c = s[i];
142+
s[i] = s[j];
143+
s[j] = c;
144+
}
54145
}
55146

56147
#define ERROR_MSG_SIZE 256
@@ -73,6 +164,11 @@ void error(int e_type, char *name)
73164
strcat(error_msg, name);
74165
strcat(error_msg, ": Permission denied");
75166
break;
167+
case E_INVALID_ARG:
168+
strcat(error_msg, "illegal option -- ");
169+
strcat(error_msg, name);
170+
strcat(error_msg, "\nusage: cat [-n] [file ...]");
171+
break;
76172
default:
77173
break;
78174
}

0 commit comments

Comments
 (0)