Contenido

Guía básica de programación en jC 2

1Introducción 2

2Programa de ejemplo: ¡Hola, Mundo! 2

3Entrada y Salida 2

3.1Cadenas 3

3.2Enteros 3

3.3Reales 3

4Manejo de cadenas de caracteres 4

4.1Copiar una cadena de caracteres 5

4.2Concatenar dos cadenas 5

4.3Pasar el contenido de una cadena a mayúsculas o minúsculas 6

4.4Pasar un número a cadena 6

5Paso de parámetros 7

5.1Paso de parámetros por valor 7

5.2Paso de parámetros por referencia 8

5.3Paso de vectores y matrices 9












Guía básica de programación en jC

1Introducción

Durante todo el libro, se empleará el lenguaje de programación jC. Este lenguaje de programación cuenta con muchas posibilidades, ya que además de definir sus propias extensiones, incluye una variante de C más exigente con el cumplimiento del sistema de tipos que el C original.

Específicamente, no se utilizan las capacidades de C++ para programación orientada a objetos, sino sólo la parte que da soporte al paradigma de programación estructurada.

jC permite ocultar una buena parte de las características más complejas de C, mientras otras se pueden utilizar tal cuál se hacía en C. A continuación se enumeran sus características más básicas.

2Programa de ejemplo: ¡Hola, Mundo!

El típico programa de ejemplo, ¡Hola, mundo!, se muestra a continuación.


import std.io;

import std.util;


int main()

{

println( "¡Hola, Mundo!" );

return ExitSuccess;

}


La directiva import permite utilizar módulos (es decir, otras funciones), que si llevan el prefijo std se corresponden con la librería estándar. En este caso, std.io se corresponde con la entrada y salida estándar, necesarias para poder utilizar println(). Esta función visualiza la cadena pasada por parámetro por la pantalla. Finalmente, se retorna ExitSuccess, obtenido de std.util, que se corresponde con el final del programa “sin novedad”, es decir, con éxito.

Es necesario resaltar que la ejecución en jC siempre comienza en la primera instrucción de la función main().

3Entrada y Salida

La entrada y salida se realiza mediante las funciones readln() y print()/write() o println()/writeln(), respectivamente.

En cuanto a la petición de datos, se realiza con readln(), que devuelve siempre una cadena de caracteres (un vector de caracteres o char[]).

En cuanto a la salida de datos, se le puede pasar a print()/write() cualquier tipo de variable, y visualizará su valor por pantalla. La diferencia entre print o write y sus contrapartidas terminadas en ln es que estas realizarán automáticamente un salto de línea. Las funciones println() y writeln() sin parámetro alguno realizan un salto de línea. Como puede deducirse, write() y print() son funciones equivalentes, realizando exactamente la misma tarea.


import std.io;

import std.util;

import std.math;


int main()

{

print( "PI tiene un valor de: " );

println( PI );


return ExitSuccess;

}


3.1Cadenas

Las cadenas se piden mediante la función readln(), y se muestran mediante la función print() o println(). Una cadena en jC no es más que un vector de caracteres, representado por el tipo char[].


/**

* @name Presentame

* @author jbgarcia@uvigo.es

*/


import std.util;

import std.io;


int main()

{

char[] nombre = readln( "Dame tu nombre: " );


print( "Hola desde jC, " );

println( nombre );


return ExitSuccess;

}

3.2Enteros

Los números enteros (se designan como int), deben leerse con readln(), como una cadena, al igual que el resto de tipos en jC. Para convertir una cadena a número entero, y viceversa se utilizan las funciones strToInt() e intToStr(), respectivamente.


/**

* @name Nombre y edad

* @author jbgarcia@uvigo.es

*/


import std.util;

import std.io;

import std.string;


int main()

{

char[] nombre = readln( "Dame tu nombre: " );

int edad = strToInt( readln( "Dame tu edad: " ) );


print( "Hola desde jC, " );

print( nombre );

print( " tienes " );

print( edad );

println( " años." );


return ExitSuccess;

}

3.3Reales

Los números flotantes (se designan como double) deben leerse con readln(), como una cadena, al igual que el resto de tipos en jC. Para convertir una cadena a número flotante, y viceversa se utilizan las funciones strToDbl() y dblToStr(), respectivamente.


/**

* @name Conversor de euros

* @author jbgarcia@uvigo.es

*/


import std.util;

import std.io;

import std.string;


final double ValorEuroEnPesetas = 166.386;


int main()

{

double cantidad = strToDbl( readln( "Dame una cantidad en euros: " ) );


print( "En pesetas es: " );

println( cantidad * ValorEuroEnPesetas );


return ExitSuccess;

}

4Manejo de cadenas de caracteres

