Кольцевая структура Collatz
Я пытаюсь создать структуру Collatz, которая спрашивает пользователя, сколько раз он хотел бы запустить ее. Затем он циклически увеличивает код каждый раз на 3 (n = n + 3). Хотя код частично работает, он продолжает повторять предыдущий процесс, который завершен, например, с вводом 5 и выполнением процесса 3 раза "Дочерний 1 = 5, 16, 8, 4, 2, 1" и "Дочерний 2 =" 8,4,2,1 "и" Ребенок 3 = 11,34,17,52,26,13 и т. Д. "
Проблема в том, что он зацикливается слишком много раз и запускает каждый дочерний элемент несколько раз. Один раз это правильно и во второй раз он запускает последовательность с "1".
Я запускаю это из Linux Debian. Для компиляции я использую "gcc -o имя_файла filename.c", а затем для выполнения я использую "./filename 5", где 5 - это число, переданное "n" для структуры Коллатца. Затем он запрашивает, сколько раз запустить цикл.
Я понимаю, что я, вероятно, далеко, но я полностью потерян и был бы очень признателен за любую помощь.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int n, j, x;
printf ("How many times would you like this to run?\n");
scanf ("%d",&j);
if (argc == 1) {
fprintf (stderr,"Usage: ./a.out <starting value>\n");
return -1;
}
printf("\nMain program's process ID: %d\n",getpid());
n = atoi(argv[1]);
for (x=1; x <= j; x++){
pid = fork();
if (pid < 0) {
fprintf(stderr, "Unable to fork child\n");
return -1;
}
else if (pid == 0) { /*child process */
printf("\nChild %d (ID: %d)\n",x,getpid());
printf("\nStart sequence at: %d\n",n);
while (n != 1) {
n = n % 2 ? 3 * n + 1 : n / 2;
printf("\n(Child %d) %d ",x,n);
}
printf("\n\nAbout to end execution (I'm process %d) .\n",getpid());
}
else { /* parent process */
wait(NULL);
n = n + 3;
}
}
return 0;
}
1 ответ
Мне кажется, что вы не завершаете дочерний процесс после его завершения, вы просто позволяете ему продолжать основной цикл родительского процесса, порождая больше процессов. Кроме того, вы запустили процесс и ожидаете его, который ничего не покупает, позволяя вашему родительскому процессу просто выполнять вычисления - вместо этого порождают все дочерние элементы и ждут, пока они завершатся, каждый в свое время. Я переработал ваш код, чтобы включить в него все вышеперечисленное и некоторые настройки стиля:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
if (argc == 1) {
fprintf(stderr,"Usage: ./a.out <starting value>\n");
return EXIT_FAILURE;
}
int j;
printf ("How many times would you like this to run?\n");
scanf ("%d", &j);
(void) fpurge(stdin);
printf("\nMain program's process ID: %d\n", getpid());
int n = atoi(argv[1]);
for (int x = 1; x <= j; x++) {
pid_t pid = fork();
if (pid == -1) {
fprintf(stderr, "Unable to fork child\n");
return EXIT_FAILURE;
} else if (pid == 0) { /* child process */
pid_t child_pid = getpid();
printf("\nChild %d (ID: %d)\n", x, child_pid);
printf("\nStart sequence at: %d\n", n);
while (n != 1) {
n = n % 2 ? 3 * n + 1 : n / 2;
printf("\n(Child %d) %d ", x, n);
}
printf("\n\nAbout to end execution (I'm process %d).\n", child_pid);
return EXIT_SUCCESS; /* child terminates */
}
else { /* parent process */
n = n + 3;
}
}
for (int x = 1; x <= j; x++) {
wait(NULL);
}
return EXIT_SUCCESS;
}
SAMPLE RUN
> ./a.out 5
How many times would you like this to run?
4
Main program's process ID: 1164
Child 1 (ID: 1165)
Start sequence at: 5
(Child 1) 16
(Child 1) 8
(Child 1) 4
(Child 1) 2
(Child 1) 1
About to end execution (I'm process 1165).
Child 3 (ID: 1167)
Start sequence at: 11
(Child 3) 34
(Child 3) 17
(Child 3) 52
(Child 3) 26
(Child 3) 13
Child 2 (ID: 1166)
(Child 3) 40
(Child 3) 20
Start sequence at: 8
(Child 3) 10
(Child 3) 5
(Child 2) 4
(Child 3) 16
(Child 2) 2
(Child 3) 8
(Child 2) 1
(Child 3) 4
(Child 3) 2
About to end execution (I'm process 1166).
(Child 3) 1
About to end execution (I'm process 1167).
Child 4 (ID: 1168)
Start sequence at: 14
(Child 4) 7
(Child 4) 22
(Child 4) 11
(Child 4) 34
(Child 4) 17
(Child 4) 52
(Child 4) 26
(Child 4) 13
(Child 4) 40
(Child 4) 20
(Child 4) 10
(Child 4) 5
(Child 4) 16
(Child 4) 8
(Child 4) 4
(Child 4) 2
(Child 4) 1
About to end execution (I'm process 1168).
>
Если результаты не по порядку вас беспокоят, рассмотрите возможность использования потоков и возврата результатов, которые будут напечатаны основным потоком, или используйте какую-либо блокировку для синхронизации вывода. Или попросите детей записать результаты во временные файлы или каналы, которые родительский итог суммирует в конце.
Последнее замечание о стиле, не возвращайте -1 из main()
и не делать exit(-1)
- хотя возвращение -1 указывает на ошибку системных подпрограмм, значение, возвращаемое main()
для операционной системы должен быть в диапазоне от 0 (успех) до 255 с 1 (сбой), являющийся общим индикатором ошибки.