elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Arreglado, de nuevo, el registro del warzone (wargame) de EHN


  Mostrar Temas
Páginas: 1 [2]
11  Foros Generales / Sugerencias y dudas sobre el Foro / Sitio externo para subir los archivos fuente en: 3 Marzo 2014, 18:49 pm
A veces cuando colocamos fragmentos de código muy grandes en nuestros posts, los mismos se hacen de una extensión inmensa. Imagínense si se trata de un proyecto grande con varias cabecera, y fuentes ...

Me gustaría saber si ustedes recomienda un sitio externo especializado en subir archivos fuentes de C, y colocar en nuestros post sólo el link a dichos sitios

..........  :huh:
12  Programación / Programación C/C++ / Biblioteca de matriz de cadenas en: 3 Marzo 2014, 18:44 pm
Hola a todos. En esta ocasión quiero compartir un trabajo con la comunidad. También se aceptan críticas (de buena fe), sugerencias, etc ...

A veces queremos leer texto organizado en forma de tabla, con filas y columas. Por ejemplo, a partir de un fichero de texto formateado en columnas, o en el resultado de convertir una hoja de cálculo a un .txt
En tales ocasiones es común crear una matriz bidimensional de cadenas para almacenar los datos.

Como es una tarea rutinaria y repetitiva, quise desarrollar una clase "StringMatrix" de matriz de cadenas. Dicha clase posee su respectivo constructor por defecto, un constructor de copia (para obtener un objeto nuevo como copia idéntica del contenido de otro), un operador de asignación (para hacer el contenido de un StringMatrix idéntido al de otro), así como los tradicionales getElement y putElement para obtener y colocar elementos desde y en la matriz. Funcionan así:
Código
  1. putElement(i, j, str);
escribe el contenido del string str en la posición (i,j) de la matriz (los valores de los índices empiezan en cero). Es de hacer notar que trabaja "por copia", esto es, el elemento (i,j) reserva su espacio de memoria propio donde copia el contenido de str, luego el propio str puede alterado luego sin afectar el contenido de la matriz. Por otra parte, si se pide asignar en una posición que excede el tamaño de la matriz, se intenta dimensionar la misma previamente. Devuelve -1 en caso de error (por ejemplo, si falla la asignación de memoria), y 0 en caso de éxito.

Código
  1. str = getElement(i, j);
devuelve en str una copia del contenido del elemento (i,j) de la matriz. Es importante que devuelva un valor "por copia", pues así podemos alterar el string str devuelto sin afectar la matriz original.

Los métodos NRows() y NCols(), que no toman argumentos, devuelven la cantidad de filas y columnas, respectivamente, de la matriz (al crear el objeto, estos números valen cero). Por su parte, los métodos addRow() y addColumn() sirven para añadir una fila o una columna a la matriz.

Finalmente el destructor como era de esperarse libera toda la memoria dinámicamente asignada y retorna. Se cuenta con un método peculiar Reinitialize() el cual también libera la memoria asignada y pone las dimensiones de la matriz a cero. Es similar al destructor, excepto que no destruye al objeto (éste sigue vivo) sino que lo pone en las mismas condiciones de cuándo fue creado. Es como "vaciar" la matriz para poder llenarla de nuevo.

CONDICIONES DE PRECAUCIÓN: Es de hacer notar que si el objeto no se crea con éxito (falla la petición de memoria realizada), sus dimensiones se ponen en -1. Los métodos getElement() y putElement() inspeccionan primero si existe esta condición de error y en dicho caso no se ejecutan. De un modo similar los métodos addRow() y addColumn() inspecionan si la petición de memoria fue exitosa y sólo en ese caso incrementan el contador de filas o de columnas. En caso contrario, no se añade ninguna fila o columna, y las dimensiones de la matriz permanecen iguales.

En mi opinión pueden mejorarse algunas cosas, como los nombres de los métodos (quizá addCol() en lugar de addColumn()), y añadir la posibilidad de eliminar una fila o columna solamente. También incorporar un método para redimensionar, que automáticamente añada las filas o columnas que hagan falta si se pasa de una dimensión menor a una mayor, o elimine las que sobren en caso contrario.

