2017-04-26 70 views
0

我需要实现在C递归函数,可以模拟一个pstree,就是想象中的数字下面的过程:不完整的C递归函数。我不知道如何实现正确

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; 
} 
+0

似乎'processos'是一个全局变量,它包含'i'的所有子元素的列表。这在递归函数中不起作用。递归调用将覆盖数组。您必须将其设置为本地变量并将其传递给需要分配值的函数 –

回答

0

processos是一个全局变量,它包含我的所有孩子的名单。这在递归函数中不起作用。递归调用将覆盖数组。你必须让一个局部变量并把它传递到具有分配的值的函数:

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公顷建议,它甚至会更好,首先要确定孩子的数量,然后申报,并填写一VLA

+0

在这种情况下,固定大小的数组给我带来不好的感觉 - 要么他们太大,要么他们不能满足需求。我个人更喜欢吸气剂的儿童进程的数量,并使用这一个来初始化VLA ... – Aconcagua

+0

@Aconcagua是的,你是一个改进。我只是想尽可能少地指出实际问题的核心 –

0
quantProc = preenche_vetor(i); 

好了,现在我们有一些进程。

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

两种可能的情况:

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

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