Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

// How to fix this code for it to do what is supposed to do? /* About this progr

ID: 3885927 • Letter: #

Question

// How to fix this code for it to do what is supposed to do?

/*
About this program:
- This program counts words.
- The specific words that will be counted are passed in as command-line
arguments.
- The program reads words (one word per line) from standard input until EOF or
an input line starting with a dot '.'
- The program prints out a summary of the number of times each word has
appeared.
- Various command-line options alter the behavior of the program.

E.g., count the number of times 'cat', 'nap' or 'dog' appears.
> ./main cat nap dog
Given input:
cat
.
Expected output:
Looking for 3 words
Result:
cat:1
nap:0
dog:0
*/

#include
#include
#include
#include "assignment1_test.h"

#define LENGTH(s) (sizeof(s) / sizeof(*s))

/* Structures */
typedef struct {
char *word;
int counter;
} WordCountEntry;


int process_stream(WordCountEntry entries[], int entry_count)
{
short line_count = 0;
char buffer[30];

while (gets(buffer)) {
if (*buffer == '.')
break;
/* Compare against each entry */
int i = 0;
while (i < entry_count) {
if (!strcmp(entries[i].word, buffer))
entries[i].counter++;
i++;
}
line_count++;
}
return line_count;
}


void print_result(WordCountEntry entries[], int entry_count)
{
printf("Result: ");
while (entry_count-- > 0) {
printf("%s:%d ", entries->word, entries->counter);
}
}


void printHelp(const char *name)
{
printf("usage: %s [-h] ... ", name);
}


int main(int argc, char **argv)
{
const char *prog_name = *argv;

WordCountEntry entries[5];
int entryCount = 0;

/* Entry point for the testrunner program */
if (argc > 1 && !strcmp(argv[1], "-test")) {
run_assignment1_test(argc - 1, argv + 1);
return EXIT_SUCCESS;
}

while (*argv != NULL) {
if (**argv == '-') {

switch ((*argv)[1]) {
case 'h':
printHelp(prog_name);
default:
printf("%s: Invalid option %s. Use -h for help. ",
prog_name, *argv);
}
} else {
if (entryCount < LENGTH(entries)) {
entries[entryCount].word = *argv;
entries[entryCount++].counter = 0;
}
}
argv++;
}
if (entryCount == 0) {
printf("%s: Please supply at least one word. Use -h for help. ",
prog_name);
return EXIT_FAILURE;
}
if (entryCount == 1) {
printf("Looking for a single word ");
} else {
printf("Looking for %d words ", entryCount);
}

process_stream(entries, entryCount);
print_result(entries, entryCount);

return EXIT_SUCCESS;
}

// Where assignment1_test.h is:

/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
int run_assignment1_test(int argc, char **argv);
int main(int argc, char **argv);

// Where assignment1_test.c is:

/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/

#define _GNU_SOURCE
#include
#undef _GNU_SOURCE
#include
#include
#include
#include "testrunner.h"
#include "assignment1_test.h"

#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0)

/* test of -h switch behavior (B3) */
int test_help_switch(int argc, char **argv)
{
char *args[] = {"./main", "-h", NULL};
FILE *out, *err, *tmp;
char buffer[100];

freopen("/dev/null", "r", stdin);
freopen("assignment1.out", "w", stdout);
freopen("assignment1.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stdout);
fclose(stderr);

out = fopen("assignment1.out", "r");
err = fopen("assignment1.err", "r");
if (fgets(buffer, 100, out) != NULL && !strncmp(buffer, "usage:", 6)) {
tmp = out;
}
else {
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strncmp(buffer, "usage:", 6));
tmp = err;
}
if (fgets(buffer, 100, tmp) != NULL) {
quit_if(!strcmp(buffer, "./main: Invalid option -h. Use -h for help. "));
}
fclose(out);
fclose(err);
return EXIT_SUCCESS;
}

/* test of basic functionality (B4, B5) */
int test_basic_functionality(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];

out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);

out = fopen("assignment1.out", "r");
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}

