Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

problemas con funcion recursiva

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: problemas con funcion recursiva Responder citando

Hola foro tengo la siguiente funcion recursiva, pero no me sale de ella a pesar de que se cumpla la condicion por la cual pregunto para salir
Código:
void list (String Dir, TIdFTP * ftp, TMemo *m){

   static String mainDir = Dir;

   ftp->ChangeDir(Dir);    

   ftp->List("",true);

   int count = ftp->DirectoryListing->Count;

   if (count == 0) {
      String dir = ftp->RetrieveCurrentDir();
      ftp->ChangeDirUp();
      ftp->RemoveDir(dir);
      //main Dir = Dir = "/x
      String a =ftp->RetrieveCurrentDir();
      if (ftp->RetrieveCurrentDir() == mainDir) {         
         return ;   
      }      
      list (ftp->RetrieveCurrentDir(), ftp, m);
   }else{
      for (int i = 0; i <count>DirectoryListing->Items[i]->ItemType == ditDirectory) {
            list (ftp->DirectoryListing->Items[i]->FileName, ftp, m);   
         }         
         if (ftp->DirectoryListing->Items[i]->ItemType == ditFile) {
            ftp->Delete(ftp->DirectoryListing->Items[i]->FileName);
            list (ftp->RetrieveCurrentDir(), ftp, m);    
         }
      }
    }
}


Espero me puedan ayudar . Slaudos y gracias
_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

En un principio tiene buena pinta.
De todas formas, ¿puedes poner el codigo de nuevo con la opcion de Deshabilitar HTML, ya que el bucle for de abajo no se ve bien.

A simple vista se me ocurre si tienes en cuenta, si es un servidor FTP montado en WINDOWS, los directorios . y ..
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Revisa el segmento del la funcion donde se valida la salida
¿no se estara colando un condenado simbolo raro en la igualdad?
Por lo tanto nunca llega a ser igual

