diff --git a/Makefile b/Makefile index 2584e4a..283f7bf 100644 --- a/Makefile +++ b/Makefile @@ -128,13 +128,14 @@ UPROGS=\ $U/_rm\ $U/_sh\ $U/_stressfs\ + $U/_test_count\ $U/_usertests\ $U/_grind\ $U/_wc\ $U/_zombie\ -fs.img: mkfs/mkfs README.md $(UPROGS) - mkfs/mkfs fs.img README.md $(UPROGS) +fs.img: mkfs/mkfs README.md $(UPROGS) count_sample.txt + mkfs/mkfs fs.img README.md $(UPROGS) count_sample.txt -include kernel/*.d user/*.d diff --git a/count_sample.txt b/count_sample.txt new file mode 100644 index 0000000..40fa391 --- /dev/null +++ b/count_sample.txt @@ -0,0 +1,4 @@ +Hello, World! 12345 +This is a Test. +Lowercase and UPPERCASE letters! +Digits: 6789012345 diff --git a/user/test_count.c b/user/test_count.c new file mode 100644 index 0000000..65e31c7 --- /dev/null +++ b/user/test_count.c @@ -0,0 +1,32 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" +#include "kernel/fcntl.h" + +void run_wc_test(char *test_description, char *wc_args) { + int pid = fork(); + if (pid == 0) { + char *args[4]; + args[0] = "wc"; + args[1] = wc_args; + args[2] = "count_sample.txt"; + args[3] = 0; + + printf("\n%s\n", test_description); + exec("wc", args); + exit(0); + } else { + wait(0); + } +} + +int main(void) { + run_wc_test("Test with no flags", ""); + run_wc_test("Test counting punctuation (-p)", "-p"); + run_wc_test("Test counting digits (-d)", "-d"); + run_wc_test("Test counting uppercase letters (-u)", "-u"); + run_wc_test("Test counting lowercase letters (-l)", "-l"); + run_wc_test("Test with invalid option (-z)", "-z"); + + exit(0); +} diff --git a/user/wc.c b/user/wc.c index 6a851ca..e0ef264 100644 --- a/user/wc.c +++ b/user/wc.c @@ -1,54 +1,131 @@ #include "kernel/types.h" +#include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h" +int count_punct = 0, count_digits = 0, count_upper = 0, count_lower = 0; +int flags_specified = 0; + char buf[512]; -void -wc(int fd, char *name) -{ +int is_digit(char c) { + return c >= '0' && c <= '9'; +} + +int is_uppercase(char c) { + return c >= 'A' && c <= 'Z'; +} + +int is_lowercase(char c) { + return c >= 'a' && c <= 'z'; +} + +int is_punctuation(char c) { + return c == '.' || c == ',' || c == '!' || c == '?' || c == ';' || c == ':' || + c == '\'' || c == '"' || c == '(' || c == ')' || c == '[' || c == ']' || + c == '{' || c == '}' || c == '-' || c == '_'; +} + +/** + * Counts the number of lines, words, and characters from the file descriptor `fd`. + * Or counts punctuation marks, digits, uppercase, and lowercase letters, + * based on flags. + * + * Flags: + * - `-p` : Count punctuation marks. + * - `-d` : Count digits. + * - `-u` : Count uppercase letters. + * - `-l` : Count lowercase letters. + * + * @param fd the file descriptor to read from + * @param name the name of the file being processed + */ +void wc(int fd, char *name) { int i, n; int l, w, c, inword; + int punct_count = 0, digit_count = 0, upper_count = 0, lower_count = 0; l = w = c = 0; inword = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(i=0; i 0) { + for (i = 0; i < n; i++) { c++; - if(buf[i] == '\n') + if (buf[i] == '\n') l++; - if(strchr(" \r\t\n\v", buf[i])) + if (strchr(" \r\t\n\v", buf[i])) inword = 0; - else if(!inword){ + else if (!inword) { w++; inword = 1; } + + if (count_punct && is_punctuation(buf[i])) { + punct_count++; + } + if (count_digits && is_digit(buf[i])) { + digit_count++; + } + if (count_upper && is_uppercase(buf[i])) { + upper_count++; + } + if (count_lower && is_lowercase(buf[i])) { + lower_count++; + } } } - if(n < 0){ + + if (n < 0) { printf("wc: read error\n"); exit(1); } - printf("%d %d %d %s\n", l, w, c, name); -} -int -main(int argc, char *argv[]) -{ - int fd, i; - - if(argc <= 1){ - wc(0, ""); - exit(0); + if (!flags_specified && name[0] != '\0') { + printf("%d %d %d %s\n", l, w, c, name); } - for(i = 1; i < argc; i++){ - if((fd = open(argv[i], 0)) < 0){ - printf("wc: cannot open %s\n", argv[i]); - exit(1); - } - wc(fd, argv[i]); - close(fd); + if (count_punct) { + printf("Punctuation: %d\n", punct_count); + } + if (count_digits) { + printf("Digits: %d\n", digit_count); } + if (count_upper) { + printf("Uppercase: %d\n", upper_count); + } + if (count_lower) { + printf("Lowercase: %d\n", lower_count); + } +} + +int main(int argc, char *argv[]) { + int fd, i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-p") == 0) { + count_punct = 1; + flags_specified = 1; + } else if (strcmp(argv[i], "-d") == 0) { + count_digits = 1; + flags_specified = 1; + } else if (strcmp(argv[i], "-u") == 0) { + count_upper = 1; + flags_specified = 1; + } else if (strcmp(argv[i], "-l") == 0) { + count_lower = 1; + flags_specified = 1; + } else if (argv[i][0] == '-') { + printf("wc: invalid option %s\n", argv[i]); + exit(1); + } else { + if ((fd = open(argv[i], 0)) < 0) { + printf("wc: cannot open %s\n", argv[i]); + exit(1); + } + wc(fd, argv[i]); + close(fd); + } + } + exit(0); }