#include #include #include #include #include typedef struct { // True if user provided valid arguments, false on error bool valid_arguments; // User asked --help and it must be printed bool help_requested; // Number of input filenames found in arguments, if 0 stdin will be used size_t input_filename_count; // Name of the file where output will be printed, if NULL stdout will be used char* output_filename; } arguments_t; void init_arguments(arguments_t* arguments); arguments_t parse_arguments(int argc, char* argv[]); int print_help(); int reverse_speech(FILE* input_file, FILE* output_file); int reverse_speech_in_file(const char* input_filename, FILE* output_file); int main(int argc, char* argv[]) { setlocale(LC_ALL, ""); // Fields in structures may be word-aligned, and it may requiere more bits // printf("sizeof(arguments_t): %zu\n", sizeof(arguments_t)); // The entire local structure is overwritten by the struct returned by parse_arguments arguments_t arguments = parse_arguments(argc, argv); // If argument --help was provided, ignore the rest if ( arguments.help_requested ) return print_help(); // If the provided arguments are wrong, stop if ( ! arguments.valid_arguments ) return 1; // Assume stdout as output file FILE* output_file = stdout; if ( arguments.output_filename ) { // A filename was provided with "-o file" option, open it as output file output_file = fopen(arguments.output_filename, "w"); if ( output_file == NULL ) return fprintf(stderr, "reverse_speech: error: could not open %s\n", arguments.output_filename); } // If not input files were provided, use stdin int result = 0; if ( arguments.input_filename_count == 0 ) result = reverse_speech(stdin, output_file); else { // One or more input files were provided // Traverse arguments again processing these input files for ( int index = 1; index < argc; ++index ) { // Ignore options (they begin with '-') if ( argv[index][0] == '-' ) { // Ignore output filename if it was provided if ( argv[index][1] == 'o' ) ++index; } else { // An input filename was found, process it // We do not stop processing other files if one fails result += reverse_speech_in_file(argv[index], output_file); } } } // If an output filename was used, close it if ( arguments.output_filename ) fclose(output_file); return result; } int print_help() { const char* const help = "reverse_speech v1.0 [2016-Sep-23] jeissonh@gmail.com\n" "Reverts speech in the concatenation of input text FILES\n" "\n" " Usage: reverse_speech [FILES] [-o OUTPUT_FILE]\n" "\n" "Rvereesd sepceh dsiottroins lteetrs psotioins wtiihn wrods, but\n" "keeipng frist and lsat lteetr. Hmuan barnis are albe to rseotre\n" "mseasegs form tehse dsiottroins.\n" ; printf("%s", help); return 0; } void init_arguments(arguments_t* arguments) { (*arguments).help_requested = false; (*arguments).input_filename_count = 0; arguments->output_filename = NULL; } arguments_t parse_arguments(int argc, char* argv[]) { arguments_t result; init_arguments( &result ); for ( int index = 1; index < argc; ++index ) { if ( strcmp(argv[index], "--help") == 0 ) result.help_requested = true; else if ( *argv[index] == '-' ) { if ( strcmp(argv[index], "-o") == 0 ) { if ( index + 1 < argc ) { result.output_filename = argv[index + 1]; ++index; } else { fprintf(stderr, "reverse_speech: error: missing output filename\n"); } } } else ++result.input_filename_count; } return result; } int reverse_speech_in_file(const char* input_filename, FILE* output_file) { FILE* input_file = fopen(input_filename, "r"); if ( input_file == NULL ) { fprintf(stderr, "reverse_speech: error: could not open %s\n", input_filename); return 2; } int result = reverse_speech(input_file, output_file); fclose(input_file); return result; } int reverse_speech(FILE* input_file, FILE* output_file) { wchar_t previous = 0, current = 0, next = 0; if ( fwscanf(input_file, L"%lc", ¤t) == WEOF ) return 0; while ( fwscanf(input_file, L"%lc", &next) != WEOF ) { if ( iswalpha(previous) && iswalpha(current) && iswalpha(next) ) { wint_t next2 = fgetwc(input_file); if ( iswalpha(next2) ) { fwprintf(output_file, L"%lc", next); next = next2; } else if ( next2 != WEOF ) { fwprintf(output_file, L"%lc", current); previous = current; current = next; next = next2; } } fwprintf(output_file, L"%lc", current); previous = current; current = next; } fwprintf(output_file, L"%lc", current); return 0; }