Las cadenas de caracteres no son en realidad más que vectores del tipo char, es decir, char[]. Mediante la función size(), que se puede obtener de la biblioteca estándar, concretamente de std.util, se puede obtener el número de caracteres presentes en la cadena. No se usa ningún carácter extra de fin de cadena ni nada por el estilo: el tamaño del vector de caracteres es también el tamaño de la cadena.


/**

* @name DemoCadena

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;


int main()

{

char[] cadHola = new char[4];

char[] cadAdios = "Hasta luego";

cadHola[ 0 ] = 'H';

cadHola[ 1 ] = 'o';

cadHola[ 2 ] = 'l';

cadHola[ 3 ] = 'a';

char[] cadBueno = new char[]{ 'B', 'u', 'e', 'n', 'o' };

// Ver la cadena 'hola'

print( "Longitud: " );

print( size( cadHola ) );

print( ": " );

println( cadHola );

// Ver la cadena 'Bueno'

print( "Longitud: " );

print( size( cadBueno ) );

print( ": " );

println( cadBueno );

// Ver la cadena 'hasta luego'

print( "Longitud: " );

print( size( cadAdios ) );

print( ": " );

println( cadAdios );

return ExitSuccess;

}


Los módulos relevantes de la biblioteca estándar son std.string, que proporciona todas las funciones que tienen que ver con el manejo de cadenas de caracteres, y std.chtype, que proporciona todas las funciones relevantes cuando se trata de manejar caracteres que forman parte de cadenas de caracteres.

4.1Copiar una cadena de caracteres

Las copias de las cadenas de caracteres las realiza la función strCopy(), que admite sólo un parámetro: el vector de caracteres a copiar, devolviendo un nuevo vector con exactamente la misma secuencia de caracteres.


/**

* @name CopiaCadena

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;


int main()

{

char[] cadena = "Hola desde jC!";

char[] cadena2;


cadena2 = strCopy( cadena );

println( cadena2 );


return ExitSuccess;

}

4.2Concatenar dos cadenas

Dos vectores de caracteres se pueden concatenar mediante la función strConcat(), que admite dos parámetros. El primero es el primer vector de caracteres, que actuará también como destino. El segundo es un literal de cadena u otro vector de caracteres, que se copiará a continuación del último carácter ocupado en el primer vector de caracteres. Nótese que debe haber suficiente espacio en el primer vector de caracteres para su propia contenido concatenado con la segunda cadena y el cero de fin de cadena.


/**

* @name ConcatenaCadena

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;


int main()

{

char[] cadena = "Hola ";

char[] cadena2 = "desde jC!";


println( strConcat( cadena, cadena2 ) );


return ExitSuccess;

}

4.3Pasar el contenido de una cadena a mayúsculas o minúsculas

No existe una función que permita convertir una cadena a mayúsculas o minúsculas, aunque las funciones toupper() y tolower(), definidas en el módulo cctype, permiten construir fácilmente sendas funciones. Como ejemplo, se indica a continuación cómo pasar una cadena a minúsculas.


/**

* @name minsCadena

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;

import std.charType;


/**

* @brief Pasa una cadena a mins.

* @param org La cadena a pasar a mins.

* @return Una nueva cadena, como org, pero en mins.

*/

char[] strMins(char[] org)

{

int max = size( org );

char[] toret = new char[ max ];


for(int i = 0; i < max; ++i) {

toret[ i ] = toLowerCase( org[ i ] );

}


return toret;

}


int main()

{

char[] cadena = readln( "Introduzca una cadena: " );


println( strMins( cadena ) );


return ExitSuccess;

}

4.4Pasar un número a cadena

En ocasiones es necesario realizar una conversión antagónica a la que se ha venido haciendo hasta ahora: pasar un número entero, almacenado en una variable de tipo entero (int), a una cadena cuyos caracteres estén compuestos por los dígitos del número.


/*

* @name cnvtNumero

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;


int main()

{

int numero;

char[] strNum;


// Pedir el número (implica cnvt. desde cadena)

numero = strToInt( readln( "Dame un número: " ) );

print( "El num. es: " );

println( numero );


// Pasar el número a una cadena, y visualizarlo

strNum = intToStr( numero );

print( "El número era " );

println( strNum );


return ExitSuccess;

}

5Paso de parámetros

jC soporta dos tipos de paso de parámetros: por valor (también denominado por copia, en ocasiones), y por referencia. Al contrario que en muchos lenguajes, no se indica un tipo u otro de ninguna manera, sino que el tipo de paso de parámetros depende de la variable que está siendo pasada.

5.1Paso de parámetros por valor

El paso de parámetros por valor se utiliza cuando se le quiere símplemente pasar un dato a una función o procedimiento, sin que los cambios a dicho dato sean repercutidos en la función que llama. Es el tipo de paso de parámetros más simple.

Para cualquier tipo, el paso de parámetros por valor consiste básicamente en poner el nombre del tipo y el nombre del parámetro formal a continuación. Para su invocación, se indica el nombre de la variable o un valor literal.


/** @name Calculo Factorial

* @author jbgarcia@uvigo.es

*/

