Autor Tema: Generador de cabeceras .h automático  (Leído 4376 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Generador de cabeceras .h automático
« en: 24 de Marzo de 2015, 13:49:12 »
En este hilo voy a explicar paso a paso como hacer un sencillo generador de cabeceras .h a partir del código .c

El programa será sencillo a propósito, para que sirva a la vez como aprendizaje de Python


Para comenzar, un pequeño programa que devuelve el listado de todos los archivos del directorio actual:

Código: [Seleccionar]
#-*- coding: utf8 -*-
# Esto es un comentario. La línea anterior indica la codificación UTF8 de este archivo

# Carga la librería de interface con el Sistema Operativo (OS)
import os

# Imprime un listado de todos los archivos del directorio actual ('.')
for filename in os.listdir('.'):
   print(filename)




Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #1 en: 24 de Marzo de 2015, 15:42:18 »
Ahora un listado de todos los archivos de código .c y .cpp:

Código: Python
  1. #-*- coding: utf8 -*-
  2. # Esto es un comentario. La línea anterior indica la codificación UTF8 de este archivo
  3.  
  4. # Carga la librería de interface con el Sistema Operativo (OS)
  5. import os
  6.  
  7. # Imprime un listado de todos los archivos del directorio actual ('.')
  8. for filename in os.listdir('.'):
  9.    ext = filename.split('.')[-1]                   # Divide el nombre por el caracter '.' y toma el último
  10.    if ext.lower() == 'c' or ext.lower() == 'cpp':  # Si la extension en minúsculas es 'c' o 'cpp'
  11.       print(filename)                              #   imprime el nombre en pantalla

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #2 en: 24 de Marzo de 2015, 15:52:48 »
Una función que me devuelve una lista con todos los archivos del directorio actual con extensión 'c' o 'cpp'

Código: Python
  1. #-*- coding: utf8 -*-
  2. # Esto es un comentario. La línea anterior indica la codificación UTF8 de este archivo
  3.  
  4. # Carga la librería de interface con el Sistema Operativo (OS)
  5. import os
  6.  
  7. def cfiles(path):
  8.    """Devuelve una lista con todos los archivos de código c, del directorio  'path' """
  9.    cfiles_list = []
  10.    for filename in os.listdir('.'):
  11.       ext = filename.split('.')[-1]                   # Divide el nombre por el caracter '.' y toma el último
  12.       if ext.lower() == 'c' or ext.lower() == 'cpp':  # Si la extension en minúsculas es 'c' o 'cpp'
  13.          cfiles_list.append(filename)
  14.    return cfiles_list
  15.  
  16. if __name__ == "__main__":
  17.    for cfilename in cfiles('.'):
  18.       print(cfilename)

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #3 en: 24 de Marzo de 2015, 15:58:30 »
Ahora un poco de magia de Python. Voy a resumir la función con la capacidad de Python para hacer 'List Comprehensions'

Código: Python
  1. #-*- coding: utf8 -*-
  2. import os                        # Interface con el Sistema Operativo
  3.  
  4. def cfiles(path):
  5.    """Devuelve una lista con todos los archivos de código c, del directorio  'path' """
  6.    return [cname for cname in os.listdir(path) if cname.split('.')[-1].lower() in ('c', 'cpp')]
  7.  
  8.  
  9. if __name__ == "__main__":
  10.    for cfilename in cfiles('.'):
  11.       print(cfilename)

Creo que me va a resultar difícil explicar todo esto paso a paso.
Los que estéis interesados en aprender Python desde cero os recomiendo que comencéis por libros sencillos:

    http://www.todopic.com.ar/foros/index.php?topic=44276.msg366751

Saludos.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #4 en: 24 de Marzo de 2015, 16:41:41 »
Este programa ya hace algo útil.
El programa comprueba si existe el archivo de cabecera asociado a un archivo *.c o *.cpp
En caso de que no exista, creará un nuevo archivo de cabecera con un contenido básico.

Código: Python
  1. #-*- coding: utf8 -*-
  2. import os                     # Interface con el Sistema Operativo
  3. from string import Template   # Plantillas
  4.  
  5.  
  6. header_template = Template("""\
  7. // Automatic header for: $CFILE
  8. #ifndef $DEFINE
  9. #define $DEFINE
  10.  
  11. #endif
  12. """)
  13.  
  14.  
  15. def list_cfiles(path):
  16.   """Devuelve una lista con todos los archivos de código c, del directorio  'path' """
  17.   return [cname for cname in os.listdir(path) if cname.split('.')[-1].lower() in ('c', 'cpp')]
  18.  
  19. def base_name(filename):
  20.   """Devuelve el nombre de un fichero, sin extensión"""
  21.   return  os.path.splitext(filename)[0]
  22.  
  23. def header_name(cfilename):
  24.   """Devuelve el nombre de un archivo de cabecera a partir del nombre del archívo de código"""
  25.   return base_name(cfilename) + '.h'
  26.  
  27.  
  28. def header_process(filename):
  29.   """Genera un archivo de cabecera si no existe"""
  30.  
  31.   # Si existe el archivo de cabecera, retorna
  32.   hfilename = header_name(filename)
  33.   if os.path.exists(hfilename):
  34.     return
  35.  
  36.   # Escribe el archivo de cabecera en el disco
  37.   print("Generando: %s" % hfilename)
  38.   hfile_text = header_template.substitute(
  39.      DEFINE = '_' + basename.upper() + '_H',
  40.      CFILE = cfilename)
  41.   open(hfilename, 'wt').write(hfile_text)
  42.  
  43.  
  44. if __name__ == "__main__":
  45.   for cfilename in list_cfiles('.'):
  46.     header_process(cfilename)

Saludos.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re: Generador de cabeceras .h automático
« Respuesta #5 en: 24 de Marzo de 2015, 16:57:32 »
Debo deir que por ahora parese muy poco intuitivo... quizá por conocer otros lenguajes que son mas o menos similares.
Evidentemente para aprender voy a tener que arrancar de cero cero, muy poco de lo que conozco me sirve para este lenguaje. Lo que sí se ve a simple vista es que es muy práctico y directo. Maneja cadenas y archivos de forma directa... voy a seguir leyendo y practicando sobre este ejemplo.

Saludos!
-
Leonardo Garberoglio

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #6 en: 24 de Marzo de 2015, 19:10:21 »
Este programa es avanzado. Incluye muchos conceptos.
No vale como ejemplo para comenzar.
Una vez que lo conoces te van surgiendo atajos y maneras de hacer las cosas que a un principiante le despistan.

Imágínate para alquien que no sepa c:

   while(*p++ = q*++);

   printf("%04X\t%04X", *((int *)&i), *((int *)&i)+1));

   for(int i=100;i--;)


