Devolver un array de arrays desde c

Post Reply
pgfdz
Posts: 145
Joined: Wed Nov 03, 2010 9:16 am

Devolver un array de arrays desde c

Post by pgfdz »

Hola

Quiero devolver un array desde una función de c qu sea asi:

{{22,33},{44,55},{12,13}}

para un array normal sería:

hb_reta(3);

hb_storvni( n1, -1, 1 );
hb_storvni( n2, -1, 2 );
hb_storvni( n3, -1, 3 );

pero no sé anidarlos.

Alguna ayuda?

Gracias
Paco García
User avatar
carlos vargas
Posts: 1723
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Post by carlos vargas »

una ejemplo lo puedes ver en este codigo de harbour, la funcion directory conocida por todos:

Code: Select all | Expand


#include "hbapi.h"
#include "hbapifs.h"
#include "hbapiitm.h"

#include "directry.ch"

/* NOTE: 8.3 support should be added in a separate way, like
         as a function which converts full names to 8.3 names, since
         this issue is very much platform specific, and this is
         not the only place which may need the conversion [vszakats]. */


PHB_ITEM hb_fsDirectory( const char * pszDirSpec, const char * pszAttributes )
{
   PHB_ITEM  pDir = hb_itemArrayNew( 0 );
   char *    pszFree = NULL;
   PHB_FFIND ffind;
   HB_FATTR  ulMask;

   /* Get the passed attributes and convert them to Harbour Flags */

   ulMask = HB_FA_ARCHIVE |
            HB_FA_READONLY |
            HB_FA_DEVICE |
            HB_FA_TEMPORARY |
            HB_FA_SPARSE |
            HB_FA_REPARSE |
            HB_FA_COMPRESSED |
            HB_FA_OFFLINE |
            HB_FA_NOTINDEXED |
            HB_FA_ENCRYPTED |
            HB_FA_VOLCOMP;

   if( pszAttributes && *pszAttributes )
      ulMask |= hb_fsAttrEncode( pszAttributes );

   if( pszDirSpec && *pszDirSpec )
   {
      if( ulMask != HB_FA_LABEL )
      {
         /* CA-Cl*pper compatible behavior - add all file mask when
          * last character is directory or drive separator
          */

         HB_SIZE nLen = strlen( pszDirSpec ) - 1;
#ifdef HB_OS_HAS_DRIVE_LETTER
         if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR ||
             pszDirSpec[ nLen ] == HB_OS_DRIVE_DELIM_CHR )
#else
         if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR )
#endif
            pszDirSpec = pszFree =
                           hb_xstrcpy( NULL, pszDirSpec, HB_OS_ALLFILE_MASK, NULL );
      }
   }
   else
      pszDirSpec = HB_OS_ALLFILE_MASK;

   /* Get the file list */

   if( ( ffind = hb_fsFindFirst( pszDirSpec, ulMask ) ) != NULL )
   {
      PHB_ITEM pSubarray = hb_itemNew( NULL );

      do
      {
         char buffer[ 32 ];

         hb_arrayNew    ( pSubarray, F_LEN );
         hb_arraySetC   ( pSubarray, F_NAME, ffind->szName );
         hb_arraySetNInt( pSubarray, F_SIZE, ffind->size );
         hb_arraySetDL  ( pSubarray, F_DATE, ffind->lDate );
         hb_arraySetC   ( pSubarray, F_TIME, ffind->szTime );
         hb_arraySetC   ( pSubarray, F_ATTR, hb_fsAttrDecode( ffind->attr, buffer ) );

         /* Don't exit when array limit is reached */
         hb_arrayAddForward( pDir, pSubarray );
      }
      while( hb_fsFindNext( ffind ) );

      hb_itemRelease( pSubarray );

      hb_fsFindClose( ffind );
   }

   if( pszFree )
      hb_xfree( pszFree );

   return pDir;
}

HB_FUNC( DIRECTORY )
{
   hb_itemReturnRelease( hb_fsDirectory( hb_parc( 1 ), hb_parc( 2 ) ) );
}  
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
pgfdz
Posts: 145
Joined: Wed Nov 03, 2010 9:16 am

Re: Devolver un array de arrays desde c

Post by pgfdz »

Muchas gracias Carlos.
;)
Paco García
User avatar
carlos vargas
Posts: 1723
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Post by carlos vargas »

un ejemplo, construido en base al post anterior

Code: Select all | Expand


function main()
  local a, x
 
  a:=MyTEST()
  ?"Tamaño:",len(a)
 
  ?"Inicio"
 
  IF hb_isarray(a)
    for x:=1 to len(a)
      ?a[x,1],"->",a[x,2],"->",a[x,3]
    next
    ?"------------------"
    aeval( a, {|i| qout( i[1] ), qqout( "->" ), qqout( i[2] ) } )
  ENDIF
 
  ?"Final"
 
return


#pragma BEGINDUM
#include "hbapi.h"
#include "hbapifs.h"
#include "hbapiitm.h"

#define N_SIZE    3
#define N_COL1    1
#define N_COL2    2
#define N_COL3    3

#define TRUE      0
#define FALSE     1

HB_FUNC( MYTEST )
{
  PHB_ITEM pArray    = hb_itemArrayNew( 0 );
  PHB_ITEM pSubArray = hb_itemNew( NULL );
  int iItems = 0;
  HB_BOOL bItem = FALSE;
 
  do
  {
    ++iItems;
    bItem = !bItem;
   
    hb_arrayNew( pSubArray, N_SIZE );
   
    hb_arraySetNInt( pSubArray, N_COL1, iItems    ); /*item numerico entero*/
    hb_arraySetC   ( pSubArray, N_COL2, "Items #" ); /*item caracter*/
    hb_arraySetL   ( pSubArray, N_COL3, bItem     ); /*item logico*/
   
    /*hb_arraySetNL(); item numerico long*/
    /*hb_arraySetND(); item numerico double*/
    /*hb_arraySetDS(); item date string*/
    /*hb_arraySetDL(); item date numeric long*/
    /*hb_arraySetCL(); item date character with size define*/
   
    hb_arrayAddForward( pArray, pSubArray );
  }
  while( iItems < 5);
 
  hb_itemRelease( pSubArray );
 
  hb_itemReturnRelease( pArray );
}

#pragma ENDDUMP
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
antolin
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Post by antolin »

Carlos: ¿Esto sólo es para Harbour, o también funciona con xHarbour?
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
User avatar
carlos vargas
Posts: 1723
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Post by carlos vargas »

en teoria no habria problemas, ademas es solo de compilar y probar el ejemplo :-), la función directory es similar en código en ambos compiladores

UPDATE: Comprobado con xharbour, funciono sin problemas.
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
antolin
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Post by antolin »

Hola foreros.

Este hilo me ha venido de maravillas, pues tenía necesidad de una función similar a Directory modificada. El inconveneinte es que mi xHarbour no trae ni la mitad de estas funciones, aunque algunas parecidas. Así que para a prender a manipular esta faceta de (x)Harbour que desconocía por completo, lo primero que he hecho ha sido traducir la función Directory aquí expuesta, para adptarla a mi xHarbour.Tras muchos sudores este es el resultado:

Code: Select all | Expand

HB_FUNC( XDIRECTORY )  // xDirectory( LPSTR cDir, LPSTR cAttr )
   {
   LPSTR pszDirSpec = hb_parc( 1 ) ;
   LPSTR pszAttributes = hb_parc( 2 ) ;

   PHB_ITEM  pDir   = hb_itemArrayNew( 0 ) ;
   PHB_FFIND ffind  ;
   USHORT    ulMask ;

   ulMask = HB_FA_ARCHIVE    |
            HB_FA_READONLY   |
            HB_FA_DEVICE     |
            HB_FA_TEMPORARY  |
            HB_FA_SPARSE     |
            HB_FA_REPARSE    |
            HB_FA_COMPRESSED |
            HB_FA_OFFLINE    |
            HB_FA_NOTINDEXED |
            HB_FA_ENCRYPTED  |
            HB_FA_VOLCOMP ;

   if ( pszAttributes && *pszAttributes ) ulMask |= hb_fsAttrEncode( pszAttributes ) ;

   if ( pszDirSpec && *pszDirSpec )
      {
      if ( ( ffind = hb_fsFindFirst( pszDirSpec, ulMask ) ) != NULL )
     {
     PHB_ITEM pSubarray = hb_itemNew( NULL ) ;

     do {
        char buffer[ 32 ];

        hb_arrayNew( pSubarray, ( ULONG ) 5 ) ;

        hb_itemArrayPut( pSubarray, 1, hb_itemPutC( NULL, ( const char *  ) ffind->szName ) ) ;
        hb_itemArrayPut( pSubarray, 2, hb_itemPutNInt( NULL, ( HB_LONG ) ffind->size ) ) ;
        hb_itemArrayPut( pSubarray, 3, hb_itemPutDL( NULL, ( LONG ) ffind->lDate ) ) ;
        hb_itemArrayPut( pSubarray, 4, hb_itemPutC( NULL, ( const char *  ) ffind->szTime ) ) ;
        hb_itemArrayPut( pSubarray, 5, hb_itemPutC( NULL, ( const char *  ) hb_fsAttrDecode( ffind->attr, buffer ) ) ) ;

        hb_arrayAddForward( pDir, pSubarray );
        }
     while( hb_fsFindNext( ffind ) ) ;
     hb_itemRelease( pSubarray ) ;
     }

      hb_fsFindClose( ffind ) ;
      }
   hb_itemReturnRelease( pDir ) ;
   }

Y funciona perfectamente (aunque estoy seguro que se puede perfeccionar), así que con este punto de partida podré hacer lo que necesito.

El Único inconveniente es que no he podido/sabido traducir el trozo:

Code: Select all | Expand

if( ulMask != HB_FA_LABEL )
   {
   /* CA-Cl*pper compatible behavior - add all file mask when
   * last character is directory or drive separator
   */

   HB_SIZE nLen = strlen( pszDirSpec ) - 1;

   #ifdef HB_OS_HAS_DRIVE_LETTER
       if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR ||
           pszDirSpec[ nLen ] == HB_OS_DRIVE_DELIM_CHR )
   #else
       if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR )
   #endif

   pszDirSpec = pszFree = hb_xstrcpy( NULL, pszDirSpec, HB_OS_ALLFILE_MASK, NULL ) ;
   }

pues en las cabeceras (includes) de mi xHarbour no existen las constantes HB_OS_PATH_DELIM_CHR, HB_OS_DRIVE_DELIM_CHR ni HB_OS_ALLFILE_MASK. Y aunque me imagino algo, con mis limitaciones en C++ no he sido capaz de implementarlo, aunque en realidad pasando atributos y nombres de directorios normales no lo he echado en falta.

Para seguir probando, he implementando una función que me dice si un directorio tiene subdirectorios o no, que seguramente será más rápida que empleando el tradicional Directory():

Code: Select all | Expand

#define HB_FA_TODOS   65535

HB_FUNC( HASITSUBDIRS )  // HasItSubDirs( LPSTR cSubdir )
   {
   LPSTR cPath = hb_parc( 1 ) ;

   char  cDir[MAX_PATH] ;

   PHB_FFIND ffind  ;

   BOOL lDirs = FALSE ;

   if ( cPath && *cPath )
      {
      cDir[0] = 0 ;
      strcat( cDir, cPath ) ;
      strcat( cDir, "\\*.*" ) ;

      if ( ( ffind = hb_fsFindFirst( cDir, HB_FA_TODOS ) ) != NULL )
     {
     hb_fsFindNext( ffind ) ;

     while( hb_fsFindNext( ffind ) && !lDirs ) lDirs = ( ( ffind->attr & 16 ) == 16 ) ;
     }
      hb_fsFindClose( ffind ) ;
      }
   hb_retl( lDirs ) ;
   }

Otra posible modificación sería hacer que xDirectory devuelva más datos. Como por ejemplo el el nombre de Windows de cada directorio, o la longitud del nombre, etc.

Muy interesante...

Un saludo.
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
xmanuel
Posts: 773
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla
Been thanked: 5 times
Contact:

Re: Devolver un array de arrays desde c

Post by xmanuel »

Creo que le has cogido la idea a esto... me alegro!!!

HB_OS_PATH_DELIM_CHR es una macro que sera sustituida en tiempo de compilación en C por el delimitador de directorios de sistema operativo en el que estés trabajando, como t´lo harás en windows es "\" en linux sería "/".
HB_OS_DRIVE_DELIM_CHR en windows es ":"
HB_OS_ALLFILE_MASK es "*.*" para windows y linux :-)

Este codigo

Code: Select all | Expand


    #ifdef HB_OS_HAS_DRIVE_LETTER
       if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR ||
           pszDirSpec[ nLen ] == HB_OS_DRIVE_DELIM_CHR )
   #else
       if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR )
   #endif

   pszDirSpec = pszFree = hb_xstrcpy( NULL, pszDirSpec, HB_OS_ALLFILE_MASK, NULL ) ;
 


lo puedes sutituir por este otro en windows:

Code: Select all | Expand


   #ifdef HB_OS_HAS_DRIVE_LETTER
       if( pszDirSpec[ nLen ] == '\\' || pszDirSpec[ nLen ] == ':' )
   #else
       if( pszDirSpec[ nLen ] == '\\' )
   #endif

   pszDirSpec = pszFree = hb_xstrcpy( NULL, pszDirSpec, "*.*", NULL ) ;
 


Es muy importante usar las comillas tal como te lo digo, en C ' es para caracteres y " para cadenas

Espero que te valga y si tienes dudas lánzalas al foro que seguro que te ayudaremos ;-)

Salu2
Manu Exposito
______________________________________________________________________________
Sevilla - Andalucía
antolin
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Post by antolin »

Muchas Gracias Manuel. Lo que más me gusta de programar es investigar y probar cosas nuevas. Siempre es un alivio encontrar gente dispuesta a echar una mano.
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
antolin
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Post by antolin »

Bueno eso de que funciona perfectamente es un decir, resulta que ponga los atributos que ponga, siempre me devuelve la misma matriz. Como si ulMask no sirviera de nada...

He tenido que añadir:

Code: Select all | Expand

if ( ( ffind->attr & ulMask ) == ffind->attr  )  hb_arrayAddForward( pDir, pSubarray );

Entonces ¿Para qué sirve ulMask? O ¿me estoy equivocando en algo?

Un saludo.
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
Post Reply