[P&AM Lab] генератор паролей

Grigoriy A. Sitkarev sitkarev на komitex.ru
Вт Фев 15 01:46:31 MSK 2011


Уже поздно. Завтра утром наверное прочтёте.

1. Давайте договоримся что комментарии мы будем стараться писать на 
английском языке, это полезно с точки зрения языковой практики, набора 
словарного запаса и пригодится в будущем -- не все программисты говорят 
на русском, но почти все понимают английский.

2. Хоть программа и не большая, даже здесь лучше бы было разбить её на 
ряд чётких, небольших функций. Каждая из которых выполняет одно действие 
и делает это хорошо. Хорошие программы состоят не из малого числа 
больших функций, а большого числа малых.

3. В K&R С внутри switch ключевые слова case не нужно отделять ещё раз 
табуляцией. Они относятся к тому же уровню вложенности.

switch (tag) {
case 0:
	...
	break;
case 1:
	...
	break;
	...
}

4. Если мы хотим вывести строку на терминал, не надо это делать посимвольно:

	for (i = 0; i < passlen; i++) {
		printf("%c", password[i]);
	}

Нужно было сначала терминировать нулём строку в password, и объявлять 
этот массив нужно было наверное так:

#define MAX_LENGTH	255

int main(int argc, char *argv[]) {
	...
	char password[MAX_LENGTH+1];
	...
	for (i = 0; i < passlen; i++) {
		tag = lrand48() % 3;
	...
	}

	//Выводим пароль на экран, чтобы было не так грустно//
	printf("Password: ");	

	password[passlen] = '\0';

	printf("%s", password);

Думаю что идея ясна.

5. Думаю что стоит читать полностью строку в буфер из stdin через 
fgets(3) а потом травить на неё strcasecmp(3) и проверять что там ввёл 
пользователь и устанавливать флаг. Другой вариант, переписать проще 
цикл, и не забыть про tolower(3).

6. Делать проверку повторно на confirm == 'Y' и confirm == 'y' не нужно. 
Для этого нужно было ранее сделать переменную-флаг и проверять её.

if (write_to_file) {
	...
}

7. Дальше, очень сложно сделано считывание путей. Наверно городить 
огород с динамическим выделением памяти для буферов не стоит, да и 
читать посимвольно и каждый раз увеличивать буфера на 1 байт тоже. Кроме 
того, очень сложные условия стоят в циклах, этого нужно стараться 
избегать. Они должны быть предельно простыми и идиоматичными. А уже 
внутри цикла проверяйте условия ещё раз и пользуйтесь оператором break.

for (pathlen = 0; (((c = getchar()) != EOF) &&
	(c != '\n') && (pathlen != PATH_MAX) ); pathlen++) {
	...
}

Проще бы было:

for (pathlen = 0; (c = getchar()) != EOF; pathlen++) {

	if (c == '\n')
		break;

	if (pathlen >= PATH_MAX-1)
		break;
	...
}

Обратите внимание что я проверяю PATH_MAX-1, потому что нужно ещё место 
для терминирующего нуля.

Про буфера я уже сказал, никаких malloc(3)/realloc(3) там всё же не 
нужно. Достаточно буферов статического размера. POSIX/SUSv2 гарантирует 
что имена файлов и путей вместятся в эти лимиты:

char filename[NAME_MAX+1];
char pathname[PATH];
char path[PATH];

У нас в рассылке раньше где-то было сообщение о том что это за лимиты и 
откуда они взялись.

И всё равно не понятно, почему отдельно просят файл а потом ещё и 
каталог? Если можно сразу попросить ввести путь. И в UNIX обычно так и 
делается. Если просят ввести путь к файлу, то туда можно вводить 
абсолютный и относительный пути (если не оговорено обратное).

Системный вызов open(2) вообще-то открывает путь как относительный так и 
абсолютный. Может быть в этом была загвоздка?

8. Читать, ещё раз повторюсь, посимвольно через getchar(3) наверное не 
стоит в тех случаях. Проще сделать это через fgets(3).

9. Принято в большинстве случаев сообщения на stderr и в лог-файлы 
отправлять без завершающей точки. Обратите внимание как пишет ядро на 
консоль и в логи, как ведут себя другие прикладные программы и утилиты. 
Отмечу что грамматически сообщения составлены корректно и ясно отражают 
смысл ошибок/событий.

Как итог, программу можно существенно упростить, она будет короче, 
понятнее и яснее. Есть над чем потрудиться. Когда я что-то ещё вспомню, 
напишу в рассылку. Очень приятно видеть что идёт процесс, приходит 
понимание и присутствует творчество. Нужно идти вперёд.

--
Г.А.

13.02.2011 22:32, Константин Никулов пишет:
> Прощу прощения, не тот файл сбросил. Вот в этом...




Подробная информация о списке рассылки Lab