【问题标题】:Incomplete C recursive function. I do not know how to implement correctly不完整的 C 递归函数。我不知道如何正确实施
【发布时间】:2017-04-26 12:29:44
【问题描述】:

我需要在C中实现一个可以模拟pstree的递归函数,也就是把下面的数字想象成一个进程:

1 (father)
   2 (child of 1)
   3 (child of 1)
     4 (son of 3)
       5 (child of 4)
     6 (child of 3)

等等……

void imprime_Pstree(int i, int ntabs)
{
    int k = 0, j = 0, quantProc = 0;
    int procAtual;

    // Prints the number of tabs
    for(k = 0; k < ntabs; k++)
        printf("\t");

    quantProc = preenche_vetor(i);

    // Prints the process name
    imprimeNomeProcesso(i);


    for(j = 0; j < quantProc; j++) {

        imprime_Pstree(processos[j], ntabs+1);
    }

}

但它只打印父级(称为递归函数)和相同的子级,没有其他子级。 我知道在前一个孩子的父级中丢失了对递归函数的另一个调用,但是如何呢?


完整代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>

int processos[1000];

void limpa_vetor() {
    int i;
    for(i = 0; i < 1000; i++)
        processos[i] = 0;
}

int preenche_vetor(int proc) {
    char path[50];
    char string[100];
    int i, j = 0, cont = 0;
    char temp;
    FILE *arq;

    limpa_vetor();

    sprintf(path, "/proc/%d/task/%d/children", proc, proc);
    arq = fopen(path, "r");

    if (arq != NULL)
    {
        limpa_vetor();

        fscanf(arq, "%s", string);
        while(strcmp(string, "") != 0)
        {
            if(feof(arq)) break;
            processos[j] = atoi(string);
            cont++;

            fscanf(arq, "%c", &temp);
            fscanf(arq, "%s", string);
            j++;
        }
    }
    return cont;
}

void imprimeNomeProcesso(int proc) {
    char path[50];
    char string[100];
    int i, j = 0;
    char temp;
    FILE *arq;

    sprintf(path, "/proc/%d/stat", proc);
    arq = fopen(path, "r");

    if (arq != NULL)
    {
        fscanf(arq, "%s", string);
        while(strcmp(string, "") != 0)
        {
            if(feof(arq)) break;

            if(j == 1)
            {
                printf("%s ", string);
                break;
            }

            fscanf(arq, "%c", &temp);
            fscanf(arq, "%s", string);
            j++;
        }
        printf("\n");
    }

}

void imprime_Pstree(int i, int ntabs)
{
    int k = 0, j = 0, quantProc = 0;
    int procAtual;

    // Imprime a quantidade de tabs
    for(k = 0; k < ntabs; k++)
        printf("\t");

    quantProc = preenche_vetor(i);

    // Imprime o nome do processo
    imprimeNomeProcesso(i);


    for(j = 0; j < quantProc; j++) {

        imprime_Pstree(processos[j], ntabs+1);
    }

}

int main()
{
    imprime_Pstree(1, 0);

    return 0;
}

【问题讨论】:

  • 看来processos 是一个全局变量,其中包含i 的所有子项的列表。这在递归函数中不起作用。递归调用将覆盖数组。您必须将其设为本地 var 并将其传递给必须分配值的函数

标签: c recursion


【解决方案1】:

processos 是一个全局变量,包含 i 的所有子项的列表。这在递归函数中不起作用。递归调用将覆盖数组。您必须将其设为本地 var 并将其传递给必须分配值的函数:

void imprime_Pstree(int i, int ntabs)
{
    int k = 0, j = 0, quantProc = 0;
    int procAtual;
    int processos[1000];    // <-- have a local array

    // Imprime a quantidade de tabs
    for(k = 0; k < ntabs; k++)
        printf("\t");

    // pass that array to preenche_vetor()
    quantProc = preenche_vetor(i, processos );

   // Imprime o nome do processo
   imprimeNomeProcesso(i);


   for(j = 0; j < quantProc; j++) {

        imprime_Pstree(processos[j], ntabs+1);
   }   

}

当然,您还必须更改 preenche_vetor() 的签名,并且必须在那里进行初始化()。

编辑 正如@Aconcagua ha 建议的那样,最好先确定孩子的数量,然后申报并填写 VLA

【讨论】:

  • 固定大小的数组在这种情况下给我一种不好的感觉——要么它们太大,要么它们不能满足需要。我个人更喜欢获取子进程数量的getter,并使用它来初始化VLA ...
  • @Aconcagua 是的,你会是一个进步。我只是想尽可能少地改变以指出实际问题的核心
【解决方案2】:
quantProc = preenche_vetor(i);

嗯,现在我们有许多进程。

for(j = 0; j < quantProc; j++)
{
    imprime_Pstree(processos[j], ntabs+1);
}

两种可能的情况:

  1. processos 包含系统中所有当前活动进程的列表。然后,您将迭代这些进程,就像它们在数组中一样,即。 e.如果任何进程至少有一个子进程,则系统中的第一个进程(linux:将是 id 为 0 的根进程,通常永远不会死亡)将始终作为当前进程的子进程打印。您需要一个单独的列表,其中包含您可以迭代的子进程 ID!

  2. processospreenche_vetor 函数填充,并带有给定进程 ID 的子进程。然后对imprime_Pstree 的任何递归调用都会覆盖被调用者的子进程列表(因为再次调用preenche_vetor)。解决方案:您需要为每个递归调用提供一个单独的数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-08
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    相关资源
    最近更新 更多