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);
for (i = 0; s[i] != '\0'; i++)
if (strncmp(s+i, t, n) == 0)
return i;
return -1;
}
В табл. 6.4 представлены широко используемые функции из стандартной библиотеки ввода вывода.
fp=fopen(s, mode)
Открыть файл s
; значения mode "r"
, "w"
, "a"
соответствуют чтению, записи и добавлению (при ошибке возвращается NULL) c=gets(fp)
Читать символ: getchar()
это getc(stdin)
putc(c, fp)
Записать символ: putchar(c)
это putc(c, stdout)
ungetc(c, fp)
Вернуть символ во входной файл fp
; можно вернуть не более одного символа за раз scanf(fmt, a1, ...)
Читать символы из stdin
в a1
, ...
в соответствии с fmt
. Каждый ai
должен быть указателем fscanf(fp,...)
Читать из файла fp
sscanf(s,...)
Читать из строки s
printf(fmt, a1, ...)
Форматировать a1
, ... в соответствии с fmt
; печатать в stdout
fprintf(fp, ...)
Печатать ...
в файл fp
sprintf(s, ...)
Печатать ...
в строку s fqets(s, n, fp)
Читать не более n
символов в s
из fp
(возвращается NULL
по концу файла) fputs(s, fp)
Печатать строку s
в файл fp
fflush(fp)
Занести буферизованные данные выходного потока в файл fp
fclose(fp)
Закрыть файл fp
fp=popen(s, mode)
Открыть программный канал для команды s
(см. fopen
) pclose(fp)
Закрыть программный канал fp
system(s)
Запустить команду s
и ждать ее окончания
Таблица 6.4: Полезные стандартные функции ввода-вывода
Упражнение 6.11Модифицируйте
zap
так, чтобы можно было применять любое число аргументов. В настоящем виде zap
высвечивает на экране строку, соответствующую выбранному варианту. Будет она делать это? Если нет, модифицируйте программу соответствующим образом. Подсказка: getpid(2)
.Упражнение 6.12Постройте
fgrep(1)
на основе strindex
. Сравните время работы при сложных поисках, например 10 слов на документ. Почему fgrep
выполняется быстрее?6.8 Диалоговая программа сравнения файлов: idiff
Поддерживать две чем-то отличающиеся версии файла, каждая из которых содержит часть нужного вам файла, довольно распространенная проблема. Зачастую она возникает в тех случаях, когда изменения вносятся независимо двумя разными людьми. Программа
diff
подскажет вам, чем различаются файлы, но вы не получите никакой помощи, если захотите выбрать какую-то информацию из одного файла, а какую-то из другого.В этом разделе мы напишем программу
idiff
(диалоговая diff
), которая предоставляет пользователю каждую порцию выходного потока diff
и предлагает ему возможность выбора фрагментов "от и до" или их редактирования. Программа idiff
помещает выбранные фрагменты в соответствующем порядке в файл idiff.out
. Допустим, даны такие два файла:file1: file2:
This is This is
a test not a test
of of
your our
skill ability.
and comprehension.
diff
вырабатывает следующее:$ diff file1 file2
2c2
< a test
---
> not a test
4,6c4,5
< your
< skill
< and comprehension.
---
> our
> ability.
$
Диалог с
idiff
может выглядеть так:$ idiff file1 file2
2c2
Первое различие< a test
---
> not a test
?