str2list:
 Todo Clases Archivos Funciones 'defines'
str2list.h
Ir a la documentación de este archivo.
1 // str2list.h (C) 2011 adolfo@di-mare.com
2 
3 /** \file str2list.h
4  \brief Funciones para crear listas y matrices a partir de hileras.
5 
6  \author Adolfo Di Mare <adolfo@di-mare.com>
7  \date 2011
8 */
9 
10 #ifndef str2list_h
11 #define str2list_h ///< Evita la inclusión múltiple
12 
13 #include <list> // std::list<>
14 #include <string> // std::string
15 #include <cstdlib> // atoi() atol() atof()
16 
17 /** Retorna \c true para todos los caracters considerados como
18  espacios en blanco por \c str2list().
19  - { <code> , () <> {} [] </code> } && \c isspace().
20  - El punto \c char('.') no es considerado espacio en blanco
21  ( pues forma parte de un número flotante: \c 1.0e22 ).
22  - <code> false == iswhitespace_str2list( '.' ) </code>.
23 
24  \dontinclude test_str2list.cpp
25  \skipline test::iswhitespace()
26  \until }}
27  \see test_str2list::test_iswhitespace()
28 */
29 template <class CHAR>
30 bool iswhitespace_str2list( CHAR ch ) {
31  if ( ch==',' || isspace(ch) ) { return true; }
32 
33  if ( ch=='(' || ch==')' ) { return true; }
34  if ( ch=='<' || ch=='>' ) { return true; }
35  if ( ch=='{' || ch=='}' ) { return true; }
36  if ( ch=='[' || ch==']' ) { return true; }
37  return false;
38 // NOTA: implementado con plantillas para evitar usar el archivo str2list.cpp
39 }
40 
41 /** Almacena en \c "L<>" la lista de hileras construida en base a \c "str".
42  - En \c "str" están los valores que serán almacenados en \c "L<>" separados
43  por varios delimitadores.
44  - Como delimitadores se usan los caracteres blancos y la coma.
45  - Como delimitadores se usan los caracteres \c ispace() y \c ','.
46  - El punto \c '.' no se interpreta como delimitador.
47  - Los caracteres { <code> , () <> {} [] </code> } son interpretados como
48  blancos y no verifica que estén balanceados o en parejas.
49  - Ignora el paréntesis del principio y del final de \c "str".
50  - Si al principio encuentra el caracter \c '|' procesa la hilera hasta que
51  encuentra el siguiente caracter \c '|'.
52  - No examina lo que está después de la barrita final \c '|'.
53  - Siempre modifica el valor de \c "L<>".
54  - Retorna la última posición de \c "str" que fue examinada.
55 
56  \dontinclude test_str2list.cpp
57  \skipline test::str2list::list()
58  \until }}
59  \see test_str2list::str2list_list()
60 */
61 template <class STRING>
62 const char* str2list( std::list<STRING>& L , const char* str ) {
63  L.clear();
64  if ( str == 0) { return 0; }
65  if (*str == 0) { return str; }
66  while ( iswhitespace_str2list(*str) ) { ++str; } // skip leading blanks
67  if (*str=='|') { ++str; } // skip first '|'
68 
69  std::string val; // next value to store into L
70  const bool IN_WHITESPACE = false; const bool IN_STRING = !IN_WHITESPACE;
71  bool state = IN_WHITESPACE;
72  while ( (*str != 0) && (*str != '|') ) {
73  if ( state == IN_WHITESPACE ) {
74  if ( ! iswhitespace_str2list(*str) ) {
75  state = IN_STRING;
76  val = *str;
77  }
78  }
79  else { // assert( state == IN_STRING );
80  if ( iswhitespace_str2list(*str) ) {
81  L.push_back( val );
82  val.clear();
83  state = IN_WHITESPACE;
84  }
85  else {
86  val += *str;
87  }
88  }
89  ++str;
90  }
91  if ( !val.empty() ) { L.push_back(val); }
92  return str;
93 // NOTA: implementado con plantillas para evitar usar el archivo str2list.cpp
94 }
95 
96 
97 /** Usa \c str2list(L,str) para retornar la lista de valores de \c "str".
98 
99  \dontinclude test_str2list.cpp
100  \skipline test::str2list::example()
101  \until }}
102  \see test_str2list::str2list_example()
103 */
104 inline std::list<std::string> str2list( const char* str ) {
105  std::list<std::string> L;
106  str2list(L,str);
107  return L;
108 }
109 
110 /** Retorna la lista de valores construida en base a \c "str".
111  Usa \c str2list() junto con \c ATON_wrap::ATON().
112  \tparam N tipo de dato: { <code> int long double </code> }
113  \tparam ATON_wrap Empaque \c ATON() alrededor del convertidor:
114  { <code> atoi() atol() atof() </code> }.
115 */
116 template <class N, class ATON_wrap>
117 std::list<N> str2list_wrap( const char* str ) {
118  std::list<std::string> L;
119  std::list<N> RES;
120  str2list(L,str);
121 
122  std::list< std::string >::const_iterator it;
123  for ( it= L.begin(); it!=L.end(); ++it ) {
124  RES.push_back( ATON_wrap::ATON(it->c_str()) );
125  }
126  return RES;
127 }
128 
129 /// Empaque \c ATON() alrededor de la función \c atoi().
131  /// Retorna \c atoi(str).
132  static int ATON( const char * str ) { return atoi(str); }
133 };
134 
135 /// Empaque \c ATON() alrededor de la función \c atol().
137  /// Retorna \c atol(str).
138  static long ATON( const char * str ) { return atol(str); }
139 };
140 
141 /// Empaque \c ATON() alrededor de la función \c atof().
143  /// Retorna \c atof(str).
144  static double ATON( const char * str ) { return atof(str); }
145 };
146 
147 inline std::list<int> intlist( const char* str ) {
148  return str2list_wrap<int, str2list_int_wrap>( str );
149 } ///< Sinónimo de \c makeList_int().
150 
151 /** Retorna la lista de enteros \c (int) construida en base a \c "str".
152  Usa \c str2list() junto con \c atoi().
153 
154  \dontinclude test_str2list.cpp
155  \skipline test::intlist()
156  \until }}
157  \see test_str2list::test_intlist()
158 */
159 inline std::list<int> makeList_int( const char* str ) {
160  return str2list_wrap<int, str2list_int_wrap>( str );
161 }
162 
163 
164 inline std::list<long> longlist( const char* str ) {
165  return str2list_wrap<long, str2list_long_wrap>( str );
166 } ///< Sinónimo de \c makeList_long().
167 
168 /** Retorna la lista de enteros \c (long) construida en base a \c "str".
169  Usa \c str2list() junto con \c atol().
170 
171  \dontinclude test_str2list.cpp
172  \skipline test::makeList_long()
173  \until }}
174  \see test_str2list::test_makeList_long()
175 */
176 inline std::list<long> makeList_long( const char* str ) {
177  return str2list_wrap<long, str2list_long_wrap>( str );
178 }
179 
180 
181 /** Retorna la lista de flotantes construida en base a \c "str".
182  Usa \c str2list() junto con \c atof().
183 
184  \dontinclude test_str2list.cpp
185  \skipline test::doublelist()
186  \until }}
187  \see test_str2list::test_doublelist()
188 */
189 inline std::list<double> doublelist( const char* str ) {
190  return str2list_wrap<double, str2list_double_wrap>( str );
191 }
192 
193 std::list<char> charlist( const char* str ) {
194  std::list<std::string> Lstr;
195  std::list<char> Lchar;
196  str2list(Lstr,str);
197 
198  std::list< std::string >::const_iterator it;
199  for ( it= Lstr.begin(); it!=Lstr.end(); ++it ) {
200  if ( (*it)[0] == '\'' ) {
201  if ( it->size() == 1 ) {
202  Lchar.push_back( ' ' ); // blank
203  ++it;
204  }
205  else {
206  Lchar.push_back( (*it)[1] );
207  }
208  }
209  else {
210  Lchar.push_back( (*it)[0] );
211  }
212  }
213 
214  return Lchar;
215 } ///< Sinónimo de \c makeList_char().
216 
217 /** Retorna la lista de caracteres \c (char) construida en base a \c "str".
218  Usa \c str2list() pero se brinca las comillas simples \c (').
219  - No necesita que cada letra venga entre comillas simples.
220  - Si alguno de los valores tiene más de un caracter, usa el primero e ignora los demás.
221 
222  \dontinclude test_str2list.cpp
223  \skipline test::charlist()
224  \until }}
225  \see test_str2list::test_makeList_char()
226 */
227 inline std::list<char> makeList_char( const char* str ) {
228  return charlist( str );
229 }
230 
231 /** Almacena en \c "M<<>>" la matriz de hileras construida en base a \c "str".
232  - Cada renglón de la matriz debe estar entre caracteres \c '|'.
233  - Para obtener cada renglón se usa \c str2list().
234  - La matriz se retorna como una lista de listas de hileras.
235  - Ignora sublistas nulas pues \c "M<<>>" nunca contiene sublistas nulas.
236  - Siempre modifica el valor de \c "M<<>>".
237  - Retorna la longitud de la sublista más grande de \c "M<<>>" (para
238  calcular cuántas columnas tiene la matriz).
239 
240  \dontinclude test_str2list.cpp
241  \skipline test::str2matrix()
242  \until }}
243  \see test_str2list::test_str2matrix()
244 */
245 template <class STRING>
246 size_t str2matrix( std::list< std::list<STRING> >& M , const char* str ) {
247  M.clear();
248  if ( str == 0) { return 0; }
249  if (*str == 0) { return 0; }
250 
251  size_t mx = 0; // max sublist length
252  M.push_back( std::list<STRING>() );
253  while ( *str != 0 ) {
254  typename std::list<STRING> & L = M.back(); // L: last list in M<<>>
255  str = str2list( L , str );
256  if ( *str!=0 ) { str++; }
257  mx = ( L.size()<mx ? mx : L.size() ); // keep max
258  if ( ! M.back().empty() ) {
259  M.push_back( std::list<STRING>() );
260  }
261  }
262  if ( M.back().empty() ) { M.pop_back(); }
263  return mx;
264 // NOTA: implementado con plantillas para evitar usar el archivo str2list.cpp
265 }
266 
267 /** Almacena en \c MATRIX[][] la matriz construida en base a \c "str".
268  Usa \c str2matrix() junto con \c ATON_wrap::ATON().
269  \tparam N tipo de dato: { <code> int long double </code> }
270  \tparam ATON_wrap Empaque \c ATON() alrededor del convertidor:
271  { <code> atoi() atol() atof() </code> }
272  \tparam Nrows Cantidad de filas de \c MATRIX[][].
273  \tparam Ncols Cantidad de columnas de \c MATRIX[][].
274 */
275 template <class N, class ATON_wrap, unsigned Nrows, unsigned Ncols>
276 void matrix2list_wrap( N MATRIX[Nrows][Ncols] , const char* str ) {
277  std::list< std::list<std::string> > Mlist;
278  size_t NCOLS = str2matrix( Mlist , str ); // Mlist <== str
279  size_t NROWS = Mlist.size();
280 
281  NROWS = ( NROWS<Nrows ? NROWS : Nrows ); // take min(NROWS,Nrows)
282  NCOLS = ( NCOLS<Ncols ? NCOLS : Ncols ); // take min(NCOLS,Ncols)
283 
284  typename std::list< std::list<std::string> > :: const_iterator it;
285  typename std::list<std::string> :: const_iterator jt;
286 
287  it = Mlist.begin();
288  for ( size_t i=0; i<NROWS; ++i,++it ) {
289  jt = it->begin();
290  for ( size_t j=0; j<NCOLS; ++j ) {
291  if ( jt==it->end() ) { MATRIX[i][j] = 0; }
292  else {
293  MATRIX[i][j] = ATON_wrap::ATON( jt->c_str() );
294  jt++;
295  }
296  }
297  }
298 }
299 
300 /** Almacena en \c M[][] la matriz de enteros \c (int) construida en base a \c "str".
301  Usa \c str2matrix() junto con \c atoi().
302 
303  \dontinclude test_str2list.cpp
304  \skipline test::intmatrix()
305  \until }}
306  \see test_str2list::test_intmatrix()
307 */
308 template <unsigned Nrows, unsigned Ncols>
309 inline void intmatrix( int M[Nrows][Ncols] , const char* str ) {
310  return matrix2list_wrap<int, str2list_int_wrap, Nrows, Ncols>( M , str );
311 }
312 
313 /** Almacena en \c M[][] la matriz de enteros \c (long) construida en base a \c "str".
314  Usa \c str2matrix() junto con \c atol().
315  \dontinclude test_str2list.cpp
316  \skipline test::longmatrix()
317  \until }}
318  \see test_str2list::test_longmatrix()
319 */
320 template <unsigned Nrows, unsigned Ncols>
321 inline void longmatrix( long M[Nrows][Ncols] , const char* str ) {
322  return matrix2list_wrap<long, str2list_long_wrap, Nrows, Ncols>( M , str );
323 }
324 
325 /** Almacena en \c M[][] la matriz de flotantes construida en base a \c "str".
326  Usa \c str2matrix() junto con \c atof().
327  \dontinclude test_str2list.cpp
328  \skipline test::doublematrix()
329  \until }}
330  \see test_str2list::test_doublematrix()
331 */
332 template <unsigned Nrows, unsigned Ncols>
333 inline void doublematrix( double M[Nrows][Ncols] , const char* str ) {
334  return matrix2list_wrap<double,str2list_double_wrap,Nrows,Ncols>( M,str );
335 }
336 
337 #include <cstring> // memset()
338 
339 /** Almacena en \c M[][] la matriz de caracteres construida en base a \c "str".
340  Usa \c str2matrix() pero se brinca las comillas simples \c (').
341  - No necesita que cada letra venga entre comillas simples.
342  - Si alguno de los valores tiene más de un caracter, usa el primero e ignora los demás.
343 
344  \dontinclude test_str2list.cpp
345  \skipline test::charmatrix()
346  \until }}
347  \see test_str2list::test_charmatrix()
348 */
349 template <unsigned Nrows, unsigned Ncols>
350 inline void charmatrix( char M[Nrows][Ncols] , const char* str ) {
351  std::list< std::list<std::string> > Mstr;
352  str2matrix( Mstr, str );
353  memset( M, ' ', sizeof(M) ); // llena la matriz de blancos
354 
355  unsigned i,j; // paralelos (i<->it) && (j<->jt)
356  std::list< std::list<std::string> >::const_iterator it;
357  std::list<std::string>::const_iterator jt;
358  for ( i=0,it=Mstr.begin(); (i<Nrows && it!=Mstr.end()); ++i,++it ) {
359  const std::list<std::string>& Mrenglon = (*it);
360  for ( j=0,jt=Mrenglon.begin(); (j<Ncols && jt!=Mrenglon.end()); ++j,++jt ) {
361  if ( (*jt)[0] == '\'' ) {
362  if ( jt->size() == 1 ) {
363  M[i][j] = ' '; // blank
364  ++jt;
365  }
366  else {
367  M[i][j] = (*jt)[1];
368  }
369  }
370  else {
371  M[i][j] = (*jt)[0];
372  }
373  }
374  }
375  return;
376 }
377 
378 #endif // str2list_h
379 
380 // EOF: str2list.h