/* test of stderr output support (C1) */
int test_stderr_output(int argc, char **argv)
{
char *args[] = {"./main", "-wrong", NULL};
char *result[] = {"./main: Invalid option -wrong. Use -h for help. ",
"./main: Please supply at least one word. Use -h for help. "};
FILE *err;
int i;
char buffer[100];

freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("assignment1.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stderr);

err = fopen("assignment1.err", "r");
for (i = 0; i < 2; i++) {
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(err);
return EXIT_SUCCESS;
}

/* test of -fFILENAME switch behavior (C2) */
int test_file_output(int argc, char **argv)
{
char *args[] = {"./main", "-fassignment1.out", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];

out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("/dev/null", "w", stdout);
freopen("assignment1.in", "r", stdin);
quit_if(main(5, args) != EXIT_SUCCESS);
fcloseall();

quit_if((out = fopen("assignment1.out", "r")) == NULL);
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}

/* test of supporting an arbitrary number of words (C3) */
int test_malloc(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", "c", "a", "t", NULL};
char *result[] = {"Looking for 6 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 ",
"c:0 ", "a:0 ", "t:0 "};
FILE *out;
int i;
char buffer[100];
quit_if(system("grep malloc main.c > /dev/null"));
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(7, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("assignment1.out", "r");
for (i = 0; i < 8; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}

/* test of fgets usage (C4) */
int test_fgets(int argc, char **argv)
{
quit_if(system("grep fgets main.c > /dev/null"));
return EXIT_SUCCESS;
}

/* test of multiple words per line support (C5) */
int test_strtok(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:2 ",
"nap:1 "};
FILE *out;
int i;
char buffer[100];
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, "dog dog nap ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("assignment1.out", "r");
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}

void delete_temp_files()
{
unlink("assignment1.in");
unlink("assignment1.out");
unlink("assignment1.err");
}

/*
* Main entry point for ASSIGNMENT1 test harness
*/
int run_assignment1_test(int argc, char **argv)
{
/* Tests can be invoked by matching their name or their suite name
or 'all'*/
testentry_t tests[] = {
{"help_switch", "suite1", test_help_switch},
{"basic_functionality", "suite1",
test_basic_functionality},
{"stderr_output", "suite1", test_stderr_output},
{"file_output", "suite1", test_file_output},
{"malloc", "suite1", test_malloc},
{"fgets", "suite1", test_fgets},
{"strtok", "suite1", test_strtok}};
atexit(delete_temp_files);
return run_testrunner(argc, argv, tests, sizeof(tests) / sizeof (testentry_t));
}

//

Explanation / Answer

The code is fixed


#include
#include
#include
#include "assignment1_test.h"
#define LENGTH(s) (sizeof(s) / sizeof(*s))
/* Structures */
typedef struct {
char *word;
int counter;
} WordCountEntry;

int process_stream(WordCountEntry entries[], int entry_count)
{
short line_count = 0;
char buffer[30];
while (gets(buffer)) {
if (*buffer == '.')
break;
/* Compare against each entry */
int i = 0;
while (i < entry_count) {
if (!strcmp(entries[i].word, buffer))
entries[i].counter++;
i++;
}
line_count++;
}
return line_count;
}

void print_result(WordCountEntry entries[], int entry_count)
{
printf("Result: ");
while (entry_count-- > 0) {
printf("%s:%d ", entries->word, entries->counter);
}
}

void printHelp(const char *name)
{
printf("usage: %s [-h] ... ", name);
}

int main(int argc, char **argv)
{
const char *prog_name = *argv;
WordCountEntry entries[5];
int entryCount = 0;
/* Entry point for the testrunner program */
if (argc > 1 && !strcmp(argv[1], "-test")) {
run_assignment1_test(argc - 1, argv + 1);
return EXIT_SUCCESS;
}
while (*argv != NULL) {
if (**argv == '-') {
switch ((*argv)[1]) {
case 'h':
printHelp(prog_name);
default:
printf("%s: Invalid option %s. Use -h for help. ",
prog_name, *argv);
}
} else {
if (entryCount < LENGTH(entries)) {
entries[entryCount].word = *argv;
entries[entryCount++].counter = 0;
}
}
argv++;
}
if (entryCount == 0) {
printf("%s: Please supply at least one word. Use -h for help. ",
prog_name);
return EXIT_FAILURE;
}
if (entryCount == 1) {
printf("Looking for a single word ");
} else {
printf("Looking for %d words ", entryCount);
}
process_stream(entries, entryCount);
print_result(entries, entryCount);
return EXIT_SUCCESS;
}
// Where assignment1_test.h is:
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
int run_assignment1_test(int argc, char **argv);
int main(int argc, char **argv);
// Where assignment1_test.c is:
/*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/
#define _GNU_SOURCE
#include
#undef _GNU_SOURCE
#include
#include
#include
#include "testrunner.h"
#include "assignment1_test.h"
#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0)
/* test of -h switch behavior (B3) */
int test_help_switch(int argc, char **argv)
{
char *args[] = {"./main", "-h", NULL};
FILE *out, *err, *tmp;
char buffer[100];
freopen("/dev/null", "r", stdin);
freopen("assignment1.out", "w", stdout);
freopen("assignment1.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stdout);
fclose(stderr);
out = fopen("assignment1.out", "r");
err = fopen("assignment1.err", "r");
if (fgets(buffer, 100, out) != NULL && !strncmp(buffer, "usage:", 6)) {
tmp = out;
}
else {
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strncmp(buffer, "usage:", 6));
tmp = err;
}
if (fgets(buffer, 100, tmp) != NULL) {
quit_if(!strcmp(buffer, "./main: Invalid option -h. Use -h for help. "));
}
fclose(out);
fclose(err);
return EXIT_SUCCESS;
}
/* test of basic functionality (B4, B5) */
int test_basic_functionality(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("assignment1.out", "r");
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of stderr output support (C1) */
int test_stderr_output(int argc, char **argv)
{
char *args[] = {"./main", "-wrong", NULL};
char *result[] = {"./main: Invalid option -wrong. Use -h for help. ",
"./main: Please supply at least one word. Use -h for help. "};
FILE *err;
int i;
char buffer[100];
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("assignment1.err", "w", stderr);
quit_if(main(2, args) != EXIT_FAILURE);
fclose(stderr);
err = fopen("assignment1.err", "r");
for (i = 0; i < 2; i++) {
quit_if(fgets(buffer, 100, err) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(err);
return EXIT_SUCCESS;
}
/* test of -fFILENAME switch behavior (C2) */
int test_file_output(int argc, char **argv)
{
char *args[] = {"./main", "-fassignment1.out", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 "};
FILE *out;
int i;
char buffer[100];
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("/dev/null", "w", stdout);
freopen("assignment1.in", "r", stdin);
quit_if(main(5, args) != EXIT_SUCCESS);
fcloseall();
quit_if((out = fopen("assignment1.out", "r")) == NULL);
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of supporting an arbitrary number of words (C3) */
int test_malloc(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", "c", "a", "t", NULL};
char *result[] = {"Looking for 6 words ",
"Result: ",
"cat:1 ",
"dog:0 ",
"nap:0 ",
"c:0 ", "a:0 ", "t:0 "};
FILE *out;
int i;
char buffer[100];
quit_if(system("grep malloc main.c > /dev/null"));
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(7, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("assignment1.out", "r");
for (i = 0; i < 8; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
/* test of fgets usage (C4) */
int test_fgets(int argc, char **argv)
{
quit_if(system("grep fgets main.c > /dev/null"));
return EXIT_SUCCESS;
}
/* test of multiple words per line support (C5) */
int test_strtok(int argc, char **argv)
{
char *args[] = {"./main", "cat", "dog", "nap", NULL};
char *result[] = {"Looking for 3 words ",
"Result: ",
"cat:1 ",
"dog:2 ",
"nap:1 "};
FILE *out;
int i;
char buffer[100];
out = fopen("assignment1.in", "w");
fprintf(out, "cat ");
fprintf(out, "dog dog nap ");
fprintf(out, ". ");
fclose(out);
freopen("assignment1.in", "r", stdin);
freopen("assignment1.out", "w", stdout);
quit_if(main(4, args) != EXIT_SUCCESS);
fclose(stdin);
fclose(stdout);
out = fopen("assignment1.out", "r");
for (i = 0; i < 5; i++) {
quit_if(fgets(buffer, 100, out) == NULL);
quit_if(strcmp(buffer, result[i]));
}
fclose(out);
return EXIT_SUCCESS;
}
void delete_temp_files()
{
unlink("assignment1.in");
unlink("assignment1.out");
unlink("assignment1.err");
}
/*
* Main entry point for ASSIGNMENT1 test harness
*/
int run_assignment1_test(int argc, char **argv)
{
/* Tests can be invoked by matching their name or their suite name
or 'all'*/
testentry_t tests[] = {
{"help_switch", "suite1", test_help_switch},
{"basic_functionality", "suite1",
test_basic_functionality},
{"stderr_output", "suite1", test_stderr_output},
{"file_output", "suite1", test_file_output},
{"malloc", "suite1", test_malloc},
{"fgets", "suite1", test_fgets},
{"strtok", "suite1", test_strtok}};
atexit(delete_temp_files);
return run_testrunner(argc, argv, tests, sizeof(tests) / sizeof (testentry_t));
}
//