#include #include #include #include struct code_struct { // valid is 1 if a valid code has been stored in this object // successfully, and valid is 0 otherwise (if, let's say, we // encountered errors while reading the file that stores the code). int valid; int m; // number of bits in original word int n; // number of bits in codeword int number; // number of original words, equals 2^m. int distance; // distance of the code. // original is a 2D array, with 2^m rows and m columns. // original[i] is the i-th original word, and it is actually // the string of '0' and '1' characters that represents number i // in binary. char ** original; // Codebook is a 2D array, with 2^m rows and n columns. // Each row is a string of '0' and '1' characters that is // the codeword for original[i]; char ** codebook; }; // computes and returns the number of positions where code1 and code2 // differ. length is the number of characters in each of code1 and code2. int hammingDistance(char * code1, char * code2, int length); // For the specified word, this function computes the distance to each // string in codes, and identifies the index of the most similar codeword. // It returns that index. // number is the number of strings in codes, and length is the // length of each string in codes. // If there were ties (more than one codeword had the smallest distance to // word), *tie_flag is set to 1, otherwise it is set to 0. int nearestWord(char ** codes, char * word, int number, int length, int * tie_flag); int codeDistance(struct code_struct code); void destroyCode(struct code_struct code) { int i; for (i = 0; i < code.number; i++) { free(code.original[i]); free(code.codebook[i]); } free(code.original); free(code.codebook); code.valid = 0; } struct code_struct read_code(char * code_file) { struct code_struct result; result.valid = -1; FILE * handle = fopen(code_file, "rb"); if (handle == 0) { printf("failed to open file %s\n", code_file); return result; } int items; items = fscanf(handle, "%d %d", &(result.m), &(result.n)); if (items != 2) { printf("failed to read m and n\n"); return result; } result.number = (int) pow(2, result.m); result.original = malloc(sizeof(char*) * result.number); result.codebook = malloc(sizeof(char*) * result.number); int i; for (i = 0; i < result.number; i++) { result.original[i] = malloc(sizeof(char) * result.m); result.codebook[i] = malloc(sizeof(char) * result.n); } char buffer1[1000]; char buffer2[1000]; for (i = 0; i < result.number; i++) { items = fscanf(handle, "%s %s", buffer1, buffer2); if (items != 2) { printf("failed to read entry %d\n", i); destroyCode(result); return result; } int len = strlen(buffer1); if (len != result.m) { printf("error: original word %d has %d characters%d\n", i, len); destroyCode(result); return result; } len = strlen(buffer2); if (len != result.n) { printf("error: original word %d has %d characters%d\n", i, len); destroyCode(result); return result; } memcpy(result.original[i], buffer1, result.m); memcpy(result.codebook[i], buffer2, result.n); } fclose(handle); result.distance = codeDistance(result); result.valid = 1; return result; } // input_buffer contains a string whose characters are '0' and '1' // and that represents an original word. // This identifies and returns the corresponding codeword. void convert_to_codeword(struct code_struct code, char * input_buffer, char * output_buffer); // output_buffer contains a string whose characters // are '0' and '1' and that represents a codeword in binary. // This function decodes the codeword, and the stores the original // word in output_buffer, as a string as a string of // binary ('0' and '1') characters. // returns: // 1 if no error was detected. // 0 if an error was detected and corrected. // -1 if an error was detected but not corrected. int convert_to_original_word(struct code_struct code, char * input_buffer, char * output_buffer); // Reads data from the input file (represented by input_handle) // in chunks of m_parameter characters, that represent an original word. // Each chunk is encoded, and the n-character-long // result is stored at the output file (represented by output_handle). void encode(struct code_struct code, FILE * input_handle, FILE * output_handle) { char * input_buffer = malloc(sizeof(char)*code.m); char * output_buffer = malloc(sizeof(char)*code.n); while(1) { // read the next "word" from the input file int items = fread(input_buffer, sizeof(char), code.m, input_handle); if (items != code.m) { break; } // This is where your function is called. convert_to_codeword(code, input_buffer, output_buffer); // Write the "codeword" to the output file. fwrite(output_buffer, sizeof(char), code.n, output_handle); } free(input_buffer); free(output_buffer); } // Reads data from the input file (represented by input_handle) // in chunks of n characters, that represent codewords in binary digits. // Each chunk is decoded, and the m-character-long // result (containing '0' and '1' characters and representing the original // code in binary) is stored at the output file (represented by // output_handle). // // This function also prints, for each detected error: // - the position of the word containing the error. void decode(struct code_struct code, FILE * input_handle, FILE * output_handle) { char * input_buffer = malloc(sizeof(char)*code.n); char * output_buffer = malloc(sizeof(char)*code.m); int word_counter = 0; while(1) { int items = fread(input_buffer, sizeof(char), code.n, input_handle); if (items != code.n) { break; } // This is where your function is called. int result = convert_to_original_word(code, input_buffer, output_buffer); fwrite(output_buffer, sizeof(char), code.m, output_handle); if (result == 0) { printf("error detected and corrected at word %d\n", word_counter); } else if (result == -1) { printf("error detected and NOT corrected at word %d\n", word_counter); } word_counter++; } } int main(int argc, char ** argv) { if (argc != 5) { printf("error: four command-line arguments needed:\n"); printf(" number code_file input_file output_file\n"); return 1; } // int number = 1; // char * code_file = "code1.txt"; // char * input_file = "out1.txt"; // char * output_file = "out2.txt"; int number = atoi(argv[1]); char * code_file = argv[2]; char * input_file = argv[3]; char * output_file = argv[4]; struct code_struct code = read_code(code_file); if (code.valid == 0) { printf("failed to load a valid code from: %s\n", code_file); } FILE * input_handle = fopen(input_file, "rb"); FILE * output_handle = fopen(output_file, "wb"); if (number == 0) // we must do encoding { // do the encoding encode(code, input_handle, output_handle); // close the files. fclose(input_handle); fclose(output_handle); } else if (number == 1) { // do the decoding and correction. decode(code, input_handle, output_handle); // close the files. fclose(input_handle); fclose(output_handle); } destroyCode(code); return 0; }