#c #printf
#c #printf
Вопрос:
У меня есть программа на языке C, которая выводит некоторые данные на стандартный вывод. Я использовал printf
для этого, но мне также нужно сохранить данные в файл, поэтому я изменил его на fprintf
. Проблема в том, что при использовании fprintf данные располагаются в неправильном порядке, не имеет значения, является ли вывод стандартным выводом или файлом.
if(...) {
out = fopen(param.F, "w");
} else {
out = stdout;
}
// some code here
fprintf(out, "a");
// more code
fprintf(out, "b");
....
После этого выходные данные всегда разные. Иногда это
acb
Иногда это
cab
и т.д. … Я пробовал различные комбинации setbuf и fflush, но ни одна из них не помогла.
РЕДАКТИРОВАТЬ: Возможно, важно знать, что я использую некоторые fork()
в своей программе, но, как я упоминал ранее, при использовании printf проблем нет.
Вот мой вывод:
1: парикмахерская: проверяет
2: клиент 1: создан
3: клиент 1: вводит
5: парикмахер: готов
6: клиент 1: готов
4: клиент 2: создан
7: парикмахерская: закончена
8: парикмахерская: проверяет
9: клиент 2: вводит
10: клиент 1: обслужен
11: парикмахер: готов
12: клиент 2: готов
13: парикмахер: закончено
14: парикмахерская: проверяет
15: клиент 2: обслужен
Они должны быть упорядочены по номерам. Программа имеет структуру, подобную этой:
int main() {
pid = fork();
if(pid == 0) {
// barber printfs
} else if (pid > 0) {
// customer printfs
}
}
Комментарии:
1. Пожалуйста, опубликуйте простой тестовый пример с входными данными и ожидаемыми результатами, который показывает вашу проблему. В противном случае мы просто предполагаем.
2. Я использую fork, но он работал с printf
3. Вам нужно опубликовать весь соответствующий код. В опубликованном вами коде нет ничего изначально неправильного. (Кроме того, где печатается ‘c’?)
4. Что ж, моя проблема была «решена». У меня был особый случай входных данных, для которых выходные данные были в неправильном порядке, в остальном все работает нормально. Тем не менее, спасибо за вашу помощь!
5. звучит подозрительно, как будто у нас отсутствует тег для домашнего задания.
Ответ №1:
(Не могу прокомментировать, должен ответить …)
Нет, дело не в том, что буфер printf / fprintf отличается, объект FILE * остается тем же самым, если вы выполняете fprintf(стандартный вывод, …) или printf(….).
Несколько процессов записывают данные в один и тот же файл, и в результате отсутствия синхронизации и разной буферизации в каждом процессе выходные данные перепутаны.
Ответ №2:
у printf и fprintf будет разная буферизация драйвера устройства.
Поскольку вы говорите, что используете fork, и на основе выходных данных я делаю вывод, что код похож на
- Открыть файл
- Форк
- Записать данные
В этом случае возникает другой порядок, потому что запись происходит в случайном порядке, в зависимости от того, когда запланирован каждый дочерний процесс.
Самое простое решение — просто обернуть приложение в сценарий оболочки и запустить двоичный файл через tee — таким образом, все, что вы регистрируете в stdout, также отправляется в file.
Если вам нужно более сложное решение, вам нужно настроить механизм IPC между процессами и выполнять все операции записи в родительском.
Один из подходов заключается в том, чтобы установить стандартный вывод в канал (из socketpair) перед форком и прочитать из канала в родительском процессе (используя select(), чтобы избежать блокировки), затем войти в screen / file. Вам нужно будет выполнить dup() stdout перед использованием freopen, чтобы избежать его потери. Я, вероятно, пропустил несколько вещей, поскольку я не делал этого некоторое время.