Aquí el fichero de cabecera de la clase. Ojo: el que algunos comentarios están en inglés no significa que me lo haya copiado de internet >:(, sino que los puse en ese idioma por si navegando por el inmenso mundo que es la web, este código llega a ser leído fuera de fronteras hispanas (jeje, aunque eso requeriría mucha suerte  :laugh:)

Código
  1. /* SMATRIX.H
  2.  * Declaración de la clase sMatrix
  3.  * Las funciones miembro están definidas en smatrix.cpp
  4.  *
  5.  * Por Yoel Monsalve.
  6.  */
  7.  
  8. #ifndef SMATRIX_H
  9. #define SMATRIX_H
  10.  
  11. /*** Definición de la clase StringMatrix ***/
  12. class StringMatrix { // matriz de cadenas de caracteres
  13. public:
  14. StringMatrix(); /* constructor por defecto */
  15. StringMatrix( StringMatrix & ); /* constructor de copia */
  16. ~StringMatrix(); /* destructor */
  17. void ReInitialize(void);
  18. char *getElement(int, int);
  19. int putElement(int, int, const char *);
  20. int NRows();
  21. int NCols();
  22. int addRow(); /* añadir una fila: devuelve 0 si tuvo éxito, -1 si no tuvo */
  23. int addColumn(); /* añadir una columna: devuelve 0 si tuvo éxito, -1 si no tuvo */s
  24.  
  25. StringMatrix &operator = (StringMatrix &);
  26. private:
  27. char ***Matrix; /* para almacenar físicamente los elementos de la matriz */
  28. int _NRows; /* cantidad de filas */
  29. int _NCols; /* cantidad de columnas */
  30. };
  31.  
  32. #endif

y ahora el código fuente de la clase:

Código
  1. /* SMATRIX.CPP
  2.  * Definiciones de funciones miembro de la clase sMatrix.
  3.  *
  4.  * Por Yoel Monsalve.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "smatrix.h"
  11.  
  12. /* Default constructor.
  13.  * Constructor por defecto. */
  14. StringMatrix :: StringMatrix( ) {
  15.  
  16. Matrix = (char ***) malloc( sizeof(char **) );
  17.  
  18. if (Matrix != NULL)
  19. _NRows = _NCols = 0; /* success */
  20. else
  21. _NRows = _NCols = -1; /* constructor failed !!! */
  22. }
  23.  
  24. /* Copy constructor. Creates a new object as a copy of other object.
  25.  * Constructor de copia. Crea un nuevo objeto como una copia de otro objeto. */
  26. StringMatrix :: StringMatrix ( StringMatrix &S ) {
  27.  
  28. int i, j;
  29.  
  30. Matrix = (char ***) malloc( sizeof(char **) );
  31. if (Matrix != NULL)
  32. _NRows = _NCols = 0; /* success */
  33. else {
  34. _NRows = _NCols = -1; /* constructor failed !!! */
  35. return;
  36. }
  37.  
  38. /* resize at the same size of S */
  39. if ( S.NRows() < 0 || S.NCols() < 0 ) return;
  40. while ( _NRows < S.NRows() )
  41. addRow();
  42. while ( _NCols < S.NCols() )
  43. addColumn();
  44.  
  45. printf("%d, %d\n", S.NRows(), S.NCols());
  46. /* and copy here the content of S */
  47. for ( i = 0; i < _NRows; i++ )
  48. for ( j = 0; j < _NCols; j++ )
  49. Matrix[i][j] = S.getElement(i, j);
  50. }
  51.  
  52. /* Assignment operator, from other StringMatrix object.
  53.  * Operador de asignacióm, a partir de otro objeto StringMatrix. */
  54. StringMatrix & StringMatrix :: operator = (StringMatrix &S) {
  55.  
  56. int i, j;
  57.  
  58. /* avoid self-assignment */
  59. if ( &S == this ) return *this;
  60.  
  61. /* caution if matrix creation failed */
  62. if ( _NRows < 0 || _NCols < 0 )
  63. return *this;
  64.  
  65. /* resize at the same size of S */
  66. if ( S.NRows() < 0 || S.NCols() < 0 ) return *this;
  67. while ( _NRows < S.NRows() )
  68. addRow();
  69. while ( _NCols < S.NCols() )
  70. addColumn();
  71.  
  72. /* and copy here the content of S */
  73. for ( i = 0; i < _NRows; i++ )
  74. for ( j = 0; j < _NCols; j++ )
  75. Matrix[i][j] = S.getElement(i, j);
  76. }
  77.  
  78. /* "Re-initializes" the object. Frees the dinamic allocated memory, and
  79.  * it puts the dimensions to zero. This is, returns he object to the original
  80.  * state like it was created.
  81.  *
  82.  * "Re-inicializa" el objeto. Libera la memoria dinámicamente asignada,
  83.  * y pone las dimensiones a cero. Es decir, devuelve el objeto al estado
  84.  * original como fue creado */
  85. void StringMatrix :: ReInitialize( ) {
  86.  
  87. int i, j;
  88.  
  89. /* if matrix creation failed, try create it again */
  90. if ( _NRows < 0 || _NCols < 0 ) {
  91. Matrix = (char ***) malloc( sizeof(char **) );
  92. if (Matrix != NULL)
  93. _NRows = _NCols = 0; /* success */
  94. else {
  95. _NRows = _NCols = -1; /* constructor failed !!! */
  96. return;
  97. }
  98. }
  99.  
  100. /* frees the allocated memory space */
  101. if (_NRows > 0) {
  102. for (i = 0; i < _NRows; i++) {
  103. if (_NCols > 0) {
  104. for (j = 0; j < _NCols-1; j++)
  105. free(Matrix[i][j]);
  106. Matrix[i][j] = NULL;
  107. }
  108. free(Matrix[i]);
  109. Matrix[i] = NULL;
  110. }
  111. }
  112. _NRows = _NCols = 0;
  113. }
  114.  
  115. /* Class destructor /
  116.  * Destructor de la clase */
  117. StringMatrix :: ~StringMatrix( ) {
  118. int i, j;
  119.  
  120. /* frees the allocated memory assigned to the objects /
  121. * libera el espacio de memoria asignado a los objetos */
  122. for (i=0; i<_NRows; i++) {
  123. for (j=0; j<_NCols; j++) {
  124. free( Matrix[i][j] );
  125. Matrix[i][j] = NULL;
  126. }
  127. free( Matrix[i] );
  128. Matrix[i] = NULL;
  129. }
  130. free( Matrix );
  131. Matrix = NULL;
  132.  
  133. _NRows = -1;
  134. _NCols = -1;
  135. }
  136.  
  137. /* Get the number of rows of the matriz /
  138.  * Obtener el numero de filas de la matriz */
  139. int StringMatrix :: NRows( ) {
  140.  
  141. return _NRows;
  142. }
  143.  
  144. /* Get the number of columns of the matriz /
  145.  * Obtener el numero de columnas de la matriz */
  146. int StringMatrix :: NCols( ) {
  147.  
  148. return _NCols;
  149. }
  150.  
  151. /* Get an specific element in the matrix. Warning: the indexes start in zero.
  152.  * On success is returned a copy of the string stored in such element of
  153.  * the matrix. On error, returns NULL.
  154.  
  155. /* Obtener un elemento especifico de la matriz. Cuidado: los índices empiezan
  156.  * en cero. En caso exitoso devuelve una copia de la cadena almacenada en
  157.  * dicho elemento de la matriz. En caso de error, devuelve NULL. */
  158. char * StringMatrix :: getElement( int i, int j ) {
  159.  
  160. char *s;
  161.  
  162. /* caution if matrix creation failed */
  163. if ( _NRows < 0 || _NCols < 0 )
  164. return NULL;
  165.  
  166. /* must be 0 <= i <= _N_Rows - 1, and 0 <= j <= _NCols - 1 */
  167. if (i < 0 || i >= _NRows || j < 0 || j >= _NCols)
  168. return NULL;
  169.  
  170. if ( ( s = (char *) malloc ( (strlen(Matrix[i][j]) + 1) * sizeof(char) ) ) == NULL )
  171. return NULL;
  172.  
  173. strcpy(s, Matrix[i][j]);
  174. return s;
  175. }
  176.  
  177. /* Puts an element in a specified position of the matrix. If the position
  178.  * exceed the size of matrix, the same is automatically resized.
  179.  * On success returns 0, and -1 otherwise.
  180.  *
  181.  * Pone un elemento en una posicion especificada de la matriz. Si la posicion
  182.  * excede el tamano de la matriz, la misma es redimensionada automaticamente.
  183.  * Devuelve 0 si tuvo exito, -1 si no tuvo. */
  184. int StringMatrix :: putElement( int i, int j, const char * s ) {
  185.  
  186. char *cPtr;
  187.  
  188. /* caution if matrix creation failed */
  189. if ( _NRows < 0 || _NCols < 0 )
  190. return -1;
  191.  
  192. /* fail if i < 0, or j < 0 */
  193. if ( i < 0 | j < 0 )
  194. return -1;
  195.  
  196. /* if i > _NRows - 1, completed rows that are needed */
  197. while ( i >= _NRows )
  198. addRow();
  199.  
  200. /* if j > _NCols - 1, completed columns that are needed */
  201. while ( j >= _NCols )
  202. addColumn();
  203.  
  204. /* now, copies the s string in the (i,j) element of the matrix (allocates
  205. * memory before) */
  206. if ( ( cPtr = (char *) realloc( Matrix[i][j], (strlen(s) + 1) * sizeof(char) ) ) != NULL ) {
  207. strcpy(cPtr, s);
  208. Matrix[i][j] = cPtr;
  209. return 0;
  210. }
  211. else
  212. return -1;
  213.  
  214. }
  215.  
  216. /* Add a row to the matrix. On success returs 0, and -1 otherwise.
  217.  *
  218.  * Anade una fila a la matriz. Devuelve 0 si tuvo éxito, -1 si no tuvo. */
  219. int StringMatrix :: addRow() {
  220.  
  221. char ***xPtr;
  222. char **yPtr;
  223. char *zPtr;
  224. int j;
  225.  
  226. /* caution if matrix creation was failed */
  227. if ( _NRows < 0 ) return -1;
  228.  
  229. /* allocate memory for one more row */
  230. if ( ( xPtr = (char ***) realloc( Matrix, (_NRows + 1) * sizeof(char **) ) ) != NULL ) {
  231. Matrix = xPtr;
  232.  
  233. /* if matrix already has columns added */
  234. if ( _NCols > 0 ) {
  235. /* complete the new row with empty elements */
  236. if ( ( yPtr = (char **) malloc( _NCols * sizeof(char *) ) ) != NULL ) {
  237. Matrix[_NRows] = yPtr;
  238. for (j = 0; j < _NCols; j++) {
  239. if ( ( zPtr = (char *) malloc( sizeof(char) ) ) != NULL ) {
  240. Matrix[_NRows][j] = zPtr;
  241. *zPtr = '\0';
  242. }
  243. else
  244. return -1;
  245. }
  246. }
  247. else
  248. return -1;
  249. }
  250. /* otherwise */
  251. else {
  252. /* complete the new row with empty elements */
  253. if ( ( yPtr = (char **) malloc( 1 * sizeof(char *) ) ) != NULL ) {
  254. Matrix[_NRows] = yPtr;
  255. if ( ( zPtr = (char *) malloc( sizeof(char) ) ) != NULL ) {
  256. Matrix[_NRows][0] = zPtr;
  257. *zPtr = '\0';
  258. }
  259. else
  260. return -1;
  261. }
  262. else
  263. return -1;
  264. }
  265. }
  266. else
  267. return -1;
  268.  
  269. /* Success, then increase _NRows and return. */
  270. _NRows++;
  271. return 0;
  272. }
  273.  
  274. /* Add a column to the matrix. On success returs 0, and -1 otherwise.
  275.  *
  276. /* Anade una columna a la matriz. Devuelve 0 si tuvo éxito, -1 si no tuvo. */
  277. int StringMatrix :: addColumn() {
  278.  
  279. char **yPtr;
  280. char *zPtr;
  281. int i;
  282.  
  283. /* return if matrix creation was failed */
  284. if (_NRows <= 0 || _NCols < 0) return -1;
  285.  
  286. for (i = 0; i < _NRows; i++) {
  287. /* allocate memory for one more column */
  288. if ((yPtr = (char **) realloc( Matrix[i], (_NCols + 1) * sizeof(char *) ) ) != NULL ) {
  289. Matrix[i] = yPtr;
  290. if ( ( zPtr = (char *) malloc( sizeof(char) ) ) != NULL ) {
  291. Matrix[i][_NCols] = zPtr;
  292. *zPtr = '\0';
  293. }
  294. else
  295. return -1;
  296. }
  297. else
  298. return -1;
  299. }
  300.  
  301. /* Success, then increase _NCols and return. */
  302. _NCols++;
  303. return 0;
  304. }

Podemos ver ahora su funcionamiento, en el sencillo archivo de prueba que crea dos matrices, llena una con cuatro cadenas. Luego, en la segunda matriz se copia el contenido de la primera, y éste se imprime por la pantalla ¡Fácil!

Código
  1. #include <stdio.h>
  2. #include <smatrix.h>       /* fichero de cabecera de la clase */
  3.  
  4. int main() {
  5.  
  6. StringMatrix S, M;
  7. int i, j;
  8.  
  9. S.putElement(0, 0, "hugo");
  10. S.putElement(0, 1, "paco");
  11. S.putElement(1, 0, "maria");
  12. S.putElement(1, 1, "luisa");
  13.  
  14. /* copia contenido de S en M */
  15. M = S;
  16. /* y lo imprime en pantalla */
  17. for (i = 0; i < 2; i++) {
  18. for (j = 0; j < 2; j++)
  19. printf("%s\t", M.getElement(i, j) );
  20. fputs("\n", stdout);
  21. }
  22.  
  23. return 0;
  24. }

NOTA: para compilar el fichero de prueba, llamado por ejemplo test.cpp, enlazado con el fichero smatrix.cpp que define la clase StringMatrix, usar la orden:

g++ -o test test.cpp smatrix.cpp

y suponiendo que los tres archivos test.cpp, smatrix.cpp y smatrix.h están en el mismo directorio. Para un proyecto grande valdría la pena crear directorios src, include, lib donde poner los ficheros apropiados y compilar adecuadamente según el caso. Se puede también hacer una biblioteca con esta y otras clases de utilería, ustedes ya saben ...

Sugerencias, comentarios ?????
Páginas: 1 [2]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines