Devolver un array de arrays desde c

Devolver un array de arrays desde c

Postby pgfdz » Wed Aug 27, 2014 10:22 am

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
pgfdz
 
Posts: 145
Joined: Wed Nov 03, 2010 9:16 am

Re: Devolver un array de arrays desde c

Postby carlos vargas » Wed Aug 27, 2014 2:33 pm

una ejemplo lo puedes ver en este codigo de harbour, la funcion directory conocida por todos:
Code: Select all  Expand view

#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)
User avatar
carlos vargas
 
Posts: 1683
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Postby pgfdz » Fri Aug 29, 2014 3:35 pm

Muchas gracias Carlos.
;)
Paco García
pgfdz
 
Posts: 145
Joined: Wed Nov 03, 2010 9:16 am

Re: Devolver un array de arrays desde c

Postby carlos vargas » Fri Aug 29, 2014 5:36 pm

un ejemplo, construido en base al post anterior
Code: Select all  Expand view

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)
User avatar
carlos vargas
 
Posts: 1683
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Postby antolin » Sat Sep 06, 2014 5:56 pm

Carlos: ¿Esto sólo es para Harbour, o también funciona con xHarbour?
Peaaaaaso de foro...
antolin
 
Posts: 491
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Postby carlos vargas » Sat Sep 06, 2014 6:39 pm

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)
User avatar
carlos vargas
 
Posts: 1683
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Devolver un array de arrays desde c

Postby antolin » Fri Oct 24, 2014 4:38 pm

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 view
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 view
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 view
#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...
antolin
 
Posts: 491
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Postby xmanuel » Fri Oct 24, 2014 7:53 pm

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 view

    #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 view

   #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
xmanuel
 
Posts: 756
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Postby antolin » Fri Oct 24, 2014 9:35 pm

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...
antolin
 
Posts: 491
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Devolver un array de arrays desde c

Postby antolin » Mon Oct 27, 2014 5:13 pm

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 view
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...
antolin
 
Posts: 491
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 15 guests