<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BeOSmAn&#039;s Blooog &#187; Lenguajes</title>
	<atom:link href="http://beosman.org/archivo/category/lenguajes/feed" rel="self" type="application/rss+xml" />
	<link>http://beosman.org</link>
	<description>Breaking with the past to build the future</description>
	<lastBuildDate>Fri, 18 May 2012 14:47:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Más de ortografía (o por qué si no escribes bien nadie te entiende)</title>
		<link>http://beosman.org/archivo/2012/lenguajes/mas-de-ortografia-o-por-que-si-no-escribes-bien-nadie-te-entiende.html</link>
		<comments>http://beosman.org/archivo/2012/lenguajes/mas-de-ortografia-o-por-que-si-no-escribes-bien-nadie-te-entiende.html#comments</comments>
		<pubDate>Tue, 24 Apr 2012 17:41:45 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[En el Mundo Real]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=6128</guid>
		<description><![CDATA[Sigo viendo, sobre todo en Twitter, cómo todavía hay gente que dice que la buena ortografía es innecesaria porque &#8220;total, si todo el mundo te entiende&#8221;. Pues venga, como &#8220;todo el mundo me entiende&#8221;, a descifrar esto: Yo calculo que el calculo que calculo el arbitro que arbitro, desanimo al prospero medico que prospero siendo [...]]]></description>
			<content:encoded><![CDATA[<p>Sigo viendo, sobre todo en Twitter, cómo todavía hay gente que dice que la buena ortografía es innecesaria porque <em>&#8220;total, si todo el mundo te entiende&#8221;</em>. Pues venga, como <em>&#8220;todo el mundo me entiende&#8221;</em>, a <a title="Enchufa2: La importancia de poner tildes" href="http://www.enchufa2.es/archives/la-importancia-de-poner-tildes.html"><em>descifrar</em> esto</a>:</p>
<blockquote class="small"><p>
Yo calculo que el calculo que calculo el arbitro que arbitro, desanimo al prospero medico que prospero siendo critico con quien critico a quien le medico por un palpito tras un resbalon por un liquido. Y el domine, sin su habito, rotulo en publico el modulo en el que habito.
</p></blockquote>
<p>¿Tener buena ortografía? ¿Yo? ¿Pero si todo el mundo me entiende?</p>
<p>Venga, y ahora que <a href="http://tts.imtranslator.net/KhjN">os lo lea una máquina para que veáis cómo suena realmente&#8230;</a> y para ver, también, si sois capaces de entenderlo, claro.</p>
<p class="postdata">
Aunque ya lo enlacé en el primer párrafo, este texto lo saqué de la entrada <a href="http://www.enchufa2.es/archives/la-importancia-de-poner-tildes.html">«La importancia de poner tildes»</a> del blog <a href="http://www.enchufa2.es">Enchufa2</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/lenguajes/mas-de-ortografia-o-por-que-si-no-escribes-bien-nadie-te-entiende.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Algoritmo de cálculo de la sucesión de Fibonacci en C++</title>
		<link>http://beosman.org/archivo/2012/informatica/algoritmo-de-calculo-de-la-sucesion-de-fibonacci-en-cpp.html</link>
		<comments>http://beosman.org/archivo/2012/informatica/algoritmo-de-calculo-de-la-sucesion-de-fibonacci-en-cpp.html#comments</comments>
		<pubDate>Thu, 08 Mar 2012 14:38:44 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5838</guid>
		<description><![CDATA[Seguro que todos los que habéis tenido matemáticas en el instituto o universidad conocéis la sucesión de Fibonacci. Y seguro que todos los que habéis hecho algún curso, módulo o carrera de informática la habéis tenido que implementar alguna vez, ¿verdad? Lo más fácil era seguir las instrucciones del profesor e implementar, sin salirse del [...]]]></description>
			<content:encoded><![CDATA[<p>Seguro que todos los que habéis tenido matemáticas en el instituto o universidad conocéis la <a href="http://es.wikipedia.org/wiki/Sucesi%C3%B3n_de_Fibonacci">sucesión de Fibonacci</a>. Y seguro que todos los que habéis hecho algún curso, módulo o carrera de informática la habéis tenido que implementar alguna vez, ¿verdad?</p>
<p>Lo más fácil era seguir las instrucciones del profesor e implementar, sin salirse del guión, la definición matemática de esta sucesión:</p>
<blockquote class="small"><p>
<em>f<sub>0</sub> = 0<br />
f<sub>1</sub> = 1<br />
f<sub>n</sub> = f<sub>n-1</sub> + f<sub>n-2</sub> para todo n = 2, 3, 4&#8230;</em>
</p></blockquote>
<p>Siguiendo esto estrictamente, en C++ os quedaría:</p>
<pre>

unsigned long long
fibonacci(int value) {
  if(value == 0) {
    return 0;
  } else if(value == 1) {
    return 1;
  } else {
    return fibonacci(value - 1) + fibonacci(value - 2);
  }
}
</pre>
<p>Este algoritmo, como podréis observar, es <a href="http://es.wikipedia.org/wiki/Recursividad">recursivo</a>, es decir, se llama a sí mismo con parámetros diferentes a los que se pasa inicialmente para calcular la solución.</p>
<p>Pero este algoritmo tiene un problema bastante más grave que el de la recursividad (que, dependiendo del número de llamadas recursivas, corremos el riesgo de desbordar la pila) y es el de la duplicidad de llamadas a la función con el mismo valor del parámetro. Es decir, ¿te has parado a pensar cuántas veces se llama a la función <code>fibonacci(int)</code> con el mismo parámetro? Pues te lo digo yo: para un valor inicial de 8, esta función se llama 13 veces con el 0, 21 veces con el 1, 13 veces con el 2, 8 veces con el 3, 5 veces con el 4, 3 veces con el 5, 2 veces con el 6 y 1 vez con el 7. En total 66 veces. 66 veces cuando el valor a calcular es 8. Si tenemos que calcular con el 20, la función se llama un total de ¡<span class="nowrap">21 890</span> veces!</p>
<p>Digamos que esta función, implementada directamente como se define matemáticamente, es totalmente ineficiente. Probad, si queréis, a calcular el tiempo de cálculo para 20, 40, 50… si tenéis tiempo, claro.</p>
<p>¿Y cómo solucionarlo? Pues mediante <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_din%C3%A1mica">programación dinámica</a>. Resumiendo, se trata de reducir el problema principal en problemas más pequeños, calcular la solución para cada problema pequeño y, finalmente, aplicar las soluciones de estos problemas pequeños para solucionar el problema grande.</p>
<p>Para la sucesión de Fibonacci específicamente, de lo que se trata es de no tener que calcular el mismo valor cada vez que se llama a la función, sino de tener una tabla donde están los valores previamente calculados. Si, cuando se llama a esta función el valor no está calculado, se calcula, pero si lo está, se recoge directamente de la tabla evitando toda esa recursividad y cálculos innecesarios.</p>
<p>Una posible implementación en C++ podría quedar así:</p>
<pre>

unsigned long long
fibonacci_alt(int value) {
	// Variables estáticas con la tabla de valores precalculados.
	static unsigned long long* prev_values = new unsigned long long[value];
	static bool init = true;
	if(init) {
		// Inicializamos sólo una vez.
		for(int i = 0; i &lt; value; i++) {
			prev_values[i] = -1;
		}
		init = false;
	}

	// Implementación de Fibonacci comprobando si hay algún valor precalculado.
	if(value == 0) {
		return 0;
	} else if(value == 1) {
		return 1;
	} else if(prev_values[value - 1] != -1 || prev_values[value - 2] != -1) {
		prev_values[value] = prev_values[value - 1] + prev_values[value - 2];
		return prev_values[value];
	} else {
		if(prev_values[value-1] == -1) {
			prev_values[value-1] = fibonacci_alt(value-1);
		}
		if(prev_values[value-2] == -1) {
			prev_values[value-2] = fibonacci_alt(value-2);
		}
		prev_values[value] = prev_values[value-1] + prev_values[value-2];
		return prev_values[value];
	}
}
</pre>
<p>Usando esta función, ésta sólo se ejecuta el número de veces indicado en el valor. Cierto es que usa más memoria, pero la reducción de tiempo es tan impresionante que merece la pena. De hecho, con este algoritmo, podréis calcular sin problemas la sucesión de Fibonacci para valores mayores de 200. Probad con el algoritmo anterior…</p>
<p>Y, ya de estar, <a href="/uploads/misc/fibonacci.cpp">aquí tenéis</a> un programa para probar estos dos algoritmos con alguna funcionalidad extra, como la de la presentación de estadísticas de llamadas a las funciones y demás. Y con un fallo: con el argumento “2” produce una <a href="http://es.wikipedia.org/wiki/Violaci%C3%B3n_de_segmento">violación de segmento</a>. Pero en general funciona.</p>
<p>Para compilarlo podéis usar el comando:</p>
<p class="terminal">
$ g++ -o fibonacci fibonacci.cpp
</p>
<p>Y para usarlo podéis hacerlo así (o usando el comando <code>time</code> para calcular cuánto tarda con cada método):</p>
<p class="terminal">
$ ./fibonacci<br />
fibonacci &lt;number&gt; [-a|-v|-av]<br />
Opciones:<br />
&nbsp;&nbsp;-a&nbsp;&nbsp;&nbsp;Usa el algoritmo alternativo.<br />
&nbsp;&nbsp;-v&nbsp;&nbsp;&nbsp;Muestra más información en pantalla.<br />
&nbsp;&nbsp;-av&nbsp;&nbsp;Usa el algoritmo alternativo mostrando más información.<br />
$ ./fibonacci 20<br />
6765<br />
$</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/informatica/algoritmo-de-calculo-de-la-sucesion-de-fibonacci-en-cpp.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Funciones de comprobación de tipos de datos en C++</title>
		<link>http://beosman.org/archivo/2012/informatica/funciones-de-comprobacion-de-tipos-de-datos-en-c.html</link>
		<comments>http://beosman.org/archivo/2012/informatica/funciones-de-comprobacion-de-tipos-de-datos-en-c.html#comments</comments>
		<pubDate>Tue, 06 Mar 2012 18:59:04 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5823</guid>
		<description><![CDATA[Haciendo uso de la STL de C++ y viendo que no tiene ninguna función &#8220;sencilla&#8221; de comprobación de tipos de datos, he implementado estas funciones para uso y disfrute de todo aquel que las quiera y las necesite. Con sus comentarios y todo. Por resumir, tenemos la función T StringTo&#60;T&#62;(string,T) (con sus diferentes variantes) para [...]]]></description>
			<content:encoded><![CDATA[<p>Haciendo uso de la <a href="http://en.wikipedia.org/wiki/Standard_Template_Library"><abbr title="Standard Template Library">STL</abbr></a> de <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> y viendo que no tiene ninguna función <em>&#8220;sencilla&#8221;</em> de comprobación de tipos de datos, he implementado estas funciones para uso y disfrute de todo aquel que las quiera y las necesite. Con sus comentarios y todo.</p>
<p>Por resumir, tenemos la función <code>T StringTo&lt;T&gt;(string,T)</code> (con sus diferentes variantes) para convertir una cadena al tipo determinado en la plantilla. Por ejemplo:</p>
<pre>

int i = StringTo&lt;int&gt;("42",0);  // i valdrá 42

bool error;
int a = StringTo&lt;int&gt;("42a",-1,error);  // a valdrá -1 y error será true

float f = StringTo&lt;float&gt;("123.45",-1);  // f valdrá 123.45
</pre>
<p>También está la función <code>bool StringIs&lt;T&gt;(string)</code> (también con sus variantes sobrecargadas) que comprueba si el valor pasado en la cadena como parámetro es del tipo indicado en la plantilla:</p>
<pre>

cout &lt;&lt; boolalpha &lt;&lt; StringIs&lt;int&gt;("42") &lt;&lt; endl;  // la salida será true
cout &lt;&lt; boolalpha &lt;&lt; StringIs&lt;int&gt;("42a") &lt;&lt; endl;  // la salida será false
cout &lt;&lt; boolalpha &lt;&lt; StringIs&lt;float&gt;("42") &lt;&lt; endl;  // la salida será true
cout &lt;&lt; boolalpha &lt;&lt; StringIs&lt;float&gt;("123.45") &lt;&lt; endl;  // la salida será true
</pre>
<p>Finalmente tenemos la función <code>string StringFrom&lt;T&gt;(T)</code> que devuelve una cadena con el valor pasado como parámetro convertido:</p>
<pre>

string value = StringFrom&lt;int&gt;(42);  // "value" contendrá la cadena "42"
string bvalue = StringFrom&lt;bool&gt;(true,boolapha);  // "bvalue" contendrá la cadena "true"
</pre>
<p>Y, ahora ya sí, la implementación:</p>
<pre>

#include &lt;string&gt;
#include &lt;sstream&gt;

using std::string;
using std::ios_base;
using std::stringstream;

/**
 * Convierte una cadena en el tipo dado en la plantilla.
 *
 * @param string value Valor a convertir.
 * @param T defaultValue Valor por defecto en caso de error.
 * @param bool&#038; error Esta variable se fija a true si hay error, a false si
 * todo_ está correcto.
 * @param ios_base f Si son números, se puede especificar una base de
 * conversión.
 * @return T Valor devuelto según la cadena pasada.
 */
template &lt;typename T&gt;
T
StringTo(const string value, T defaultValue, bool&#038; error, ios_base&#038; (*f)(ios_base&#038;) = NULL) {
	stringstream iss(value);
	T result;
	if(f == NULL) {
		iss &gt;&gt; result;
	} else {
		iss &gt;&gt; f &gt;&gt; result;
	}
	error = iss.fail() || iss.rdbuf()-&gt;in_avail() &gt; 0;
	return (iss.fail() || iss.rdbuf()-&gt;in_avail() &gt; 0 ? defaultValue : result);
}

/**
 * Función sobrecargada de la anterior donde se omite el parámetro "error".
 * @see template &lt;typename T&gt; T StringTo(const string, T, bool&#038;, ios_base&#038; (*)(ios_base&#038;));
 */
template &lt;typename T&gt;
T
StringTo(const string value, T defaultValue, ios_base&#038; (*f)(ios_base&#038;) = NULL) {
	bool result;
	return StringTo&lt;T&gt;(value, defaultValue, result, f);
}

/**
 * Función sobrecargada de la anterior con un "const char*" en lugar de
 * un string.
 *
 * @param const char* value Valor a convertir.
 * @param T defaultValue Valor por defecto.
 * @param ios_base&#038; f En caso de que sea un número y haya una base de
 * conversión.
 * @return T Tipo de dato a partir de la cadena.
 */
template &lt;typename T&gt;
T
StringTo(const char* value, T defaultValue, ios_base&#038; (*f)(ios_base&#038;) = NULL) {
	return StringTo&lt;T&gt;(string(value),defaultValue,f);
}

/**
 * Devuelve si una cadena contiene el tipo de dato indicado en la plantilla.
 *
 * @param string value Valor a controlar.
 * @param ios_base&#038; f En caso de que sea un número, la base de conversión.
 * @return bool True si la cadena es del tipo indicado, false en otro caso.
 */
template &lt;typename T&gt;
bool
StringIs(const string value, ios_base&#038; (*f)(ios_base&#038;) = NULL) {
	stringstream iss(value);
	T result;
	if(f == NULL) {
		iss &gt;&gt; result;
	} else {
		iss &gt;&gt; f &gt;&gt; result;
	}
	return !iss.fail() &#038;&#038; iss.rdbuf()-&gt;in_avail() &lt;= 0;
}

/**
 * Convierte un valor del tipo indicado en la plantilla a cadena de caracters.
 *
 * @param T value Valor.
 * @param ios_base&#038; f En caso de que sea numérico se puede especificar la base
 * de conversión.
 * @return string Cadena con el valor convertido.
 */
template &lt;typename T&gt;
string
StringFrom(const T value, ios_base&#038; (*f)(ios_base&#038;) = NULL) {
	stringstream result;
	if(f != NULL) {
		result &lt;&lt; f;
	}
	result &lt;&lt; (T)value;
	return result.str();
}
</pre>
<p><strong>Actualización 2012-03-07</strong>: Releyendo un poco el código y habiendo leído algo de documentación adicional, creo que quedaría más elegante si llamamos a las funciones de otra manera (con la misma implementación), por eso de simplificar. Más o menos así:</p>
<pre>

namespace string {

template &lt;typename T&gt; T to(const string) {…}

template &lt;typename T&gt; T is(const string) {…}

template &lt;typename T&gt; const string from(T value) {…}

}
</pre>
<p>Con lo que los ejemplos quedarían:</p>
<pre>

int i = string::to&lt;int&gt;("42");  // 42
bool isint = string::is&lt;int&gt;("42");  // true
string value = string::from&lt;float&gt;(123.45);  // "123.45"
</pre>
<p>Por simple elegancia <img src='http://beosman.org/wp-includes/images/smilies/grin.gif' alt=':grin:' class='wp-smiley' /> , ya que la funcionalidad es la misma. Pues quizás lo implemente&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/informatica/funciones-de-comprobacion-de-tipos-de-datos-en-c.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generar diccionarios de palabras en texto plano</title>
		<link>http://beosman.org/archivo/2012/informatica/generar-diccionarios-de-palabras-en-texto-plano.html</link>
		<comments>http://beosman.org/archivo/2012/informatica/generar-diccionarios-de-palabras-en-texto-plano.html#comments</comments>
		<pubDate>Fri, 17 Feb 2012 19:05:56 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>
		<category><![CDATA[Sistemas Operativos]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5733</guid>
		<description><![CDATA[Un diccionario, en la jerga informática, es un archivo de palabras en texto plano —es decir, sin formato— donde generalmente hay una palabra por línea. Este tipo de diccionarios tiene muchos usos, entre ellos la de actuar como base de correctores ortográficos como, por ejemplo, el diccionario de Mozilla Firefox. En Linux existe un paquete [...]]]></description>
			<content:encoded><![CDATA[<p>Un diccionario, en la jerga informática, es un archivo de palabras en texto plano —es decir, sin formato— donde generalmente hay una palabra por línea. Este tipo de diccionarios tiene muchos usos, entre ellos la de actuar como base de correctores ortográficos como, por ejemplo, el <a href="https://addons.mozilla.org/es-es/firefox/language-tools/">diccionario de Mozilla Firefox</a>.</p>
<p>En Linux existe un paquete de software llamado <a href="http://en.wikipedia.org/wiki/Aspell">Aspell</a> que es la base de la mayoría de correctores ortográficos que se usan en este sistema operativo. Y, Aspell, obviamente, también tiene muchas palabras de diferentes idiomas que usa para su cometido, sólo que los tiene en su formato interno.</p>
<p>Pero, ¿qué pasa cuando queremos obtener un diccionario para nuestros propios fines? Por ejemplo, para instalarlo como corrector ortográfico de <a href="http://www.eclipse.org">Eclipse</a>. Pues para ello, haremos uso, en Linux, del nombrado paquete Aspell en su forma de comando de consola. El famoso comando, que luego explicaré, es este:</p>
<p class="terminal nowrap">
$ aspell &#45;&#45;lang=es dump master | aspell &#45;&#45;lang=es expand | tr &#8216; &#8216; &#8216;\n&#8217; &gt; spanish-dict.txt
</p>
<p>Este gran comando, en realidad son cuatro (separados por &#8216;|&#8217; y el último por &#8216;&gt;&#8217;):</p>
<ol>
<li><code>aspell &#45;&#45;lang=es dump master</code>: Vuelca todas las palabras del diccionario interno de Aspell a formato de texto plano y una por línea, con la salvedad de que dichas palabras tienen códigos específicos para poder expandirlas (por ejemplo, poder expandir el infinitivo de un verbo en todas sus formas).</li>
<li><code>aspell &#45;&#45;lang=es expand</code>: Dada una entrada (que en el comando es la salida del comando anterior), expande cada palabra de cada línea en todas las que puede generar. Por ejemplo, lo que he comentado antes, un verbo en todas sus formas. Esta expansión se hace en la misma línea, es decir, todas las formas verbales, por ejemplo, aparecerán en la misma línea separadas por espacios.</li>
<li><code>tr ' ' '\n'</code>: La entrada de este comando es la salida del anterior, transformando todos los espacios en retornos de carro. Con esto se consigue que, ahora sí, cada palabra esté en una línea.</li>
<li><code>&gt; spanish-dict.txt</code>: Finalmente, la salida del comando anterior se redirige a un archivo cuyo nombre es &#8220;spanish-dict.txt&#8221;.</li>
</ol>
<p>Ahora, en el archivo <code>spanish-dict.txt</code> tenemos <span class="nowrap">1 250 789</span> palabras, una por línea, que podremos usar para lo que queramos.</p>
<p class="postdata">
P.D.: Llegados a este punto, os podéis preguntar para qué sirven, además, estos diccionarios, porque sólo como corrector ortográfico podría parecer poco, ¿no? Pues lleváis razón. Una de las cosas donde más se utilizan estos diccionarios, a parte de corregirnos las faltas, es para <em>crackear</em> contraseñas. El método se llama <a href="http://es.wikipedia.org/wiki/Ataque_de_diccionario">ataque de diccionario</a> y consiste en coger cada una de las palabras del archivo e ir probando si coinciden con la contraseña. Y, como <a href="http://www.meneame.net/story/hackean-email-presidente-sirio-password-12345">la mayoría de las contraseñas que usamos son débiles</a>, pues suele ser bastante rápido el descifrado.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/informatica/generar-diccionarios-de-palabras-en-texto-plano.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>De ortografía (o por qué es más importante expresar bien las ideas)</title>
		<link>http://beosman.org/archivo/2012/lenguajes/de-ortografia-o-por-que-es-mas-importante-expresar-bien-las-ideas.html</link>
		<comments>http://beosman.org/archivo/2012/lenguajes/de-ortografia-o-por-que-es-mas-importante-expresar-bien-las-ideas.html#comments</comments>
		<pubDate>Thu, 16 Feb 2012 15:13:23 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Lenguajes]]></category>
		<category><![CDATA[Opinión]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5703</guid>
		<description><![CDATA[El otro día, leyendo los comentarios de las noticias de Menéame, me quejo de que cada día menos tildes se ponen y más faltas se cometen. Que, ojo, todos las cometemos y no tiene mayor problema que el de corregirlas. Pero de ahí a jactarse de ello hay mucho. Otros argumentan, simplemente, que se centran [...]]]></description>
			<content:encoded><![CDATA[<p>El otro día, leyendo los comentarios de las noticias de <a href="http://www.meneame.net">Menéame</a>, <a href="http://www.meneame.net/notame/1070619">me quejo</a> de que cada día menos tildes se ponen y más faltas se cometen. Que, ojo, todos las cometemos y no tiene mayor problema que el de corregirlas. Pero de ahí a jactarse de ello hay mucho. <a href="http://www.meneame.net/notame/1070624">Otros argumentan</a>, simplemente, que se centran en las ideas, no en la forma.</p>
<p>Pero los que se escudan en esa idea, de que si es mejor el contenido que la forma, tendrían razón si no fuera porque, a veces, con eso de no preocuparse de la forma, no se entiende el contenido.</p>
<p>Y esto, precisamente, me lo recordó <a href="http://desequilibros.blogspot.com/2012/02/la-ortografia-no-importa-lo-importante.html">esta entrada</a> de <a href="http://desequilibros.blogspot.com">DesEquiLIBROS</a> donde <a href="/uploads/2012/02/ortografia-mi-clon-malvado.jpg">la viñeta</a> pone un ejemplo bastante claro.</p>
<p>Aún así, otra entrada de este blog, <em><a href="http://desequilibros.blogspot.com/2010/06/las-adulteras-sin-tilde.html">¿Realmente son pocos los inconvenientes que provoca la ausencia de tildes? Me dispongo a comprobarlo</a></em>, lo ilustra muchísimo mejor. Vemos unos pequeños ejemplo:</p>
<blockquote class="small"><p>
El diccionario era amplio, pero él lo amplió aún más como ahora lo amplío yo.</p>
<p>El editor asesino de tildes barrió el barrio hasta que alguien le pisó el callo y calló.</p>
<p>Habla tú ahora: bebe a la salud de su bebé y pregúntate si sin tildes cabrá la cabra.</p>
<p>Antes de que alguien le cascara la cáscara de lector, catalogó la novela sin tildes en el catálogo de lo nefasto y me pidió que no celebre que llegue a ser célebre (y no lo celebré).</p>
<p>La escritura sin tildes contrarió al contrario tal como yo le contrarío ahora.
</p></blockquote>
<p>La moraleja de la historia es bien sencilla: cuida la ortografía igual que las ideas, no vaya a ser que digas lo que no quieres decir por ahorrare un par de tildes.</p>
<p>En resumen, <a href="http://desequilibros.blogspot.com/2009/10/las-tildes-solo-molestan-quienes-no.html">como dicen en el blog</a>: <em>“Las tildes sólo<sup><a href="#solo">1</a></sup> molestan a quienes no saben dónde ponerlas”</em>.</p>
<p class="postdata">
P.D.: Una de las mejores cosas para tomar consciencia de qué es lo que habéis escrito ahorrándoos esas tildes es poner vuestro texto en un <a href="http://es.wikipedia.org/wiki/Lector_de_pantalla">lector de pantalla</a>. Vamos, que sea el ordenador quien lea. Y también <a href="http://imtranslator.net/translate-and-speak/speak/spanish/#window">los tenéis <em>on-line</em></a>.
</p>
<p class="postdata">
P.D.2: Los lectores de pantalla son más importantes de lo que la gente piensa en general, ya que las personas con deficiencias visuales también navegan por Internet, y el lector de pantalla es una de las formas que tienen de saber lo que hay escrito. ¿Habéis pensado alguna vez cómo una persona ciega lee vuestros comentarios? Imaginaos, ahora, si contienen faltas de ortografía.
</p>
<p id="solo" class="postdata">
<sup>1</sup> <strong>Actualización 2012-02-22</strong>: Ese <em>“sólo”</em> no llevaba tilde en su forma inicial, <a href="http://www.rae.es/rae/gestores/gespub000018.nsf/(voAnexos)/arch8100821B76809110C12571B80038BA4A/$File/CuestionesparaelFAQdeconsultas.htm#novOrto5">como recomienda la RAE</a>, pero yo, presonalmente, prefiero <em>cometer</em> esa falta de ortografía pos si hay ambigüedad, como en la frase <em>“esta tarde estaré solo comiendo”</em>. ¿Estaré solo, sin acompañamiento, o estaré solamente comiendo? <img src='http://beosman.org/wp-includes/images/smilies/grin.gif' alt=':grin:' class='wp-smiley' /></p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2012/lenguajes/de-ortografia-o-por-que-es-mas-importante-expresar-bien-las-ideas.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>C#</title>
		<link>http://beosman.org/archivo/2011/informatica/c-sharp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/c-sharp.html#comments</comments>
		<pubDate>Thu, 01 Dec 2011 18:54:20 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5299</guid>
		<description><![CDATA[Por necesidades del servicio voy a empezar a programar en C#, así que me he leído un par de manuales y he practicado un poco con ello. Y, la verdad, no me ha convencido demasiado. Así que, por petición popular (si por una persona se le puede llamar &#8220;popular&#8221;), estas son algunas de las conclusiones [...]]]></description>
			<content:encoded><![CDATA[<p>Por <em>necesidades del servicio</em> voy a empezar a programar en <a href="http://es.wikipedia.org/wiki/C_Sharp">C#</a>, así que me he leído un par de manuales y he practicado un poco con ello. Y, la verdad, <a href="https://twitter.com/#!/beoxman/status/139403030180274177">no me ha convencido demasiado</a>. Así que, por <a href="https://twitter.com/#!/albfernandez/status/139419504382967808">petición popular</a> (si por una persona se le puede llamar <em>&#8220;popular&#8221;</em>), estas son algunas de las conclusiones que he sacado, aunque si eres muy fan de C# quizás no deberías seguir leyendo <img src='http://beosman.org/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> :</p>
<h3>Declaración de tipos</h3>
<p>Extrañamemente se usan formas diferentes para declarar lo mismo. Porque declarar una variable o un nuevo tipo de dato debería ser consistente. Por ejemplo, para declarar una variable se usa <code>&lt;tipo de dato&gt; <strong>&lt;identificador&gt;</strong>;</code>. En cambio, para declarar un alias de un tipo de dato (no hay nuevos tipos) se usa <code>using <strong>&lt;identificador&gt;</strong> = &lt;tipo de dato&gt;;</code>. Y, ya para rematar, para declarar un <code><a href="">delegate</a></code> se usa <code>delegate &lt;valor devuelto&gt; <strong>&lt;identificador&gt;</strong> (&lt;parámetros&gt;);</code>.</p>
<p>¿No sería más sencillo y consistente tener una sintaxis común? Por ejemplo: <code>&lt;tipo de dato&gt; &lt;descripción&gt; <strong>&lt;identificador&gt;</strong>;</code>, con lo que la declaración quedaría:</p>
<pre>
// Variable:
int i;

// Tipo de dato:
typedef int MyInt;

// Usando 'using' (sin introducir ninguna palabra reservada adicional):
using int as MyInt;

// Delegate:
delegate void(int) MyDelegate;
</pre>
<p>Con esto la sintaxis siempre es consistente. Tenemos a la izquierda los tipos y a la derecha, siempre, el nombre tanto de la variable como del tipo nuevo como del delegate (que no deja de ser un tipo nuevo).</p>
<h3>Nuevos tipos de datos</h3>
<p>En C#, al igual que en C++, no se pueden declarar nuevos tipos de datos. Sí, en serio. Lo que estáis pensando ahora mismo es que con typedef sí se puede&#8230; pues no. En realidad es un alias del tipo básico. En C++, este código:</p>
<pre>
typedef int myint_t;
void overloaded_function(int value);
void overloaded_function(myint_t value);  // Error de compilación.
</pre>
<p>Daría error de compilación porque las dos funciones son iguales. <code>myint_t</code> no es un tipo de datos nuevo, sino un alias de <code>int</code>. En C# ocurre lo mismo, sólo que en lugar de declarar los <em>nuevos</em> tipos con <code>typedef</code> (que no tiene esa palabra reservada) se usa <code>using</code>:</p>
<pre>
using myint_t = int;

class Main {
  void overloaded_funcion(int value) {...}
  void overloaded_funcion(myint_t value) {...}  // Error de compilación.
}
</pre>
<p>También se puede hacer alguna triquiñuela, como hacer una clase <code>MyInt</code> que herede de <code>System.Int32</code>. Pero ya habría que implementar ciertas cosas para que funcionase.</p>
<h3>Los métodos y su tipo de acceso</h3>
<p>Es bastante enrevesado el uso de <code>virtual</code>, <code>override</code> y <code>new</code> para controlar el polimorfismo de las clases. Por ejemplo, en el código:</p>
<pre>
class A {
	public virtual void Who() { Console.WriteLine("A"); }
}

class B : A {
	public override void Who() { Console.WriteLine("B"); }
}

class C : B {
	public new virtual void Who() { Console.WriteLine("C"); }
}

class D : C {
	public override void Who() { Console.WriteLine("D"); }
}

C c = new D();
c.Who();	// Escribe "D"; lógico ¿no?

A a = new D();
a.Who();	// ¡Escribe "B"! ¿Dónde está la lógica de funciones virtuales aquí?
</pre>
<p>Es obligatorio que en todos los métodos que se podrán sobreescribir en clases derivadas se ponga <code>virtual</code>; que en todos los métodos que sobreescriben se ponga <code>override</code>; y que si un método oculta a otro se ponga <code>new</code>.</p>
<p>¿No sería más sencillo que todos los métodos fuesen virtuales por defecto (porque cuando haces clases, lo más probable es que las vayas a heredar)? ¿No sería más lógico que cuando declaras un método con el mismo nombre en la clase base, automáticamente se sobreescriba el de la base y, en caso de querer llamar al método de la base, uses <code>super</code>, <code>base</code> o similar?</p>
<p>Por cierto, decidme un caso <strong>real</strong> donde se use esta funcionalidad.</p>
<h3>El problema de la clase base frágil</h3>
<p>En <a href="http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/Part2.pdf">este manual se menciona el problema de la clase base frágil</a>, que habla de que en Java podría suceder esto, teniendo en principio estas clases:</p>
<pre>
class BaseClass {
	public void CleanUp() {
		System.out.println("BaseClass.CleanUp()");
	}
}

class DerivedClass extends BaseClass {
	public void Delete() {
		System.out.println("DerivedClass.Delete()");
	}
	public void CleanUp() {
		Delete();
	}
}

public class Test {
	public static void main(String[] args) {
		BaseClass k = new DerivedClass();
		k.CleanUp();
	}
}
</pre>
<p>La salida de este programa sería:</p>
<p class="terminal">
$ javac Test.java &#038;&#038; java Test<br />
DerivedClass.Delete();<br />
$
</p>
<p>Si luego implementamos el método <code>Delete()</code> en la clase base de esta forma:</p>
<pre>
class BaseClass {
	public void CleanUp() {
		System.out.println("BaseClass.CleanUp()");
	}
	public void Delete() {
		System.out.println("Delete all the world!");
	}
}
</pre>
<p>Según el manual, ¡podríamos borrar el mundo!</p>
<p>Esto sería un verdadero problema&#8230; si existiese. Pero es muy fácil comprobar que no se produce. La salida con la clase modificada es la misma que sin ella. Sólo usando <code>super.Delete()</code> se podría borrar el mundo.</p>
<h3>Ámbito global o local</h3>
<p>En C#, si una clase oculta un espacio de nombres, para acceder a dicho espacio introduce una nueva palabra que no está reservada, pero que hay que recordar: <code>global</code>. Por ejemplo:</p>
<pre>
class Main {

  public class System {}

  static void Main(string[] args) {
    System.Console.WriteLine("¡Hola mundo!");  // Error: la clase 'System' oculta
                                               // el espacio de nombres 'System'.
    global::System.Console.WriteLine("Esto sí funciona.");
  }
}
</pre>
<p>¿No sería más sencillo, en lugar de introducir otro identificador nuevo, usar sólo el operador <code>::</code>, como hace C++ o, incluso, usar el operador <code>.</code>?</p>
<h3>Comportamientos extraños de las variables</h3>
<p>Resulta que si declaras una variable de tipo <code>delegate</code>, esta se comporta como una <strong>lista</strong> de delegates que se llaman todos seguidos:</p>
<pre>

class Test {
	void Notify1(string text) {
		System.Console.WriteLine("Hello " + text);
	}
	void Notfiy2(string text) {
		System.Console.WriteLine("Goodbye " + text);
	}
}

Test test = new Test();

delegate void Notifier(string text);

Notifier notifier;
notifier = new Notifier(test.Notify1);
notifier += new Notifier(test.Notify2);

notifier("Manolito");

// La salida será:
// Hello Manolito
// Goodbye Manolito
</pre>
<p>¿Nos aclaramos? ¿<code>Notifier</code> es una variable o es una lista de variables? Y si todos los <code>delegate</code>s asignados devuelven algún valor, sólo se devuelve el último ejecutado. ¿Y el resto?</p>
<h3>Recorriendo listas</h3>
<p>C# añade el <code>foreach</code>, que no es más que lo que se conoce como <em><a href="http://en.wikipedia.org/wiki/Syntactic_sugar">syntactic sugar</a></em> para el bucle <code>for</code> de toda la vida evitando que el programador use variables índice:</p>
<pre>

string[] stringArray = new string[] { /* Inicialización */ };

foreach(var s in stringArray) {
  System.Console.WriteLn(s);
}
</pre>
<p>Pero no estoy criticando ese <em>syntactic sugar</em>, todo lo contrario, eso me parece muy bien. Cuanto menos código se escriba y haga más cosas, mejor.</p>
<p>Lo que ya no me parece tan bien es que en ese bucle <code>foreach</code> sólo se tenga acceso a los valores de la lista a recorrer y no se tenga acceso al índice de dicha lista. Sí, simplemente a la famosa <code>i</code> que se omite para que el programador escriba menos código.</p>
<p>Y por culpa de esto, en caso de necesitarla, pues tienes que declararla fuera e incrementarla manualmente. Vamos, con en un bucle <code>for</code>.</p>
<h3>Anidamiento</h3>
<p>No se permiten métodos anidados, es decir, declaración e implementación de métodos dentro de otros métodos. Sí, venga, vale, se puede “solucionar” mediante el uso de <code>delegates</code>, pero eso no es permitir métodos anidados, eso es una chapuza.</p>
<p>Y además, ya para rematar, tampoco se permite declarar estructuras ni clases dentro de métodos. Como está orientado a objetos, pues toda declaración adicional tiene que ir dentro de la clase.</p>
<p><strong>Actualización 2011-12-05</strong>: C y C++ tampoco permiten métodos anidados <a href="http://beosman.org/archivo/2011/informatica/c-sharp.html#comment-22891">como me indican en un comentario</a>. Esto lo puse porque yo los he usado para resolver algún problema, sólo que no recuerdo ni el lenguaje ni el proyecto en el que lo hice. ¿Pascal quizás?</p>
<h3>Atributos</h3>
<p>Los atributos del lenguaje también son otra cosa que está muy bien dentro de un lenguaje. Permiten extender la funcionalidad del compilador, por ejemplo, para hacer compilación condicional, controlar entre diferentes versiones o arquitecturas, marcar elementos como obsoletos… pero, me pregunto, ¿por qué la sintaxis no es coherente con el resto del lenguaje y hay que añadir triquiñuelas del estilo <code>[Conditional("Debug")]</code> al código?</p>
<h3>Conclusión</h3>
<p>Después de despotricar un poco toca una pequeña conclusión:</p>
<p>Si Microsoft tuvo la oportunidad de crear un nuevo lenguaje de programación desde cero, para ellos solos, sin que nadie se pueda meter, sin que nadie le diera lecciones, con la posibilidad de innovar, de mejorar lo que había hasta el momento ¿por qué lo ha hecho tan retorcido e incoherente? Porque sí, en serio, es retorcido. Hasta C++ —que mira que a <a href="http://es.wikipedia.org/wiki/Bjarne_Stroustrup">Bjarne Stroustrup</a> se le fue la olla cuando lo diseñó— es más consistente y coherente que C#. C# parece un batiburrilo de Java, C++ y alguna funcionalidad adicional como los <code>delegates</code> que más que ser un lenguaje nuevo es lo mismo de siempre con otro nombre. Y propietario, claro.</p>
<p>Y, bueno, de la compilación a código intermedio en lugar de a código máquina directamente ya no hablamos. Eso es una decisión que han tomado pero que tampoco es que importe demasiado. Recordemos que esta generación de código es una de las fases de compilación que se puede cambiar sin afectar a la sintaxis.</p>
<p>Concluyendo, a mi, personalmente, no me convence en absoluto. Pero claro, si quieres hacer un proyecto decente para sistemas Windows, no queda otra que hacerlo en C# o pelearte con los punteros en C++.</p>
<p>O usar <a href="http://es.wikipedia.org/wiki/Pascal_(lenguaje_de_programaci%C3%B3n)">Pascal</a> <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  .</p>
<p class="postdata">
<abbr title="Postdata">P.D.</abbr>: Yo, en realidad, soy más del <a href="http://www.d-programming-language.org">lenguaje de programación D</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/c-sharp.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Representar un número en binario en C++</title>
		<link>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html#comments</comments>
		<pubDate>Wed, 16 Nov 2011 19:01:20 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=5247</guid>
		<description><![CDATA[Puede que alguna vez en tu vida como desarrollador de software te veas en la necesidad de representar números en su forma binaria. Hay infinidad de algoritmos para ello, por eso no me voy a enrollar mucho. Aquí te muestro tres en C++: La forma sencilla e intuitiva template &#60;typename T&#62; char* ValueToBits(T value) { [...]]]></description>
			<content:encoded><![CDATA[<p>Puede que alguna vez en tu vida como desarrollador de software te veas en la necesidad de representar números en su forma binaria. Hay infinidad de algoritmos para ello, por eso no me voy a enrollar mucho. Aquí te muestro tres en <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a>:</p>
<h3>La forma sencilla e intuitiva</h3>
<pre>
template &lt;typename T&gt;
char*
ValueToBits(T value) {
	int length = sizeof(T)*8;
	char* result = new char[length];
	result[length] = '\0';
	for(int i = 0; i &lt; length; i++) {
		result[length-1-i] = (value &#038; (1 &lt;&lt; i) ? '1' : '0');
	}
	return result;
}
</pre>
<p>Este algoritmo es fácilmente adaptable a <a href="http://es.wikipedia.org/wiki/C_(lenguaje_de_programaci%C3%B3n)">C estándar</a>. Basta con quitar la plantilla, sobrecargar esta función con más versiones, una por cada tipo de dato que se quiera convertir, y usar <code><a href="http://en.wikipedia.org/wiki/C_dynamic_memory_allocation">malloc()</a></code> en lugar de <code>new</code>. Y, por supuesto, no hay que olvidarse de liberar la memoria del valor devuelto, o bien con <code>delete[]</code> si usas <code>new</code>, o bien con <code>free()</code> si usas <code>malloc()</code>.</p>
<h3>Usando <code>std::string</code>s</h3>
<p>Este algoritmo es similar al anterior pero usando <code>std::string</code>s, con lo que evitamos el uso de <code>char*</code> y la reserva manual de memoria.</p>
<pre>
#include &lt;string&gt;

using std::string;

template &lt;typename T&gt;
const string
ValueToBits(T value) {
	string result;
	for(int i = 0; i &lt; sizeof(T)*8; i++) {
		result = (value &#038; (1 &lt;&lt; i) ? "1" : "0") + result;
	}
	return result;
}
</pre>
<h3>La forma elegante</h3>
<p>Y ya que estamos en C++, ¿por qué no usar toda la potencia que nos proporciona la <abbr title="Standard Template Library" lang="en"><a href="http://en.wikipedia.org/wiki/Standard_Template_Library">STL</a></abbr>?</p>
<pre>
#include &lt;bitset&gt;

using std::bitset;

template &lt;typename T&gt;
const string
ValueToBits(T value) {
	return bitset&lt;sizeof(T)*8&gt;(value).to_string();
}
</pre>
<p>No me digáis que esta forma no es <strong>muy</strong> elegante <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/representar-un-numero-en-binario-en-cpp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>El género</title>
		<link>http://beosman.org/archivo/2011/citas/el-genero.html</link>
		<comments>http://beosman.org/archivo/2011/citas/el-genero.html#comments</comments>
		<pubDate>Fri, 02 Sep 2011 13:04:08 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Citas y frases]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4903</guid>
		<description><![CDATA[El uso de circunloquios para reflejar que se refiere a &#8220;ellos y ellas&#8221; solo tiene sentido si tu mente es tan simple como para pensar que podría estar refiriéndome a &#8220;ellos&#8221; y no a &#8220;ellas&#8221;. En un comentario de Menéame sobre la noticia de que por fin se usa el sentido común para el género [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>
El uso de circunloquios para reflejar que se refiere a <em>&#8220;ellos y ellas&#8221;</em> solo tiene sentido si tu mente es tan simple como para pensar que podría estar refiriéndome a <em>&#8220;ellos&#8221;</em> y no a <em>&#8220;ellas&#8221;</em>.
</p></blockquote>
<p class="alignright">
En un <a href="http://www.meneame.net/story/impone-masculino-generico/0003">comentario de Menéame</a> sobre la noticia de que <a href="http://www.meneame.net/story/impone-masculino-generico">por fin se usa el sentido común para el género en el lenguaje</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/citas/el-genero.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Llamadas encadenadas en C++</title>
		<link>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html#comments</comments>
		<pubDate>Wed, 24 Aug 2011 17:36:38 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=4772</guid>
		<description><![CDATA[Esta entrada llevaba tiempo en el tintero, por eso de tener algo de tiempo libre en vacaciones para dedicarlo a leer y elucubrar soluciones. Por ejemplo, aquí tenemos una prueba de concepto para tener la misma funcionalidad que el operador &#60;&#60; de C++ pero usando llamadas encadenas. Y hace (casi) lo mismo: puede enviar a [...]]]></description>
			<content:encoded><![CDATA[<p>Esta entrada llevaba tiempo en el tintero, por eso de tener algo de tiempo libre en vacaciones para dedicarlo a leer y elucubrar soluciones.</p>
<p>Por ejemplo, aquí tenemos una prueba de concepto para tener la misma funcionalidad que el operador <code>&lt;&lt;</code> de <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> pero usando llamadas encadenas. Y hace (casi) lo mismo: puede enviar a la <a href="http://es.wikipedia.org/wiki/Salida_est%C3%A1ndar">salida estándar</a> cualquier tipo de variable, incluyendo cadenas, <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_entero">números enteros</a>, <a href="http://es.wikipedia.org/wiki/N%C3%BAmero_real">números reales</a> y <a href="http://es.wikipedia.org/wiki/Booleano">booleanos</a>, sólo que con un formato de llamada diferente.</p>
<p>La implementación de la clase base, pudiendo extenderla lo que se quiera, es la siguiente:</p>
<div class="source">
<p><span class="directive">#include</span> &lt;iostream&gt;<br />
<span class="directive">#include</span> &lt;string&gt;<br />
<span class="directive">#include</span> &lt;sstream&gt;<br />
&nbsp;</p>
<p><span class="keyword">using</span> std::cout;<br />
<span class="keyword">using</span> std::endl;<br />
<span class="keyword">using</span> std::flush;<br />
<span class="keyword">using</span> std::string;<br />
<span class="keyword">using</span> std::stringstream;<br />
&nbsp;</p>
<p><span class="keyword">class</span> Stdout {<br />
  <span class="keyword">private</span>:<br />
    stringstream _buffer;<br />
  <span class="keyword">public</span>:<br />
    Stdout() : _buffer() {}<br />
    ~Stdout() {}<br />
    <span class="keyword">void</span> clear() {<br />
      _buffer.str(<span class="string">&quot;&quot;</span>);<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const char</span> c) {<br />
      string s;<br />
      s += c;<br />
      _buffer &lt;&lt; s;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const char</span>* text) {<br />
      _buffer &lt;&lt; text;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const</span> string text) {<br />
      _buffer &lt;&lt; text;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const int</span> i) {<br />
      _buffer &lt;&lt; i;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const float</span> f) {<br />
      _buffer &lt;&lt; f;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const double</span> d) {<br />
      _buffer &lt;&lt; d;<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    Stdout&#038; <span class="keyword">operator</span> () (<span class="keyword">const bool</span> b) {<br />
      _buffer &lt;&lt; (b ? <span class="string">&quot;true&quot;</span> : <span class="string">&quot;false&quot;</span>);<br />
      <span class="keyword">return</span> *<span class="keyword">this</span>;<br />
    }<br />
    <span class="keyword">void</span> flush() {<br />
      cout &lt;&lt; _buffer.str() &lt;&lt; ::flush;<br />
      clear();<br />
    }<br />
    <span class="keyword">void</span> endl() {<br />
      cout &lt;&lt; _buffer.str() &lt;&lt; ::endl;<br />
      clear();<br />
    }<br />
};</p>
</div>
<p>Y un ejemplo de funcionamiento sería:</p>
<div class="source">
<p><span class="keyword">int</span><br />
main() {<br />
  Stdout stdout;<br />
  stdout(<span class="string">&quot;Llamadas encadenadas: enteros: &quot;</span>)(42)(<span class="string">&apos;;&apos;</span>)(<span class="string">&quot; reales: &quot;</span>)(25.4)(<span class="string">&apos;;&apos;</span>)(<span class="string">&quot; y booleanos: &quot;</span>)(<span class="keyword">false</span>)(<span class="string">&apos;.&apos;</span>).endl();<br />
  <span class="keyword">return</span> 0;<br />
}</p>
</div>
<p>Siendo la salida:</p>
<p class="terminal">
$ make &amp;&amp; ./test<br />
Llamadas encadenadas: enteros: 42; reales: 25.4; y booleanos: false.<br />
$
</p>
<p>No tiene la misma funcionalidad que el operador <code>&lt;&lt;</code> porque, entre otras cosas, si se quiere añadir otro elemento imprimible habría que derivar la clase, mientras que con el operador <code>&lt;&lt;</code> bastaría con sobrecargarlo. Pero no me digáis que no es elegante ¿eh? <img src='http://beosman.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/llamadas-encadenadas-en-c.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Lazarus, el clon de Delphi para FreePascal</title>
		<link>http://beosman.org/archivo/2011/informatica/lazarus-el-clon-de-delphi-para-freepascal.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/lazarus-el-clon-de-delphi-para-freepascal.html#comments</comments>
		<pubDate>Tue, 22 Mar 2011 15:29:08 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=3976</guid>
		<description><![CDATA[En el inicio de la carrera, uno de los lenguajes que usábamos era Pascal1 porque era un lenguaje muy bueno para aprender por su sintaxis y no tan complicado como el C con los punteros (aunque también los tiene). Después, con el ansia de hacer cosas más «profesionales» descubrí Delphi allá por la versión 3, [...]]]></description>
			<content:encoded><![CDATA[<p class="aligncenter">
<a href="/uploads/2011/03/lazarus.png"><img src="/uploads/2011/03/lazarus-650x406.png" alt="IDE de Lazarus" title="IDE de Lazarus" width="650" height="406" class="alignnone size-large wp-image-3977" /></a>
</p>
<p>En el inicio de la carrera, uno de los lenguajes que usábamos era <a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_Pascal">Pascal</a><sup><a href="#nota20110322">1</a></sup> porque era un lenguaje muy bueno para aprender por su sintaxis y no tan complicado como el C con los punteros (aunque también los tiene).</p>
<p>Después, con el ansia de hacer cosas más <em>«profesionales»</em> descubrí <a href="http://es.wikipedia.org/wiki/Delphi">Delphi</a> allá por la versión 3, para tener ya aplicaciones con interfaz gráfica escritas en Pascal <em>avanzado</em> (orientado a objetos y demás).</p>
<p>Es en esta época que mezcla el estudio de la carrera con la programación en Delphi en la que soy más productivo: hice infinidad de aplicaciones, principalmente para aprender a programar (por mi cuenta, todo hay que decirlo) aunque alguna sí que se salvó y <a href="/proyectos"><del>usaba</del> uso habitualmente</a>.</p>
<p>Luego, con esto de la salida del estudio para integrarse en el mundo laboral, dejé de lado el Delphi para centrarme en&#8230; bueno, en lo que tocara en ese momento.</p>
<p>Pero ahora me he encontrado con que tengo que volver a hacer una aplicación, con interfaz gráfica (un editor de <acronym title="JavaScript Object Notation" lang="en"><a href="http://es.wikipedia.org/wiki/JSON">JSON</a></acronym> principalmente aunque algo <em>especial</em>) y tiene que funcionar tanto en Windows como en Linux. En su momento probé Java pero necesitaba dos librerías que había que distribuir con el <code>*.jar</code>, así que le volví a dar una oportunidad al Pascal, aunque esta vez de la mano de <a href="http://es.wikipedia.org/wiki/Lazarus">Lazarus</a> y <a href="http://es.wikipedia.org/wiki/Free_Pascal">FreePascal</a>.</p>
<p>¿Y por qué FreePascal/Lazarus? Pues porque me ha sorprendido muy gratamente que el código fuente se compila y ejecuta sin ningún cambio en Windows y Linux (obviamente son ejecutables distintos pero un sólo código fuente). No hay que preocuparse en ningún momento de directivas de compilación, de hacer diferente código para diferentes sistemas operativos y basta con distribuir un sólo ejecutable.</p>
<p>Además, la interfaz gráfica es totalmente coherente con la interfaz general del sistema sin ningún cambio en el código. Si estás en Linux tienes los temas de Linux y si estás en Windows tienes los temas de Windows. Incluso <a href="http://wiki.lazarus.freepascal.org/Aero_Glass">con los efectos de Windows 7</a>.</p>
<p>Cierto es que hay lenguajes más <em>&#8220;modernos&#8221;</em> como Python, pero digamos que Python y yo no somos muy amigos. Y pongo <em>&#8220;modernos&#8221;</em> entre comillas porque en realidad no importa la modernidad del lenguaje: <a href="http://es.wikipedia.org/wiki/C_(lenguaje_de_programaci%C3%B3n)">C</a> es de 1972, <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> de 1980 y <a href="http://es.wikipedia.org/wiki/Cobol">Cobol</a> (el lenguaje que usan muchísimos sistemas bancarios) es de 1960.</p>
<p>En definitiva, si queréis desarrollar rápido una aplicación y habéis hecho vuestros pinitos en Pascal/Delphi hace sus años, Lazarus es una buena opción. Eso sí, no le pidáis peras al olmo porque esto es para lo que es: desarrollo rápido pero casi sin planificación y con un código un poco <em>spaghetti</em> (es lo que tiene el <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_dirigida_por_eventos">desarrollo dirigido a eventos</a>). Y tened en cuenta también que esta experiencia no os servirá para mucho más. Aún así a mi me está resolviendo la papeleta de una forma muy&#8230; <em>elegante</em> <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p id="nota20110322" style="color: gray;">
<strong>Nota</strong>: Considero que Pascal es un lenguaje de programación excelente para aprender a programar porque abstrae mucho más que C y similares de los entresijos de la arquitectura del ordenador centrando la atención en los algoritmos y en las estructuras de datos. Y lo mismo pienso de la programación orientada a objetos: no se debería ver hasta tener una buena base de programación estructura y, ni mucho menos, iniciarse en la programación usando <acronym title="Programación Orientada a Objetos">POO</acronym>. Y parece que <a title="Barrapunto: La Universidad Carnegie-Mellon elimina la programación OO de su primer curso" href="http://barrapunto.com/articles/11/03/22/0530213.shtml">esto último no soy el único que lo piensa</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/lazarus-el-clon-de-delphi-para-freepascal.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Lanzar excepciones de forma polimórfica en C++</title>
		<link>http://beosman.org/archivo/2011/informatica/lazar-excepciones-de-forma-polimorfica-en-cpp.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/lazar-excepciones-de-forma-polimorfica-en-cpp.html#comments</comments>
		<pubDate>Thu, 24 Feb 2011 19:17:42 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=3854</guid>
		<description><![CDATA[Otro de mis ladrillos sobre C++. Esta vez sobre lanzamiento de excepciones polimórficas en C++ sobre Linux. Vamos al lío: Para ponernos en antecedentes, digamos que tenemos una aplicación multihilo escrita en C++ en Linux. Cuando en uno de los hilos se produce una excepción, esta debe ser atrapada (try { ... } catch(...) { [...]]]></description>
			<content:encoded><![CDATA[<p>Otro de mis ladrillos sobre C++. Esta vez sobre lanzamiento de excepciones polimórficas en C++ sobre Linux. Vamos al lío:</p>
<p>Para ponernos en antecedentes, digamos que tenemos una aplicación multihilo escrita en C++ en Linux. Cuando en uno de los hilos se produce una excepción, esta debe ser atrapada (<code>try { ... } catch(...) { ... }</code>) dentro del propio hilo. En caso de que no se haga así, la excepción se propaga al hilo principal (<code>main()</code>) sin posibilidad de atraparla, con lo que la aplicación finaliza.</p>
<p>Para resumir este punto: las excepciones no se propagan entre diferentes hilos de ejecución por lo que hay que atraparlas y procesarlas dentro del propio hilo.</p>
<p>Pero ¿qué pasa cuando queremos que una excepción sí se propague a otros hilos? Es decir, que un error que se produce en un hilo se notifique a otro hilo para que tome medidas. Por ejemplo, tenemos un hilo que gestiona las comunicaciones y otro que gestiona la interfaz. Cuando se produce un error de comunicación es la interfaz la que tiene que notificar al usuario de dicho error.</p>
<p>Soluciones existen varias. Una de ellas es enviar un mensaje con la excepción que se produce al hilo que la procesa aunque hay que tener en cuenta que debe haber una arquitectura de paso de mensajes entre hilos previa.</p>
<p>Por ejemplo, en pseudocódigo, el hilo de comunicaciones:</p>
<div class="source">
<p><span class="keyword">void</span><br />
hilo_comunicaciones() {<br />
  <span class="keyword">while</span>(mensaje = cola_mensajes.getMensaje()) {<br />
    <span class="keyword">try</span> {<br />
      enviar_mensaje(mensaje);<br />
      mensaje = recibir_respuesta();<br />
    } <span class="keyword">catch</span>(Exception&#038; e) {<br />
      notificar_interfaz(e);<br />
    }<br />
  }<br />
}</p>
</div>
<p>Y ahora el hilo de proceso de las notificaciones en la interfaz:</p>
<div class="source">
<p><span class="keyword">void</span><br />
hilo_proceso_notificaciones_error_comunicaciones(Exception&#038; e) {<br />
  <span class="keyword">try</span> {<br />
    <span class="keyword">throw</span> e;<br />
  } <span class="keyword">catch</span>(ComunicationException&#038; e) {<br />
    <span class="comment">// procesar excepciones relativas a la conexión</span><br />
  } <span class="keyword">catch</span>(TimeOutException&#038; e) {<br />
    <span class="comment">// procesar excepciones relativas al fallo de la conexión por tiempo</span><br />
  } <span class="keyword">catch</span>(ProtocolException&#038; e) {<br />
    <span class="comment">// procesar excepciones por errores de protocolo</span><br />
  } <span class="keyword">catch</span>(&#8230;) {<br />
    <span class="comment">// procesar excepciones generales</span><br />
  }<br />
}</p>
</div>
<p>El problema del proceso de procesado de excepciones en la interfaz es que al relanzar la excepción que se recibe como parámetro (<code>throw e;</code>) esta no es la excepción recibida en el hilo de comunicaciones, es decir, no hay polimorfismo por lo que siempre se procesa como una excepción general en lugar de la correspondiente.</p>
<p>La opción de usar <code>typeid(e).name()</code> en la excepción para procesar su tipo no es viable porque es demasiado costosa (el operador <code>typeid</code> es bastante costoso) y porque el nombre de la excepción no es estándar, esto es, en GNU C++ (g++) el nombre está <em>&#8220;retorcido&#8221;</em>, <em><a href="http://en.wikipedia.org/wiki/Name_mangling">mangled</a></em> en inglés.</p>
<p>La opción recomendable es añadir a la excepción base de tu aplicación, teniendo en cuenta que para tu aplicación has desarrollado una jerarquía de excepciones acorde con su funcionalidad, <a href="http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.16">un método virtual que implementen las excepciones derivadas</a> donde, simplemente, se lancen a sí mismas.</p>
<p>Un código de ejemplo sería el siguiente:</p>
<div class="source">
<p><span class="comment">// Excepción base de la jerarquía de excepciones de mi aplicación</span><br />
<span class="keyword">class</span> Exception : <span class="keyword">public</span> runtime_error {<br />
  <span class="keyword">public</span>:<br />
    Exception(<span class="keyword">const</span> string msg) : runtime_error(msg) {}<br />
    <span class="keyword">virtual</span> <span class="keyword">void</span> raise() { <span class="keyword">throw</span> *<span class="keyword">this</span>; }<br />
};</p>
<p><span class="comment">// Excepción que se lanza cuando hay un error de acceso denegado</span><br />
<span class="keyword">class</span> AccessDeniedException : <span class="keyword">public</span> Exception {<br />
  <span class="keyword">public</span>:<br />
    AccessDeniedException(<span class="keyword">const</span> string msg) : Exception(msg) {}<br />
    <span class="keyword">virtual</span> <span class="keyword">void</span> raise() { <span class="keyword">throw</span> *<span class="keyword">this</span>; }</p>
<p>};</p>
<p><span class="comment">// Resto de excepciones derivadas conforme a los</span><br />
<span class="comment">// errores que se quieren notificar</span></p>
</div>
<p>Con esta forma de declarar las excepciones, el código de gestión de las notificaciones de error en la interfaz quedaría:</p>
<div class="source">
<p><span class="keyword">void</span><br />
hilo_proceso_notificaciones_error_comunicaciones(Exception&#038; e) {<br />
  <span class="keyword">try</span> {<br />
    <strong>e.raise();</strong><br />
  } <span class="keyword">catch</span>(ComunicationException&#038; e) {<br />
    <span class="comment">// procesar excepciones relativas a la conexión</span><br />
  } <span class="keyword">catch</span>(TimeOutException&#038; e) {<br />
    <span class="comment">// procesar excepciones relativas al fallo de la conexión por tiempo</span><br />
  } <span class="keyword">catch</span>(ProtocolException&#038; e) {<br />
    <span class="comment">// procesar excepciones por errores de protocolo</span><br />
  } <span class="keyword">catch</span>(&#8230;) {<br />
    <span class="comment">// procesar excepciones generales</span><br />
  }<br />
}</p>
</div>
<p>Con lo que funcionaría sin ningún problema ya que <a href="http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.16">la excepción se lanza de forma polimórfica</a> al usar un método virtual en la clase base que implementan todas las clases derivadas.</p>
<p>Para hacer una prueba se puede <a href="/download/exception-test.cpp">descargar un archivo con un programa de ejemplo</a> (1,4 <abbr title="Kilobytes">KB</abbr>). Para compilarlo basta con ejecutar el comando <code>g++ -o test exception-test.cpp</code>.</p>
<p>Y por ir un poco más allá, se podría pensar que para implementar todas las excepciones que usa una aplicación habría que escribir bastante código, además, la mayoría sería repetido; lo único que cambiaría sería el nombre de la excepción y del constructor, el resto es todo igual.</p>
<p>Bueno, pues para eso están las <a href="http://es.wikipedia.org/wiki/Preprocesador_de_C">macros de C</a>: se puede crear una macro a la que se le pase como parámetro el nombre de tu nueva excepción y que ella genere todo el código restante. Pero no olvidéis que <a href="http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5">las macros son <em>malignas</em> en 4 formas diferentes</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/lazar-excepciones-de-forma-polimorfica-en-cpp.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Clases en C++ con constructores con parámetros variables (variadic functions)</title>
		<link>http://beosman.org/archivo/2011/informatica/clases-en-cpp-con-constructores-con-parametros-variables-variadic-functions.html</link>
		<comments>http://beosman.org/archivo/2011/informatica/clases-en-cpp-con-constructores-con-parametros-variables-variadic-functions.html#comments</comments>
		<pubDate>Fri, 21 Jan 2011 17:10:47 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=3660</guid>
		<description><![CDATA[Tanto C como C++ tienen la característica, mediante macros, de crear funciones con un número indefinido de argumentos. Esto es lo que se conoce como variadic functions. Un ejemplo de una función en C con argumentos variables sería el siguiente: #include &#60;stdarg.h&#62; int variadic_function(int arg_count,...) { va_list arg_list; va_start(arg_list,arg_count); int i, sum; for(i = 0; [...]]]></description>
			<content:encoded><![CDATA[<p>Tanto <a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_C">C</a> como <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> tienen la característica, mediante <a href="http://en.wikipedia.org/wiki/Macro_(computer_science)">macros</a>, de crear funciones con un número indefinido de argumentos. Esto es lo que se conoce como <em><a href="http://en.wikipedia.org/wiki/Variadic_function">variadic functions</a></em>.</p>
<p>Un ejemplo de una función en C con argumentos variables sería el siguiente:</p>
<div class="source">
<p><span class="directive">#include &lt;stdarg.h&gt;</span></p>
<p><span class="keyword">int</span><br />
variadic_function(<span class="keyword">int</span> arg_count,<span>.</span><span>.</span><span>.</span>) {<br />
  va_list arg_list;<br />
  va_start(arg_list,arg_count);<br />
  <span class="keyword">int</span> i, sum;<br />
  <span class="keyword">for</span>(i = 0; i &lt; arg_count; i++) {<br />
    sum += va_arg(arg_list,int);  <span class="comment">// acciones con el argumento</span><br />
  }<br />
  <span class="keyword">return</span> sum;<br />
}</p>
</div>
<p>Para declarar una función que tenga un número indefinido de argumentos es necesario incluir los puntos suspensivos (&#8230;) como argumento, pero al menos debe tener uno que no sea indefinido, esto es, primero un argumento y, posteriormente, los puntos suspensivos. Esto es así porque en la función <code>va_start()</code> hay que pasarle, como segundo argumento, el nombre del último argumento conocido de la función. Si no tuviese al menos un argumento conocido no se podría pasar este argumento a la función <code>va_start()</code>.</p>
<p>También se pueden crear métodos (funciones dentro de clases) que tengan la lista de argumentos variable, incluidos los constructores de las clases, de la forma:</p>
<div class="source">
<p><span class="keyword">class</span> MyClass {<br />
  <span class="keyword">public</span>:<br />
    MyClass(<span>.</span><span>.</span><span>.</span>);<br />
};</p>
</div>
<p>Y dirán ustedes ¿y aquí por qué no se pone al menos un argumento como nos acabas de indicar?</p>
<p>Y yo voy a responder con otra pregunta: ¿qué es lo que te enseñan el primer día de curso de programación orientada a objetos sobre los métodos de una clase? Que los métodos no estáticos de una clase tienen un argumento implícito que es un puntero a la instancia de dicha clase. El famoso puntero <code>this</code> en lenguajes como C++, <a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_Java">Java</a>, <a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_D">D</a> y alguno que otro más.</p>
<p>Y como este argumento es el primero del método, se puede pasar sin problemas como segundo argumento de la función <code>va_start()</code> para indicar que es el último definido de la lista. La implementación sería, más o menos, así:</p>
<div class="source">
<p><span class="directive">#include &lt;cstdarg&gt;</span></p>
<p><span class="keyword">using namespace</span> std;</p>
<p><span class="directive">#include &quot;MyClass.hpp&quot;</span></p>
<p>MyClass::MyClass(<span>.</span><span>.</span><span>.</span>) {<br />
  <span class="keyword">int</span> size = <em>X</em>;  <span class="comment">// el tamaño lo tenemos que tener especificado de alguna forma</span><br />
  <span class="keyword">int</span> sum = 0;<br />
  va_list arg_list;<br />
  va_start(arg_list,<strong><span class="keyword">this</span></strong>);<br />
  <span class="keyword">for</span>(<span class="keyword">int</span> i = 0; i &lt; size; i++) {<br />
    sum += va_arg(arg_list,<span class="keyword">int</span>);<br />
  }<br />
  va_end(arg_list);<br />
}</p>
</div>
<p>Esto de los argumentos indefinidos en C y C++ es una de las <em>chapuzas</em> que hay para tener esta funcionalidad ya que, en su mayoría, se hace con macros (aunque están implementadas de forma interna al compilador).</p>
<p>Hasta que no tengamos el estándar <a href="http://es.wikipedia.org/wiki/C%2B%2B0x">C++0x</a> (el nuevo estándar de C++ que supongo que ya quedará poco para que salga definitivamente) no tendremos esta característica incluida en el lenguaje. Incluso se ha ampliado a <a href="http://en.wikipedia.org/wiki/Variadic_templates">parámetros variables en las plantillas (<em>variadic templates</em>)</a>, con lo que podremos tener <a href="http://es.wikipedia.org/wiki/Tupla">tuplas</a> de <em>n</em> elementos de distinto tipo. Pero, de momento, nos conformaremos <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2011/informatica/clases-en-cpp-con-constructores-con-parametros-variables-variadic-functions.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Contra la tontuna lingüística un poco de gramática bien explicada</title>
		<link>http://beosman.org/archivo/2010/lenguajes/contra-la-tontuna-linguistica-un-poco-de-gramatica-bien-explicada.html</link>
		<comments>http://beosman.org/archivo/2010/lenguajes/contra-la-tontuna-linguistica-un-poco-de-gramatica-bien-explicada.html#comments</comments>
		<pubDate>Wed, 10 Nov 2010 19:55:23 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Humor]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=3104</guid>
		<description><![CDATA[Yo no soy víctima de la LOGSE. Tengo 48 años y he tenido la suerte de estudiar bajo unos planes educativos buenos, que primaban el esfuerzo y la formación de los alumnos por encima de las estadísticas de aprobados y de la propaganda política. En párvulos (así se llamaba entonces lo que hoy es &#8220;educación [...]]]></description>
			<content:encoded><![CDATA[<div style="font-style:italic;">
<p>Yo no soy víctima de la <acronym title="Ley Orgánica de Ordenación General del Sistema Educativo de España"><a href="http://es.wikipedia.org/wiki/LOGSE">LOGSE</a></acronym>. Tengo 48 años y he tenido la suerte de estudiar bajo unos planes educativos buenos, que primaban el esfuerzo y la formación de los alumnos por encima de las estadísticas de aprobados y de la propaganda política.</p>
<p>En párvulos (así se llamaba entonces lo que hoy es &#8220;educación infantil&#8221;) empecé a estudiar con una cartilla que todavía recuerdo perfectamente: la A de &#8220;araña&#8221;, la E de &#8220;elefante&#8221;, la I de &#8220;iglesia&#8221; la O de &#8220;ojo&#8221; y la U de &#8220;uña&#8221;.</p>
<p>Luego, cuando eras un poco más mayor, llegaba &#8220;El Parvulito&#8221;, un librito con poco más de 100 páginas y un montón de lecturas, no como ahora, que pagas por tres tomos llenos de dibujos que apenas traen texto. Eso sí, en “El Parvulito”, no había que colorear ninguna página, que para eso teníamos cuadernos.</p>
<p>En 8º de EGB, si en un examen tenías una falta de ortografía del tipo de &#8220;b en vez de v&#8221; o cinco faltas de acentos, te suspendían.</p>
<p>En BUP, aunque yo era de Ciencias, estudié Historia de España (en 1º), Latín y Literatura (en 2º) y Filosofía (en 3º y en COU). </p>
<p>Leí El Quijote y el Lazarillo de Tormes; leí las &#8220;Coplas a la Muerte de su Padre&#8221; de Jorge Manrique, a Garcilaso, a Góngora, a Lope de Vega o a Espronceda&#8230;</p>
<p>Pero, sobre todo, aprendí a hablar y a escribir con corrección. Aprendí a amar nuestra lengua, nuestra historia y nuestra cultura.</p>
<p>Aprendí que se dice &#8220;Presidente&#8221; y no Presidenta, aunque sea una mujer la que desempeñe el cargo.</p>
<p>Y&#8230; vamos con la Gramática.</p>
<p>En castellano existen los participios activos como derivado de los tiempos verbales.</p>
<p>El participio activo del verbo atacar es &#8220;atacante&#8221;; el de salir es &#8220;saliente&#8221;; el de cantar es &#8220;cantante&#8221; y el de existir, &#8220;existente&#8221;. ¿Cuál es el del verbo ser? Es &#8220;el ente&#8221;, que significa &#8220;el que tiene entidad&#8221;, en definitiva &#8220;el que es&#8221;. Por ello, cuando queremos nombrar a la persona que denota capacidad de ejercer la acción que expresa el verbo, se añade a este la terminación &#8220;-nte&#8221;.</p>
<p>Así, al que preside, se le llama &#8220;presidente&#8221; y nunca &#8220;presidenta&#8221;, independientemente del género (masculino o femenino) del que realiza la acción.</p>
<p>De manera análoga, se dice &#8220;capilla ardiente&#8221;, no &#8220;ardienta&#8221;; se dice &#8220;estudiante&#8221;, no &#8220;estudianta&#8221;; se dice &#8220;independiente&#8221; y no &#8220;independienta&#8221;; &#8220;paciente&#8221;, no &#8220;pacienta&#8221;; &#8220;dirigente&#8221;, no dirigenta&#8221;; &#8220;residente&#8221;, o &#8220;residenta&#8221;.</p>
<p>Y ahora, la pregunta del millón: nuestros políticos y muchos periodistas (hombres y mujeres, que los hombres que ejercen el periodismo no son &#8220;periodistos&#8221;) ¿hacen mal uso de la lengua por motivos ideológicos o por ignorancia de la Gramática de la Lengua Española? Creo que por las dos razones.</p>
<p>Es más, creo que la ignorancia les lleva a aplicar patrones ideológicos y la misma aplicación automática de esos patrones ideológicos los hace más ignorantes (a ellos y a sus seguidores).</p>
<p>Os propongo que paséis el mensaje a vuestros amigos y conocidos, en la esperanza de que llegue finalmente a esos ignorantes semovientes (no &#8220;ignorantas semovientas&#8221;, aunque ocupen carteras ministeriales).</p>
<p>Lamento haber aguado la fiesta a un grupo de hombres que se habían asociado en defensa del género y que habían firmado un manifiesto.</p>
<p>Algunos de los firmantes eran: el dentisto, el poeto, el sindicalisto, el pediatro, el pianisto, el golfisto, el arreglisto, el funambulisto, el proyectisto, el turisto, el contratisto, el paisajisto, el taxisto, el artisto, el periodisto, el violinisto, el taxidermisto, el telefonisto, el masajisto, el gasisto, el trompetisto, el violinisto, el maquinisto, el electricisto, el oculisto, el policío del esquino y, sobre todo, ¡el machisto!</p>
</div>
<p style="color:gray;">
Carta de una profesora de música de un instituto que me ha llegado por correo. Seguro que está en mil sitios, pero esto siempre es bueno recordarlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2010/lenguajes/contra-la-tontuna-linguistica-un-poco-de-gramatica-bien-explicada.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Llamadas a métodos protegidos desde clases externas en C++</title>
		<link>http://beosman.org/archivo/2010/informatica/llamadas-a-metodos-protegidos-desde-clases-externas-en-cpp.html</link>
		<comments>http://beosman.org/archivo/2010/informatica/llamadas-a-metodos-protegidos-desde-clases-externas-en-cpp.html#comments</comments>
		<pubDate>Thu, 23 Sep 2010 19:56:31 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=2801</guid>
		<description><![CDATA[Seguro que esta solución ya está implementada por ahí pero yo no la he encontrado. Para ponernos en antecedentes, tenemos una clase Thread en C++ que representa hilos de ejecución. Esta clase tiene un método execute() que es el que realmente ejecuta el hilo. De esta se puede heredar para implementar dicho método y que [...]]]></description>
			<content:encoded><![CDATA[<p>Seguro que esta solución ya está implementada por ahí pero yo no la he encontrado.</p>
<p>Para ponernos en antecedentes, tenemos una clase <code>Thread</code> en <a href="http://es.wikipedia.org/wiki/C%2B%2B">C++</a> que representa <a href="http://es.wikipedia.org/wiki/Hilo_de_ejecuci%C3%B3n">hilos de ejecución</a>. Esta clase tiene un método <code>execute()</code> que es el que realmente ejecuta el hilo. De esta se puede heredar para implementar dicho método y que este se ejecute en un hilo independiente. La clase <code>Thread</code> cuenta con <a href="http://es.wikipedia.org/wiki/Herencia_%28inform%C3%A1tica%29#Herencia_y_ocultaci.C3.B3n_de_informaci.C3.B3n">métodos protegidos (<em>protected</em>)</a> para que sólo los usen las clases derivadas.</p>
<p>Pero, además de derivar la clase <code>Thread</code>, esta clase tiene una clase anidada llamada <code>Thread::Worker</code> que también se puede derivar con la ventaja de que se pueden pasar muchas instancias de <code>Thread::Worker</code> a una sola instancia de la clase <code>Thread</code> para que las ejecute.</p>
<p>El problema surge cuando desde la clase <code>Thread::Worker</code>, al igual que desde las subclases de <code>Thread</code>, se desea acceder a los métodos protegidos (que, en teoría, son sólo para ayudar en la funcionalidad de las clases derivadas). Inicialmente esto no es posible ya que no se puede acceder a métodos protegidos de una clase si no es desde la propia clase o desde clases derivadas, no importa si son clases anidadas, a efectos de protección, son como clases externas.</p>
<p>Con algunas omisiones de código, la implementación de las clases es la siguiente:</p>
<div class="source">
<p><span class="comment">/* Clase Thread (gestión de hilos) */</span></p>
<p><span class="keyword">class</span> Thread {<br />
  [...]<br />
  <span class="keyword">public</span>:</p>
<p>    <span class="comment">/* Clase Worker (tareas que se ejecutan en los hilos) */</span></p>
<p>    <span class="keyword">class</span> Worker {<br />
      <span class="keyword">protected</span>:<br />
        Thread * <span class="keyword">const</span> getOwnerThread() <span class="keyword">const</span>;<br />
      <span class="keyword">public</span>:<br />
        <span class="keyword">virtual</span> <span class="keyword">void</span> execute();<br />
      <span class="comment">[...]</span><br />
    };</p>
<p>  <span class="keyword">private</span>:<br />
    Worker* _worker;<br />
    <span class="comment">[...]</span><br />
  <span class="keyword">protected</span>:<br />
    <span class="keyword">bool</span> isThreadRunning();<br />
    <span class="keyword">virtual</span> <span class="keyword">void</span> execute();<br />
    <span class="comment">[...]</span><br />
  <span class="keyword">public</span>:<br />
    Thread(Worker* worker) : _worker(worker) {<br />
      <span class="comment">// Al añadir el Worker que asigna el hilo al que pertenece</span><br />
      _worker-&gt;_owner = <span class="keyword">this</span>;<br />
    }<br />
    <span class="comment">[...]</span><br />
  [...]<br />
};</p>
<p><span class="comment">/* Clase MyThread derivada de Thread */</span></p>
<p><span class="keyword">class</span> MyThread : <span class="keyword">public</span> Thread {<br />
  <span class="keyword">protected</span>:<br />
    <span class="keyword">virtual</span> <span class="keyword">void</span> execute() {<br />
      <span class="keyword">while</span>(isThreadRunning()) {  <span class="comment">// llamada correcta porque esta función es protegida en la clase padre</span><br />
        <span class="comment">// hacer las cosas del hilo</span><br />
      }<br />
    }<br />
};</p>
<p><span class="comment">/* Clase MyWorker derivada de Thread::Worker */</span></p>
<p><span class="keyword">class</span> MyWorker : <span class="keyword">public</span> Thread::Worker {<br />
  <span class="keyword">protected</span>:<br />
    <span class="keyword">virtual</span> <span class="keyword">void</span> execute() {<br />
      <span class="keyword">while</span>(getOwnerThread()-&gt;isThreadRunning()) {  <span class="comment">// llamada incorrecta porque esta función es protegida en la clase Thread, que no es la clase padre</span><br />
        <span class="comment">// hacer las cosas del hilo</span><br />
      }<br />
    }<br />
}</p>
<p><span class="comment">/* Función de entrada de la aplicación */</span></p>
<p><span class="keyword">int</span><br />
main() {<br />
  MyThread* mt = <span class="keyword">new</span> MyThread();  <span class="comment">// correcto</span><br />
  Thread* t = <span class="keyword">new</span> Thread(<span class="keyword">new</span> MyWorker());  <span class="comment">// incorrecto, no se pueden llamar a funciones protegidas desde fuera de la clase</span><br />
  <span class="keyword">return</span> 0;<br />
}</p>
</div>
<p>La funcionalidad deseada es que la clase <code>Thread::Worker</code> se comporte como la clase <code>Thread</code> cuando se hacen clases derivadas de ella, para poder usar la funcionalidad de gestión de la clase <code>Thread</code> desde la clase <code>Thread::Worker</code> (las funciones protegidas).</p>
<p>Pero al compilador no le gusta que se llamen funciones protegidas desde clases externas aunque sean anidadas.</p>
<p>La solución pasa por crear un puntero a método en la clase anidada que sea asignado a la función que hay que ejecutar. Cuando la instancia de la clase <code>Thread::Worker</code> es añadida a la instancia de la clase <code>Thread</code>, esta última asigna las direcciones de memoria de sus métodos a las variables internas de la clase <code>Thread::Worker</code>, con lo que una llamada mediante dichos punteros funcionará sin problemas y ejecutará el método protegido de la clase <code>Thread</code> desde la clase externa <code>Thread::Worker</code>.</p>
<p>La implementación sería, más o menos de la siguiente forma:</p>
<div class="source">
<p><span class="keyword">class</span> Thread {<br />
  <span class="comment">[...]</span><br />
  <span class="keyword">public</span>:<br />
    <span class="keyword">typedef</span> <span class="keyword">bool</span> (Thread::*ThreadMethod1)();</p>
<p>    <span class="keyword">class</span> Worker {<br />
      <span class="comment">[...]</span><br />
      <span class="keyword">private</span>:<br />
        ThreadMethod1 _isThreadRunning;<br />
      <span class="keyword">protected</span>:<br />
        <span class="keyword">bool</span> isThreadRunning() {<br />
          <span class="keyword">return</span> (getOwnerThread()-&gt;*_isThreadRunning)();<br />
        }<br />
      <span class="comment">[...]</span><br />
    };</p>
<p>    Thread(Worker* worker) : _worker(worker) {<br />
      _worker-&gt;_owner = <span class="keyword">this</span>;<br />
      _worker-&gt;_isThreadRunning = &amp;Thread::isThreadRunning;<br />
    }</p>
<p>   <span class="comment">[...]</span><br />
}</p>
</div>
<p>Con esto se consigue que la clase <code>Thread::Worker</code> se comporte, a efectos de derivación de clases, como si se derivase de la clase <code>Thread</code>. Hay que tener en cuenta que las clases derivadas de la clase <code>Thread::Worker</code> siempre se tienen que añadir a una instancia de la clase <code>Thread</code> para todo funcione correctamente.</p>
<p>Como es bastante difícil interpretar código fuente desde esta lectura, he preparado <a title=".tar.gz (32 KB)" href="/download/protected.tar.gz">una pequeña aplicación en C++</a> para mostrar el funcionamiento de este tipo de solución.</p>
<p>Espero que esto sirva para alguien a parte de mi. Y si lo encontráis por algún otro sitio me lo comentáis, porque como he dicho al principio, seguro que no soy el primero en hacerlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2010/informatica/llamadas-a-metodos-protegidos-desde-clases-externas-en-cpp.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>17 pequeñas notas sobre programación en C++</title>
		<link>http://beosman.org/archivo/2010/informatica/17-pequenas-notas-sobre-programacion-en-c.html</link>
		<comments>http://beosman.org/archivo/2010/informatica/17-pequenas-notas-sobre-programacion-en-c.html#comments</comments>
		<pubDate>Mon, 10 May 2010 14:59:18 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/?p=1897</guid>
		<description><![CDATA[C++ no es C. Usa el que más te convenga en cada momento. Si programas en C++, usa su librería estándar, STL, siempre que puedas. No reinventes la rueda, si necesitas mayor funcionalidad, usa librerías que la proporcionen y que estén en un estado de madurez suficiente, como la librería boost. No se recomienda que [...]]]></description>
			<content:encoded><![CDATA[<ol>
<li><a href="http://es.wikipedia.org/wiki/C++">C++</a> no es <a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_C">C</a>. Usa el que más te convenga en cada momento.</li>
<li>Si programas en C++, usa su librería estándar, <acronym title="Standard Template Library" lang="en"><a href="http://es.wikipedia.org/wiki/C%2B%2B#Biblioteca_Est.C3.A1ndar_de_Plantillas_.28STL.2C_Standard_Template_Library.29">STL</a></acronym>, siempre que puedas.</li>
<li>No reinventes la rueda, si necesitas mayor funcionalidad, usa librerías que la proporcionen y que estén en un estado de madurez suficiente, como la librería <a href="http://es.wikipedia.org/wiki/Biblioteca_Boost"><code>boost</code></a>.</li>
<li>No se recomienda que los <em>castings</em> se hagan de forma implícita o de la forma que lo hace C. Se recomienda usar su nueva sintaxis: <code>static_cast</code>, <code>dynamic_cast</code>, <code>const_cast</code> y <code>reinterpret_cast</code>.</li>
<li>Un <em>casting</em> con <code>static_cast</code> se evalúa en tiempo de compilación y es el más parecido al <em>casting</em> implícito de C. Se usa para convertir un tipo de dato en otro.</li>
<li>Un <em>casting</em> con <code>dynamic_cast</code> se usa para hacer <em>castings</em> en tiempo de ejecución pero <strong>sólo</strong> para objetos polimórficos, esto es, para recorrer la jerarquía de clases. No funcionará con tipos básicos.</li>
<li>Un <em>casting</em> con <code>const_cast</code> no cambia de tipo sino que cambia los modificadores <code>const</code> y <code>volatile</code>.</li>
<li>Un <em>casting</em> con <code>reinterpret_cast</code> se usa para hacer cambios de tipo a nivel de bits, es decir, para convertir entre tipos totalmente distintos.</li>
<li>Una función dentro de una clase que tenga el modificador <code>const</code> (por ejemplo <code>void MiClase::MiFuncion() const { ... }</code>) no modifica el contenido del objeto (no modifica los campos del objeto). Esto se usa para ejecutar funciones dentro de instancias constantes.</li>
<li>Una función virtual pura debe ser declarada como <code>virtual</code> e igualada a cero dentro de la clase: <code>virtual void MiFuncionVirtualPura() = 0;</code>. Este tipo de funciones <strong>deben</strong> ser implementadas en las clases derivadas. Además, no se pueden instanciar clases que tengan funciones virtuales puras.
</li>
<li>Las variables miembro (propiedades) estáticas de una clase deben ser <strong>definidas</strong> fuera de la clase para que funcionen correctamente (si no se definen así, el error lo produce el <a href="http://es.wikipedia.org/wiki/Linker">linker</a>: <code>Undefined reference to MiClase::count</code>):
<pre>
class MiClase {
	public:
		static int count;
}

int MiClase::count = 0;
</pre>
</li>
<li>Las clases y funciones con plantillas se deben declarar e implementar en el mismo archivo ya que, como el código se genera en tiempo de compilación, si se declara en un <code>.h</code> y se implementa en un <code>.cpp</code>, es el <em>linker</em> el que no encuentra el código generado. <a href="http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12">Hay más soluciones</a>, pero ninguna es buena del todo.</li>
<li>Usa el sistema de gestión de excepciones de C++ y evita en lo posible el uso de valores de retorno indicando errores y sentencias <code>if</code> ya que son mucho más propensas a errores.</li>
<li>Las excepciones deben representar el error que se produce, no quién las lanza o desde donde se lanzan.</li>
<li>Siempre que puedas, usa objetos creados en el <code><a href="http://es.wikipedia.org/wiki/Pila_%28inform%C3%A1tica%29">stack</a></code> en lugar de en el <code><a href="http://es.wikipedia.org/wiki/Heap">heap</a></code>. Con esto evitarás <em><a href="http://es.wikipedia.org/wiki/Memory_leak">fugas de memoria</a></em> (<em>memory leak</em> en inglés) ya que los objetos se destruyen cuando finaliza el ámbito de los mismos.</li>
<li>Usa herramientas automatizadas para probar y depurar las aplicaciones (como <code><a href="http://es.wikipedia.org/wiki/Valgrind">valgrind</a></code> para fugas de memoria).</li>
<li>Nunca confies en que lo has revisado todo.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2010/informatica/17-pequenas-notas-sobre-programacion-en-c.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Palabras con &#8220;ch&#8221;</title>
		<link>http://beosman.org/archivo/2009/lenguajes/palabras-con-ch.html</link>
		<comments>http://beosman.org/archivo/2009/lenguajes/palabras-con-ch.html#comments</comments>
		<pubDate>Thu, 10 Dec 2009 22:37:12 +0000</pubDate>
		<dc:creator>Diego</dc:creator>
				<category><![CDATA[Humor]]></category>
		<category><![CDATA[Lenguajes]]></category>

		<guid isPermaLink="false">http://beosman.org/archivo/2009/lenguajes/palabras-con-ch.html</guid>
		<description><![CDATA[Esta es la entrada tonta del día que, gracias a que se ha presentado la Nueva Gramática de la Lengua Española, se me ocurrió poner todas las palabras bisílabas que sólo utilizasen la extinta letra che, hoy la ce hache: chacha, chachi, chacho, cheche, Chechu, chicha, chiche, chichi, chicho, chocha, chocho, chuche, chucha y chucho. [...]]]></description>
			<content:encoded><![CDATA[<p>Esta es la entrada tonta del día que, gracias a que <a href="http://www.e-consulta.com/index.php?option=com_content&#038;task=view&#038;id=42274&#038;Itemid=282">se ha presentado la Nueva Gramática de la Lengua Española</a>, se me ocurrió poner todas las palabras bisílabas que sólo utilizasen la extinta letra <q><em>che</em></q>, hoy la <em>ce hache</em>:</p>
<blockquote style="font-size: 1.2em;"><p>
<a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chacha&#038;TIPO_HTML=2">chacha</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chachi&#038;TIPO_HTML=2">chachi</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chacho&#038;TIPO_HTML=2">chacho</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=cheche&#038;TIPO_HTML=2">cheche</a>, <span style="border-bottom:1px dotted;" title="Diminutivo de nombre propio; acuérdense de Médico de Familia">Chechu</span>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chicha&#038;TIPO_HTML=2">chicha</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chiche&#038;TIPO_HTML=2">chiche</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chichi&#038;TIPO_HTML=2">chichi</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chicho&#038;TIPO_HTML=2">chicho</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chocha&#038;TIPO_HTML=2">chocha</a>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chocho&#038;TIPO_HTML=2">chocho</a>, <span style="border-bottom:1px dotted;" title="Diminutivo de Chuchería">chuche</span>, <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chucha&#038;TIPO_HTML=2">chucha</a> y <a href="http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=chucho&#038;TIPO_HTML=2">chucho</a>.
</p></blockquote>
<p>Al final han salido 14, aunque algunas no están en el <a href="http://buscon.rae.es">diccionario de la RAE</a>, pero seguro que a nadie se le escapa el significado. Además, tampoco he contado las que tienen más vocales o consonantes entre estas. Ahora sólo se me ocurre <q>Chencho</q> (el hijo pequeño de <a href="http://es.wikipedia.org/wiki/La_gran_familia">La gran familia</a>). ¿Alguna más?</p>
<p>Y hasta aquí ha llegado la entrada chorra del día <img src='http://beosman.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://beosman.org/archivo/2009/lenguajes/palabras-con-ch.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

