Мы показали вам типичную ошибку, которая является скорее результатом просмотра, а не неправильного программирования. Искать подобные ошибки при вызове функции с неверными аргументами можно также с помощью верифицирующей программы для Си lint(1)
lint с файлом pick.с, ошибка идентифицируется:$ lint pick.с
...
fprintf, arg. 1 несовместим "llib-lc"(69) :: "pick.c"(28)
...
$
Это означает, что первый аргумент в стандартной библиотеке определен иначе, чем в строке 28 вашей программы. Таким образом дана точная информация о том, что неверно.
Программа lint
lint помогает обнаружить некоторые ошибки, которые человек увидеть практически не может. После длительного редактирования всегда стоит запустить lint и убедиться в том, что каждое выдаваемое этой программой предупреждение вам понятно.6.7 Пример: zap
Программа zap
shell в гл. 5. Главная проблема данной версии скорость. Она создает много процессов и поэтому работает медленно, что недопустимо для программы, уничтожающей процессы с ошибками. Если переписать zap на Си, ее быстродействие повысится. Мы, однако, снова воспользуемся ps, чтобы найти информацию о процессе. Это намного легче, чем выуживать информацию из ядра, и, кроме того, мы имеем переносимый вариант. Программа zap открывает программный канал, входной поток для которого берется из ps, и читает из него, как из файла. Функция popen(3) аналогична fopen, за исключением того, что первый аргумент является командой, а не именем файла. То же самое справедливо и для pclose, но здесь она нам не нужна./* zap: interactive process killer */
#include
#include
char *progname; /* program name for error message */
char *ps = "ps -ag"; /* system dependent */
main(argc, argv)
int argc;
char *argv[];
{
FILE *fin, *popen();
char buf[BUFSIZ];
int pid;
progname = argv[0];
if ((fin = popen(ps, "r")) == NULL) {
fprintf(stderr, "%s: can't run %s\n", progname, ps);
exit(1);
}
fgets(buf, sizeof buf, fin); /* get header line */
fprintf(stderr, "%s", buf);
while (fgets(buf, sizeof buf, fin) != NULL)
if (argc == 1 || strindex(buf, argv[1]) >= 0) {
buf[strlen(buf)-1] = '\0'; /* suppress \n */
fprintf(stderr, "%s? ", buf);
if (ttyin() == 'y') {
sscanf(buf, "%d", &pid);
kill(pid, SIGKILL);
}
}
exit(0);
}
Мы писали программу, чтобы использовать ps -ag
Первый вызов fgets
ps; интересно выяснить, что случится, если попытаться уничтожить "процесс", соответствующий данному заголовку.Функция sscanf
scanf(3) для форматного преобразования входной строки. Она преобразует строку, а не файл. Вызов kill из системы посылает специальный сигнал процессу; сигнал SIGKILL, определенный в , не может быть перехвачен или проигнорирован. Вы можете вспомнить пятую главу, где его численное значение равно девяти, но лучше использовать символические константы из файлов макроопределений, чем включать в свои программы загадочные числа.Если аргументы отсутствуют, zap
ps как возможность для выбора. При наличии аргумента zap предлагает только те выходные строки ps, которые ему соответствуют. Функция strindex(s1, s2) проверяет, соответствует ли аргумент какой-либо части строки выходного потока ps, используя strncmp (см. табл. 6.2). Функция strindex возвращает позицию s2 в s1 или -1, если ее там нет.strindex(s, t) /* return index of t in s, -1 if none */
char *s, *t;
{
int i, n;
n = strlen(t);