Деконструкция и реконструкция
Текущая структура кода, чтобы быть вежливой, капризная.
Вы должны открывать файлы в той же функции - вероятно, main()
.Там должно быть два параллельных блока кода.Фактически, в идеале, вы должны выполнять открытие и обработку ошибок в функции, чтобы main()
просто содержал:
FILE *cfPtr1 = file_open("mike1.txt");
FILE *cfPtr2 = file_open("mike2.txt");
Если элемент управления возвращается к main()
, файлы открыты и готовы к использованию..
Затем вам нужно прочитать строку из каждого файла - снова в main()
.Если какой-либо файл не содержит строки, вы можете выручить с соответствующей ошибкой:
if (fgets(buffer1, sizeof(buffer1), cfPtr1) == 0)
...error: failed to read file1...
if (fgets(buffer2, sizeof(buffer2), cfPtr2) == 0)
...error: failed to read file2...
Затем вы вызываете код сравнения с двумя строками:
findWord(buffer1, buffer2);
Вам нужнотщательно отделять операции ввода-вывода от фактической обработки данных;если вы чередуете их, как в первой попытке, все становится очень грязно.Ввод / вывод имеет тенденцию быть запутанным, просто потому что у вас есть условия ошибок, с которыми приходится иметь дело - поэтому я перевёл операцию открытия в отдельную функцию (вдвойне, так как вам нужно сделать это дважды).
Вы можете решитьтакже обернуть вызов fgets()
и обработку ошибок в функции:
const char *file1 = "mike1.txt";
const char *file2 = "mike2.txt";
read_line(cfPtr1, file1, buffer1, sizeof(buffer1));
read_line(cfPtr2, file2, buffer2, sizeof(buffer2));
Эта функция может обрезать перевод строки с конца строки и обрабатывать все, что вы хотите, чтобы она выполнялась -и сообщите точную ошибку, включая имя файла, если что-то пойдет не так.Очевидно, что с переменными 'file1' и 'file2' вы будете использовать их вместо литеральных строк в вызовах file_open()
.Также обратите внимание, что преобразование их в переменные означает, что брать имена файлов из командной строки тривиально;вы просто устанавливаете 'file1' и 'file2', чтобы они указывали на список аргументов вместо аппаратных настроек по умолчанию.(Я на самом деле написал: const char file1[] = "mike1.txt";
кратко - но потом понял, что если вы обрабатываете имена файлов через командную строку, то вам нужны указатели, а не массивы.)
Кроме того, если вы открываете файл, вы должнызакройте файл тоже.Конечно, если ваша программа завершается, o / s убираются позади вас, но это хорошая дисциплина, в которую нужно войти.Одна из причин заключается в том, что не каждая программа завершает работу (вспомните о демонах, запускающих службы на вашем компьютере).Другое - то, что вы довольно часто кратко используете ресурс (файл, в текущем обсуждении) и больше не нуждаетесь в нем.Вы не должны хранить ресурсы в вашей программе дольше, чем вам нужно.
Философия
У Поли в его книге 1957 года "Как ее решить" есть изречение:
- Старайтесь симметрично трактовать то, что симметрично, и не разрушайте бессмысленно любую естественную симметрию.
Это такой же верный совет в программировании, как и в математике.И в своей классической книге 1978 года «Элементы стиля программирования» Керниган и Плаугер делают выразительные утверждения:
- [вызов] подпрограммы позволяет нам обобщить неровностей всписок аргументов [...]
- Сама подпрограмма суммирует закономерности кода.
В более современных книгах, таких как ' The PragmaticПрограммист 'от Hunt & Thomas (1999), изречение переведено на быстрый TLA:
- СУХОЙ - не повторяйте себя.
Если вынайдите свой код, выполняя «одни и те же» строки кода, повторенные несколько раз, напишите подпрограмму, чтобы сделать это один раз, и вызовите подпрограмму несколько раз.
Это то, к чему стремится мой переписанный код.