Skip to content

Instantly share code, notes, and snippets.

@dralletje
Created October 23, 2015 17:32
Show Gist options
  • Save dralletje/89d5bc5eed1d5deb962c to your computer and use it in GitHub Desktop.
Save dralletje/89d5bc5eed1d5deb962c to your computer and use it in GitHub Desktop.
#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
const int max_word_length = 60;
const int max_words_length = 300000;
const int max_command_length = 100;
const int max_filename_length = 80;
typedef char Word [max_word_length];
typedef Word Words [max_words_length];
// Overwrite the array at one position with the content of an other array
void copy_word(Word target, Word source) {
for (int i = 0; i < max_word_length; i = i + 1) {
target[i] = source[i];
}
}
// Print a string with a newline
void print(string msg) {
cout << msg << "\n";
}
// Check two word arrays for equality
bool compare_word(Word one, Word two) {
string one_string(one);
string two_string(two);
return one_string == two_string;
}
// Find index of Word in Words. If not found, return negative index.
int find_occurence(Word needle, Words haystack, int words_count, int offset) {
// Offset cant be off limits
assert(offset < words_count);
assert(words_count > 0);
for(int i = offset; i < words_count; i = i + 1) {
if(compare_word(haystack[i], needle)) {
return i;
}
}
return -1;
}
// Make sure there is a sequence like the one in `input` at the position
// `words_index` in the array `words`
bool ensure_sequence(Words input, int input_length, Words words, int words_count, int words_index, int input_offset) {
assert(input_offset <= input_length);
assert(words_index <= words_count);
int real_length = input_length - input_offset;
int input_index = 0;
// No sequence given.. guess that's always correct then
if (real_length == 0) {
return words_index;
}
// Loop over both arrays to compare them
while(
words_index + input_index <= words_count &&
compare_word(input[input_index + input_offset], words[words_index + input_index])
) {
input_index = input_index + 1;
if(real_length == input_index) {
return true;
}
}
return false;
}
// Just wrap `find_occurence` and `ensure_sequence`
int find_sequence(
Words input, int input_length, Words words,
int words_count, int input_offset, int offset
) {
assert(offset <= words_count);
assert(input_offset <= input_length);
int index = find_occurence(input[input_offset], words, words_count, offset);
if (index != -1 && ensure_sequence(input, input_length, words, words_count, index, input_offset)) {
return index;
} else {
return -1;
}
}
// Given by the exercise
bool read_word (ifstream& infile, Word word) {
infile >> word;
return word;
}
// Load words from a file stream and put them in an array
int read_words (ifstream& infile, Words words) {
assert(infile.is_open());
int word_counter = 0;
Word word;
while (read_word(infile, word) == true) {
if (!infile) {
break;
}
copy_word(words[word_counter], word);
word_counter = word_counter + 1;
}
return word_counter;
}
Words words_read;
Words words_input;
Word empty_word;
int main() {
int words_count;
for(int i = 0; i < max_word_length; i = i + 1) {
empty_word[i] = '\0';
}
while (true) {
// Reset the array of command words
for (int i = 0; i < max_words_length; i = i + 1) {
copy_word(words_input[i], empty_word);
}
// Request new command
cout << "\n> ";
char input[max_command_length];
for(int i = 0; i < max_command_length; i = i + 1) {
input[i] = '\0';
}
cin.getline(input, max_command_length);
cin.clear();
// Split it up in words
int words_index = 0;
int char_index = 0;
for (int i = 0; i < max_command_length; i = i + 1) {
char current = input[i];
if (current != ' ') {
words_input[words_index][char_index] = current;
char_index = char_index + 1;
} else {
words_index = words_index + 1;
char_index = 0;
}
}
int input_length = words_index + 1;
string command = words_input[0];
if(command == "enter") {
ifstream infile;
string filename;
if (input_length < 2) {
print("`enter` requires at least one argument.");
continue;
}
// Construct filename from args
for (int i = 1; i < input_length; i = i + 1) {
if (i == 1) {
filename = words_input[i];
} else {
filename = filename + " " + words_input[i];
}
}
// I find assert here a little too agressive
infile.open(filename);
if(!infile.is_open()) {
print("Opening file failed, have another try.");
continue;
}
// Read it!
words_count = read_words(infile, words_read);
// Notify the user
print("Sucessfully opened file " + filename + ".");
print("A total of " + to_string(words_count) + " words counted.");
continue;
}
if (command == "content") {
// Print every word
for(int i = 0; i < words_count; i = i + 1) {
cout << words_read[i] << " ";
}
print("");
continue;
}
// Simply exit the programmmmm
if (command == "stop") {
if (input_length > 1) {
print("`stop` doesn't take any arguments.");
continue;
}
print("Bye!");
exit(0);
}
if (command == "count") {
if (input_length < 2) {
print("`count` requires at least one argument.");
continue;
}
// Find every sencuence occurence and increase `count`
int count = 0;
int index = find_sequence(words_input, input_length, words_read, words_count, 1, 0);
while(index != -1) {
count = count + 1;
int position = index + input_length;
index = find_sequence(words_input, input_length, words_read, words_count, 1, position);
}
// Just to print it here
print("Found the sequence " + to_string(count) + " times.");
continue;
}
if (command == "where") {
if (input_length < 2) {
print("`count` requires at least one argument.");
continue;
}
// Go over all found sequences, but also display the index they are found at.
int count = 0;
int index = find_sequence(words_input, input_length, words_read, words_count, 1, 0);
while(index != -1) {
print("Found at position " + to_string(index) + ".");
count = count + 1;
int position = index + input_length;
index = find_sequence(words_input, input_length, words_read, words_count, 1, position);
}
// And the total number ofcourse
print("Found the sequence " + to_string(count) + " times.");
continue;
}
if (command == "context") {
if (input_length < 3) {
print("`content` requires at least two arguments.");
continue;
}
// Convert string argument to number
int m = atoi(words_input[1]);
// Error if it's not a number or lower than 1
if(m < 1) {
print("first argument for `content` should be a *number* higher than 0.");
continue;
}
// Again, find all sequences
int count = 0;
int index = find_sequence(words_input, input_length, words_read, words_count, 2, 0);
while(index != -1) {
// But now, also print all words around it
cout << "|";
int begin = max(index - m, 0);
int end = min(index + input_length + m - 2, words_count);
for(int i = begin; i < end; i = i + 1) {
cout << " " << words_read[i];
}
print("");
// And as usual, count it...
count = count + 1;
int position = index + input_length;
index = find_sequence(words_input, input_length, words_read, words_count, 2, position);
}
// ... and print it
print("Found the sequence " + to_string(count) + " times.");
continue;
}
cout << "please enter a valid choice" << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment