-
Notifications
You must be signed in to change notification settings - Fork 0
/
philspel.c
210 lines (196 loc) · 6.33 KB
/
philspel.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
* Include the provided hash table library.
*/
#include "hashtable.h"
/*
* Include the header file.
*/
#include "philspel.h"
/*
* Standard IO and file routines.
*/
#include <stdio.h>
/*
* General utility routines (including malloc()).
*/
#include <stdlib.h>
/*
* Character utility routines.
*/
#include <ctype.h>
/*
* String utility routines.
*/
#include <string.h>
/*
* This hash table stores the dictionary.
*/
HashTable *dictionary;
/*
* The MAIN routine. You can safely print debugging information
* to standard error (stderr) as shown and it will be ignored in
* the grading process.
*/
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Specify a dictionary\n");
return 0;
}
/*
* Allocate a hash table to store the dictionary.
*/
fprintf(stderr, "Creating hashtable\n");
dictionary = createHashTable(2255, &stringHash, &stringEquals);
fprintf(stderr, "Loading dictionary %s\n", argv[1]);
readDictionary(argv[1]);
fprintf(stderr, "Dictionary loaded\n");
fprintf(stderr, "Processing stdin\n");
processInput();
/*
* The MAIN function in C should always return 0 as a way of telling
* whatever program invoked this that everything went OK.
*/
return 0;
}
/*
* This should hash a string to a bucket index. Void *s can be safely cast
* to a char * (null terminated string) and is already done for you here
* for convenience.
*/
unsigned int stringHash(void *s) {
char *string = (char *)s;
// -- TODO --
unsigned hash = 0;
for (size_t i = 0; i < strlen(string); i++) {
hash = hash * 31 + string[i];
}
return hash % 2255;
}
/*
* This should return a nonzero value if the two strings are identical
* (case sensitive comparison) and 0 otherwise.
*/
int stringEquals(void *s1, void *s2) {
char *string1 = (char *)s1;
char *string2 = (char *)s2;
// -- TODO --
return strcmp(string1, string2) == 0;
}
/*
* This function should read in every word from the dictionary and
* store it in the hash table. You should first open the file specified,
* then read the words one at a time and insert them into the dictionary.
* Once the file is read in completely, return. You will need to allocate
* (using malloc()) space for each word. As described in the spec, you
* can initially assume that no word is longer than 60 characters. However,
* for the final 20% of your grade, you cannot assumed that words have a bounded
* length. You CANNOT assume that the specified file exists. If the file does
* NOT exist, you should print some message to standard error and call exit(1)
* to cleanly exit the program.
*
* Since the format is one word at a time, with new lines in between,
* you can safely use fscanf() to read in the strings until you want to handle
* arbitrarily long dictionary chacaters.
*/
void readDictionary(char *dictName) {
// -- TODO --
FILE *dict = fopen(dictName, "r");
if (dict == NULL) {
fprintf(stderr, "Dictionary file does not exist\n");
exit(1);
}
size_t maxWordLength = 60;
char *wordBuffer = malloc(sizeof(char) * (maxWordLength + 1));
wordBuffer[0] = '\0';
for (char charBuffer = fgetc(dict);; charBuffer = fgetc(dict)) {
size_t wordLength = strlen(wordBuffer);
if (charBuffer == '\n' || charBuffer == EOF) {
char *word = malloc(sizeof(char) * (wordLength + 1));
strcpy(word, wordBuffer);
insertData(dictionary, word, word);
if (charBuffer == EOF) {
break;
}
wordBuffer[0] = '\0';
} else {
if (wordLength == maxWordLength) {
maxWordLength *= 1.5;
wordBuffer = realloc(wordBuffer, sizeof(char) * (maxWordLength + 1));
}
wordBuffer[wordLength] = charBuffer;
wordBuffer[wordLength + 1] = '\0';
}
}
free(wordBuffer);
fclose(dict);
}
/*
* This should process standard input (stdin) and copy it to standard
* output (stdout) as specified in the spec (e.g., if a standard
* dictionary was used and the string "this is a taest of this-proGram"
* was given to stdin, the output to stdout should be
* "this is a teast [sic] of this-proGram"). All words should be checked
* against the dictionary as they are input, then with all but the first
* letter converted to lowercase, and finally with all letters converted
* to lowercase. Only if all 3 cases are not in the dictionary should it
* be reported as not found by appending " [sic]" after the error.
*
* Since we care about preserving whitespace and pass through all non alphabet
* characters untouched, scanf() is probably insufficent (since it only considers
* whitespace as breaking strings), meaning you will probably have
* to get characters from stdin one at a time.
*
* Do note that even under the initial assumption that no word is longer than 60
* characters, you may still encounter strings of non-alphabetic characters (e.g.,
* numbers and punctuation) which are longer than 60 characters. Again, for the
* final 20% of your grade, you cannot assume words have a bounded length.
*/
void processInput() {
// -- TODO --
size_t maxWordLength = 60;
char *wordBuffer = malloc(sizeof(char) * (maxWordLength + 1));
wordBuffer[0] = '\0';
for (char charBuffer = getchar();; charBuffer = getchar()) {
size_t wordLength = strlen(wordBuffer);
if (isalpha(charBuffer)) {
if (wordLength == maxWordLength) {
maxWordLength *= 1.5;
wordBuffer = realloc(wordBuffer, sizeof(char) * (maxWordLength + 1));
}
wordBuffer[wordLength] = charBuffer;
wordBuffer[wordLength + 1] = '\0';
} else {
if (wordLength > 0) {
char word[wordLength + 1];
strcpy(word, wordBuffer);
int matched = 0;
if (findData(dictionary, wordBuffer) != NULL) {
matched = 1;
} else {
for (int i = 1; i < wordLength; i++) {
wordBuffer[i] = tolower(wordBuffer[i]);
}
if (findData(dictionary, wordBuffer) != NULL) {
matched = 1;
} else {
wordBuffer[0] = tolower(wordBuffer[0]);
if (findData(dictionary, wordBuffer) != NULL) {
matched = 1;
}
}
}
if (matched) {
printf("%s", word);
} else {
printf("%s [sic]", word);
}
wordBuffer[0] = '\0';
}
if (charBuffer == EOF) {
break;
}
printf("%c", charBuffer);
}
}
free(wordBuffer);
}