Saludos.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Generador de cabeceras .h automático
« Respuesta #7 en: 24 de Marzo de 2015, 20:28:28 »
Debo deir que por ahora parese muy poco intuitivo... quizá por conocer otros lenguajes que son mas o menos similares.
Evidentemente para aprender voy a tener que arrancar de cero cero, muy poco de lo que conozco me sirve para este lenguaje. Lo que sí se ve a simple vista es que es muy práctico y directo. Maneja cadenas y archivos de forma directa... voy a seguir leyendo y practicando sobre este ejemplo.

Saludos!

Es que no estas acostumbrado a python xD, es distinto a los demas, el ejemplo mas simple:

Código: Python
  1. for filename in os.listdir('.'):
  2.    ext = filename.split('.')[-1]                   # Divide el nombre por el caracter '.' y toma el último
  3.    if ext.lower() == 'c' or ext.lower() == 'cpp':  # Si la extension en minúsculas es 'c' o 'cpp'
  4.       print(filename)

Primero notar la identacion.
Para que lo entiendas como en C

for filename in os.listdir('.'):
Primer linea es un for, y dice que por cada nombre de archivo (filename) en el "array"(lista) que devuelve os.listdir('.'), es decir la direccion (carpeta) donde se encuentra el .py Haga:

ext = filename.split('.')[-1]
Tomar el nombre y divirlo apenas encuentre un punto, suponete el nombre archivo.txt esto te queda asi: [archivo,txt] , y toma el -1 que es txt y lo guarda en ext