Código:

 String a =ftp->RetrieveCurrentDir();
   // ya probaste "ver" que es lo que sucede?
   ShowMessage(ftp->RetrieveCurrentDir()+" "+mainDir);

      if (ftp->RetrieveCurrentDir() == mainDir) {         
         return ;   

 

_________________
Ing. Gabriel Góngora Navarrete
TouchSoftwares Inc

http://www.touchsoftwares.com
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor MSN Messenger
Mensaje    Asunto: Responder citando

Muachas gracias por responder...
Aca dejo la funcion con HTML deshabilitado y antes habia un pequeño problema al cumplirse la condicion que ya esta arreglado y he comprobado en forma debug F8 que todo esta bien la condicion se cumple pero aunque se pase por el return no se sale de ella, sino que indistintamente se va para cualquier otro lado de la funcion hasta que se produce una excepcion...

Código:
void RemoveFTPDir (String Dir, TIdFTP * ftp, TMemo *m){

   static String mainDir = Dir;

   ftp->ChangeDir(Dir);

   ftp->List("",true);

   int count = ftp->DirectoryListing->Count;

   for (int i = 0; i < count; i++) {
      //carpeta
      if (ftp->DirectoryListing->Items[i]->ItemType == ditDirectory) {
         RemoveFTPDir (ftp->DirectoryListing->Items[i]->FileName, ftp, m);
      }
      if (ftp->DirectoryListing->Items[i]->ItemType == ditFile) {
         ftp->Delete(ftp->DirectoryListing->Items[i]->FileName);
         RemoveFTPDir (ftp->RetrieveCurrentDir(), ftp, m);
      }
   }

   if (count == 0) {
      String dir = ftp->RetrieveCurrentDir();
      ftp->ChangeDirUp();
      ftp->RemoveDir(dir);
      if (dir == mainDir) return ;
      RemoveFTPDir (ftp->RetrieveCurrentDir(), ftp, m);
   }
}

_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

no es por saber, pero... ¿no sobra esta linea?
Código:
      if (ftp->DirectoryListing->Items[i]->ItemType == ditFile) {
         ftp->Delete(ftp->DirectoryListing->Items[i]->FileName);
         RemoveFTPDir (ftp->RetrieveCurrentDir(), ftp, m);  <-------- ESTA

Veamos. Yo entiendo que entras en una carpeta del ftp. Si encuentra otra carpeta, llama de nuevo a la función remove. Si en esa carpeta ya no hay mas carpetas y solo archivos, borra el primero, i=0, y ¿vuelve a llamar a remove? creo que debería borrar todos los archivos y return.

Puedo estar equivocado, pero creo que eliminando esa linea no tendrás el problema

Saludos, Bosoft

PD: después de revisar mejor el código, creo:
Sobra lo del count==0
y después de la llamada al remove dentro del primer if, falta borrar la carpeta
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Hola bosoft

Cita:
Veamos. Yo entiendo que entras en una carpeta del ftp. Si encuentra otra carpeta, llama de nuevo a la función remove. Si en esa carpeta ya no hay mas carpetas y solo archivos, borra el primero, i=0, y ¿vuelve a llamar a remove? creo que debería borrar todos los archivos y return.


Imaginemos el siguiente caso:
carpeta1->fichero1
fichero2
carpeta2
Si entramos en carpeta1 y eliminamos fichero1 y luego hacemos un return como recomiendas veras que se quedan fichero2 y carpeta2 sin eliminar, por eso se vuelve a hacer una llamada ala función.

No entiendo porque me dices esto.

Cita:
PD: después de revisar mejor el código, creo:
Sobra lo del count==0
y después de la llamada al remove dentro del primer if, falta borrar la carpeta

_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

me parece que no me has entendido.
Dentro del for hay dos ifs. Según veo, ya que no he usado jamás esas funciones, el count controla cuantos elementos hay en la carpeta, ya sean directorios o archivos.
veamos tu ejemplo
carpeta1->fichero1
fichero2
carpeta2
entras en remove,
pilla el primer elemento, es directorio (carpeta1), llama a remove. Dentro del segundo remove, pilla primer elemento, es fichero (fichero1), lo borra y return (no hay mas elementos)
borra el dir (carpeta1)
pilla el segundo, es archivo (fichero2), lo borra
pilla el tercero, es carpeta (carpeta2), llama a remove ¿¿¿ ficheros??? return
borra el dir (carpeta2)

¿es eso lo que querías? el código quedaría mas o menos así. Recuerda que no se las sentencias necesarias.


Código:
void RemoveFTPDir (String Dir, TIdFTP * ftp, TMemo *m){

   static String mainDir = Dir;

   ftp->ChangeDir(Dir);

   ftp->List("",true);

   int count = ftp->DirectoryListing->Count;

   for (int i = 0; i <count>DirectoryListing->Items[i]->ItemType == ditDirectory) {
         RemoveFTPDir (ftp->DirectoryListing->Items[i]->FileName, ftp, m);
         // delete items[i]==dir;
         }
      if (ftp->DirectoryListing->Items[i]->ItemType == ditFile) {
         ftp->Delete(ftp->DirectoryListing->Items[i]->FileName);
         // delete items[i]==file;
         }
}


Saludos, Bosoft.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

bosoft recuerda que cada vez que llamo a la funcion remove entra en el directorio que encontro lo que hace que la lista de elementos varie y que hallan x cnatidad de elementos
ejemplo
carpeta0
carpeta1->fichero1
fichero2
carpeta2
entre en carpeta1 y count vale 1 si eleimino el fichero debo luego salir a carpeta 0 luego listar count vale 3 entiendes siempre varia porque debo entrar en tantas carpetas hallan y luego salir y etc. Recuerda que solo se puede eliminar una carpeta si no tiene contenido dentro.
_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Si, si, lo tengo todo en cuenta, menos el count. Es verdad, al eliminar un dir, el count descuenta y se lia parda para eso está asignado a un int que es el que usamos para el for.
Tengo una duda ¿el count contiene solo los elementos dentro de la carpeta? si tiene también los que están dentro de las subcarpetas, no he dicho nada y no se por donde pillarlo
En cambio si solo cuenta los de la carpeta actual el código que te he pasado debe funcionar
Como he visto que no ha salido bien, te lo vuelvo a poner con html desconectado
Código:
void RemoveFTPDir (String Dir, TIdFTP * ftp, TMemo *m){

   static String mainDir = Dir;

   ftp->ChangeDir(Dir);

   ftp->List("",true);

   int count = ftp->DirectoryListing->Count;

   for (int i = 0; i < count; i++) {
      //carpeta
      if (ftp->DirectoryListing->Items[i]->ItemType == ditDirectory) {
         RemoveFTPDir (ftp->DirectoryListing->Items[i]->FileName, ftp, m);
         // delete(items[i]) ==dir;
      }
      if (ftp->DirectoryListing->Items[i]->ItemType == ditFile) {
         ftp->Delete(ftp->DirectoryListing->Items[i]->FileName);
         // delete(items[i])==file;
      }
   }
}


Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

bosoft
Cita:
Tengo una duda ¿el count contiene solo los elementos dentro de la carpeta? si tiene también los que están dentro de las subcarpetas, no he dicho nada y no se por donde pillarlo

El count solo tiene el numero de elementos que están en la carpeta actual.

Ahora, si analizo tu codigo me encuentro con un problema
es el siguiente
carpeta1->fichero
carpeta2
entre a carpeta1
llame a la funcion
count = 1
elimino fichero
......y salgo de la funcion
entonces se quedan carpeta1 sin ficheros y carpeta2
es decir no cumpli mi objetivo.
_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

debe haber algún "fallito" en el código
veamos: llamas por primera vez a remove
ftp->DirectoryListing->Count =3:
carpeta1->fichero
fichero2
carpeta2
i=0;
carpeta1
en el for entra a otro remove, borra archivo y sale
borra dir,
i=1
borra fichero2
i=2
entra en carpeta2 y sale
borra carpeta2
y fin del for

Debe funcionar perfectamente
En cuanto a tu post, debes seguir ejecutando hasta que vuelvas al sitio donde se llamó el remove por primera vez, puesto que si haces un break, en el ejemplo, como la función remove ha sido llamada desde el interior de remove, la primera remove no ha terminado su ejecución

Saludos, Bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Parece que no nos entendemos...
Recurda que cada vez que se llama a la funcion ocurre lo siguiente:
1-Se va al direcorio Dir
2-Se lista el directorio
3-Se almacena la cantidad de items encontrados
4-Se recorren los items etc

Teniendo esto si el item es carpeta se llama nuevamente a la funcion y nuevamente los pasos anteriores por lo que cambia de directorio , se lista el nuevo directorio y se crea un count con la cantidad de items, es decir el for anterior ya no existe y no hay forma de dar marcha atras si no se llama a la funcion cuando se elimina un fichero o cuando los items = 0;
_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

ifrit escribió:
Parece que no nos entendemos...
Recurda que cada vez que se llama a la funcion ocurre lo siguiente:
1-Se va al direcorio Dir
2-Se lista el directorio
3-Se almacena la cantidad de items encontrados
4-Se recorren los items etc

Teniendo esto si el item es carpeta se llama nuevamente a la funcion y nuevamente los pasos anteriores por lo que cambia de directorio , se lista el nuevo directorio y se crea un count con la cantidad de items, es decir el for anterior ya no existe y no hay forma de dar marcha atras si no se llama a la funcion cuando se elimina un fichero o cuando los items = 0;


Correcto excepto
Cita:
es decir el for anterior ya no existe y no hay forma de dar marcha atras si no se llama a la función cuando se elimina un fichero o cuando los items = 0

El for anterior SI existe, aunque este latente. Siempre retrocederá una función al acabar la actual y terminará lo que estaba haciendo. Pero si la vuelves a llamar puedes anidar demasiadas funciones y ahí tienes el problema

Prueba el código y me dices

Saludos, bosoft
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Hola quiero agradecer a bosoft por la ayuda, no sabia que las funciones recursivas almacenaran el ciclo anterior y el suguiente, etc. Bueno como no pude implementar la funcion para eliminar una carpeta lo que hice fue una para recorrer una carpeta, que hasta el momento me ha funcionado muy bien y luego elimino de otra forma...para mi ver algo rustico pero como necesitaba tambien recorrer un ftp ya esta todo listo. Aca dejo lo que hago, por si a alguien le interesa.


funcion listar carpeta y subcarpetas en ftp
Código:
void Listar2(String Dir, TIdFTP * ftp, TMemo * m, TStringList * sl){
   
   ftp->Noop();//send keep alive to ftp
   
   static String mainDir = Dir;
   ftp->ChangeDir(Dir);
   ftp->List("", true);

   int countItem = ftp->DirectoryListing->Count;

   if (countItem == 0){
      if (ftp->RetrieveCurrentDir() == mainDir){
         return;
      }
      else {
         ftp->ChangeDirUp();
         ftp->List("", true);
         //Listar2(ftp->RetrieveCurrentDir(), ftp, m, sl);
      }
   }

   for (int i = 0;i <countItem>RetrieveCurrentDir() + "/" + ftp->DirectoryListing->Items[i]->FileName;

      if (ftp->DirectoryListing->Items[i]->ItemType == ditDirectory){
         //carpeta
         if (sl->IndexOf(a + "/") == -1){
            sl->Add(a + "/");
            Listar2(a, ftp, m, sl);
         }
      }
      else if (ftp->DirectoryListing->Items[i]->ItemType == ditFile){
         //fichero
         if (sl->IndexOf(a) == -1){
            sl->Add(a);
         }
      }
      //ultimo item
      if (i + 1 == countItem){
         if (ftp->RetrieveCurrentDir() == mainDir){
            return;
         }
         else {
            ftp->ChangeDirUp();
            ftp->List("", true);
            //Listar2(ftp->RetrieveCurrentDir(), ftp, m, sl);
         }
      }

   } //fin for

}
]

y la utilizo de la siguiente forma para eliminar la carpeta deseada.

Código:
TStringList * sl = new TStringList();
   Listar2("/x", IdFTP1, Memo1, sl);



   //borrar ficheros
   for (int i = sl->Count-1; i >= 0; i--) {
      if (sl->Strings[i][sl->Strings[i].Length()] != '/'){
         IdFTP1->Delete(sl->Strings[i]);
         sl->Delete(i);
      }
   }

   //borrar dir
   for (int i = sl->Count-1; i >= 0; i--) {
      IdFTP1->RemoveDir(sl->Strings[i]);
   }

    //borrar carpeta
   IdFTP1->ChangeDir("/");
   IdFTP1->RemoveDir("/x");


   delete sl;

_________________
Todos somos ignorantes, lo que no todos ignoramos lo mismo...
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.