import std.io;

import std.util;

import std.string;

int factorial(int n)

{

int resultado = n;

// Calcula el factorial, decreciendo hasta 1

--n;

while( n > 0 ) {

resultado *= n;


--n;


}


return resultado;

}

int main()

{

int x = strToInt( readln( "Introduzca valor para factorial: " ) );

print( "\nEl factorial es: " );

println( factorial( x ) );

return ExitSuccess;

}

En el ejemplo anterior, que muestra el cálculo iterativo del factorial, se puede apreciar cómo se usa el paso de parámetro por valor para n en la función factorial(). Aunque el valor de n cambia dentro de la función factorial, ese cambio no se refleja en la función llamadora, que es main(). De hecho, la variable de la que n toma el valor es x en main(). Y su valor continúa siendo el mismo cuando la ejecución retorna desde factorial(). Tal y como indica el nombre de este tipo de paso de parámetros, de x sólo se toma su valor para copiarlo en n.

Sólo los tipos básicos (es decir, int, bool, char, double) utilizan, de forma automática este tipo de paso de parámetros. Los tipos complejos, como los vectores y matrices, no pueden utilizar este tipo de paso de parámetros.

5.2Paso de parámetros por referencia

El paso de parámetros por referencia se utiliza cuando se le quiere pasar una variable a una función o procedimiento, de manera que los cambios que se le hagan a esa variable dentro de la función sean repercutidos después en el resto del programa. Este tipo de paso de parámetros sólo está disponible para tipos complejos, como por ejemplo los vectores y matrices (incluyendo, al ser vectores, las cadenas de caracteres, char[]). Para los tipos simples: int, bool, char, double, el paso de parámetros se hace siempre por valor.


/**

* @name minsCadena

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;

import std.charType;


/**

* @brief Pasa una cadena a mins.

* @param org La cadena a pasar a mins.

* @return Una nueva cadena, como org, pero en mins.

*/

char[] strMins(char[] org)

{

int max = size( org );

char[] toret = new char[ max ];


for(int i = 0; i < max; ++i) {

toret[ i ] = toLowerCase( org[ i ] );

}


return toret;

}


int main()

{

char[] cadena = readln( "Introduzca una cadena: " );


println( strMins( cadena ) );


return ExitSuccess;

}

En el ejemplo anterior, la cadena, al ser un vector de caracteres, se pasa por referencia a la función strMins(), de forma que los cambios que se hacen en su contenido (de hecho, todos sus caracteres son pasados a minúsculas) se ven reflejados en la función llamadora, que en este caso es main().

Nótese que en el caso del paso de parámetros por valor, es posible utilizar literales para el parámetro real, mientras que para el paso de parámetros por referencia utilizar un literal no tiene sentido.

5.3Paso de vectores y matrices

Como se ha visto, los tipos complejos, como los vectores y matrices, siempre se pasan por referencia, y no se puede elegir que su paso sea por valor. En el caso en que su valor desee conservarse, lo único que se puede hacer es una copia del contenido de la cadena, para trabajar sobre dicha copia en lugar de sobre la variable original.


/*

* @name contarPuntuacion

* @author jbgarcia@uvigo.es

*/


import std.io;

import std.util;

import std.string;

import std.charType;


/**

@brief Cuenta los caracteres de puntuacion en una cadena

@param cadena La cadena de la que contar los caracters

@return El num. de caracteres de puntuacion.

*/

int contarPuntuacion(char[] cadena)

{

int toret = 0;

char[] copia = strCopy( cadena );


// Convertir todo los signos de puntuacion a espacios

for(int i = 0; i < size( copia ); ++i) {

if ( isPunctuation( copia[ i ] ) ) {

copia[ i ] = ' ';

}

}


// Contar los espacios

for(i = 0; i < size( copia ); ++i) {

if( isSpace( copia[ i ] ) ) {

++toret;

}

}


return toret;

}


int main()

{

char[] cad = readln( "Dame una cadena: " );


// Pasar el num. a una cadena, y visualizarlo

print( "El número de caracteres de puntuación es: " );

println( contarPuntuacion( cad ) );


return ExitSuccess;

}


En el ejemplo anterior, se cuentan los signos de puntuación (incluyendo espacios), convirtiendo todos los signos de puntuación encontrados (, . ; : …) a espacios, y después contando todos los espacios, en una segunda pasada. Dado que ello implica modificar la cadena, se hace primeramente una copia de la cadena original, y se trabaja sobre ella, por lo que, aunque haya sido pasada por referencia (cosa que no se puede elegir), la cadena pasada desde main() nunca va a verse modificada tras la ejecución de contarPuntuacion().