if ext.lower() == 'c' or ext.lower() == 'cpp':
Como puede estar en mayuscula utiliza el lower para pasarlo a minuscula y lo compara con "c" o "cpp"

print(filename)
De cumplirse la condicion del if, imprime en la consola el nombre del archivo completo.



Una cosa mas con el tema del split y como maneja python los "arrays", No recuerdo si era 0 based o comenzaba de 1 el array, pero voy a suponer que comienza de uno, por lo que quiero explicar no va a haber problema
Suponete esto:

str = "Line1-abcdef Line2-abc Line3-abcdef Line4-abcd";

Si le hago un split a esto y guardo en otra variable puedo hacer:

ext = str.split(' ')          Esto me lo deja como : ['Line1-abcdef', 'Line2-abc', 'Line3-abcd', 'Line4-abcd']
ext = str.split(' ')[1]      Esto me deja a ext con el valor : 'Line1-abcdef'
ext = str.split(' ')[2:]    Esto me lo deja como : ['Line2-abc', 'Line3-abcd', 'Line4-abcd']
ext = str.split(' ')[2:3]    Esto me lo deja como : ['Line2-abc', 'Line3-abcd']

Si en algo me equivoco que me corrija picuino, hace mucho que no toco python.
« Última modificación: 24 de Marzo de 2015, 21:07:34 por KILLERJC »

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #8 en: 24 de Marzo de 2015, 20:54:28 »
Una lista es un conjunto de elementos. El primer elemento comienza por 0 (como en c).
En la web de python hay muchos ejemplos para saber manejarlas.

https://docs.python.org/2/tutorial/introduction.html#lists

https://docs.python.org/2/tutorial/datastructures.html#more-on-lists


Saludos.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re: Generador de cabeceras .h automático
« Respuesta #9 en: 24 de Marzo de 2015, 21:07:52 »
En realidad, ese primer ejemplo lo entendí  :P
El tema aparece en el segundo ejemplo, especificamente en esto:

Código: [Seleccionar]
return [cname for cname in os.listdir(path) if cname.split('.')[-1].lower() in ('c', 'cpp')]

si bien entiendo el objetivo, al estar en una sola línea me queda la duda de si es una sola "instruccion" o como se han anidado las mismas.
O sea, entiendo que devuelve cname, que cename sera una lista de los archivos en el path y que la extension de cname debe estar en la lista 'c', 'cpp'. Pero esta "anidado" o es todo parte de la sentencia for?

saludos!
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Generador de cabeceras .h automático
« Respuesta #10 en: 24 de Marzo de 2015, 21:22:53 »
Podrias anidarlo con algunos agregados, esta todo escrito en una sola linea.

Devuelve cname si (este es el if de atras ), donde por cada cname en la direccion "path" cumpla con la condicion de que la extension en minuscula (cname.split('.')[-1].lower()) este en la lista ('c', 'cpp')

En fin revisa todas las extensiones de los archivos buscando algun c o cpp, y va asignando a cname aquellos que cumplen con el objetivo, por ultimo devuelve esta lista.

Ahora que recuerdo no hay arrays, sino tuplas y listas..

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re: Generador de cabeceras .h automático
« Respuesta #11 en: 25 de Marzo de 2015, 06:18:28 »
Esa instrucción es una forma muy eficiente de manejar listas.

Estos dos códigos hacen lo mismo:

Código: Python
  1. from timeit import timeit
  2.  
  3.  
  4. print(timeit("""
  5.  
  6.  data = ['Frase de ejemplo'] * 1000000
  7.  
  8.  lista1 = []
  9.  for s in data:
  10.    lista1.append(s)
  11.  
  12. """, number=10))
  13.  
  14.  
  15. print(timeit("""
  16.  
  17.  data = ['Frase de ejemplo'] * 1000000
  18.  
  19.  lista2 = [s for s in data]
  20.  
  21. """, number=10))

La diferencia está en que el segundo es mucho más rápido y se escribe en menos líneas.

El resultado en mi ordenador:
2.646727243   segundos del primer código
1.152120306   segundos del segundo código


Un saludo.


 

anything