1. C Sharp
C# (pronunciado si sharp en inglés) es un lenguaje de programaciónorientado a
objetos desarrollado y estandarizado por Microsoft como parte de su plataforma .NET,
que después fue aprobado como un estándar por la ECMA (ECMA-334)
e ISO (ISO/IEC 23270). C# es uno de los lenguajes de programación diseñados para
la infraestructura de lenguaje común.
Su sintaxis básica deriva de C/C++ y utiliza el modelo de objetos de la plataforma
.NET, similar al de Java, aunque incluye mejoras derivadas de otros lenguajes.
El nombre C Sharp fue inspirado por la notación musical, donde '#' (sostenido, en
inglés sharp) indica que la nota (C es la nota do en inglés) es un semitono más alta,
sugiriendo que C# es superior a C/C++. Además, el signo '#' se compone de cuatro
signos '+' pegados.1
Aunque C# forma parte de la plataforma .NET, ésta es una API, mientras que C# es
un lenguaje de programación independiente diseñado para generar programas sobre
dicha plataforma. Ya existe un compilador implementado que provee el marco Mono -
DotGNU, el cual genera programas para distintas plataformas
como Windows,Unix, Android, iOS, Windows Phone, Mac OS y GNU/Linux.
Tipos de datos
C# contiene dos categorías generales de tipos de datos integrados: tipos de
valor y tipos de referencia. El término tipo de valor indica que esos tipos contienen
directamente sus valores.
Tipos para definir números enteros:
Tipo de datos de enteros
Tipo EquivalenteBCL Tamaño Rango Significado
byte System.Byte
8-bit (1-
byte)
0 a 255
Entero sin
signo
sbyte System.SByte
8-bit (1-
byte)
-128 a 127
Entero con
signo
2. short System.Int16
16-bit (2-
byte)
-32.768 a 32.767
Entero corto
con signo
ushort System.UInt16
16-bit (2-
byte)
0 a 65.535
Entero corto
sin signo
int System.Int32
32-bit (4-
byte)
-2.147.483.648 a 2.147.483.647
Entero medio
con signo
uint System.UInt32
32-bit (4-
byte)
0 a 4.294.967.295
Entero medio
sin signo
long System.Int64
64-bit (8-
byte)
-9.223.372.036.854.775.808 a
9.223.372.036.854.775.807
Entero largo
con signo
ulong System.UInt64
64-bit (8-
byte)
0 a 18.446.744.073.709.551.615
Entero largo
sin signo
Los tipos de coma flotante pueden representar números con componentes fraccionales.
Existen dos clases de tipos de coma flotante: float y double. El tipo double es el más
utilizado porque muchas funciones matemáticas de la biblioteca de clases de C# usan
valores double. Quizá, el tipo de coma flotante más interesante de C# es decimal,
dirigido al uso de cálculos monetarios. La aritmética de coma flotante normal está sujeta a
una variedad de errores de redondeo cuando se aplica a valores decimales. El
tipo decimal elimina estos errores y puede representar hasta 28 lugares decimales.
Tipo de datos de coma flotante
Tipo Equivalente BCL
Tamañ
o
Rango
Significad
o
float System.Single
32-bit
(4-byte)
±1.401298E−45 a ±3.402823E+38
Coma
flotante
corto
3. double System.Double
64-bit
(8-byte)
±4.94065645841246E−324 a
±1.79769313486232E+308
Coma
flotante
largo
decima
l
System.Decima
l
128-bit
(16-
byte)
−7.922816251426433759354395033
5 a
+7.922816251426433759354395033
5
Coma
flotante
monetario
Los caracteres en C# no tienen un tamaño de 8 bits como en otros muchos lenguajes de
programación, sino que usa un tamaño de 16 bits llamado Unicode al cual se le
llama char. No existen conversiones automáticas de tipo entero achar.
Tipo de datos de caracteres
Tipo Equivalente BCL Tamaño Rango Significado
char System.Char 16-bit (2-byte) 'u0000' a 'uFFFF' Carácter unicode
Para los tipos de datos lógicos no existen conversiones automáticas de tipo entero
a bool.
Tipo de datos lógicos
Tipo Equivalente BCL Tamaño Rango Significado
bool System.Boolean 8-bit (1-byte) true o false Verdadero o falso
OPERADORES
C es un lenguaje muy rico en operadores. Se definen seis tipos de operadores
aritméticos, relacionales, de asignación, lógicos, de dirección y de movimiento.
4. Operadores lógicos
§1 Sinopsis
Los operadores lógicos producen un resultado booleano, ( 3.2.1b), y sus operandos
son también valores lógicos o asimilables a ellos (los valores numéricos son asimilados
a cierto o falsosegún su valor sea cero o distinto de cero). Por contra, recuerde que las
operaciones entre bits ( 4.9.3) producen valores arbitrarios.
Los operadores lógicos son tres; dos de ellos son binarios, el último (negación) es unario.
Tienen una doble posibilidad de representación en el Estándar C++ actual: la
representación tradicional que se indica a continuación, y la natural introducida
recientemente que se detalla más adelante .
Y lógico && AND
O lógico || OR
Negación lógica ! NOT
Las expresiones conectadas con los operadores && y || se evalúan de izquierda a
derecha, y la evaluación se detiene tan pronto como el resultado verdadero o falso es
conocido (muchos programas tienen una lógica que se basa en este propiedad).
§2 && Operador Y lógico
También denominado por su nombre en inglés (generalmente en mayúsculas) AND
lógico. Devuelve un valor lógico true si ambos operandos son ciertos. En caso contrario el
resultado es false.
Sintaxis
expr-AND-logica && expresion-OR-inclusive
Comentario:
La operatoria es como sigue: El primer operando (de la izquierda) es convertido a bool.
Para ello, si es una expresión, se evalúa para obtener el resultado (esta computación
puede tener ciertos efectos laterales). A continuación, el valor obtenido es convertido
a bool cierto/falso siguiendo las reglas de conversión estándar ( 3.2.1b). Si el resultado
es false, el proceso se detiene y este es el resultado, sin que en este caso sea necesario
evaluar la expresión de la derecha (recuérdese que en el diseño de C++ prima la
velocidad).
Si el resultado del operando izquierdo es cierto, se continúa con la evaluación de la
expresión de la derecha, que también es convertida a bool. Si el nuevo resultado es true,
entonces el resultado del operador es true. En caso contrario el resultado es false.
5. Nota: la Norma informa que antes de ser evaluada la expresión derecha, han
sucedido todos los posibles efectos laterales de la expresión izquierda, a excepción
de la destrucción de los posibles objetos temporales que se hubiesen creado.
Ejemplo:
int m[3] = {0,1,2};
int x = 0;
if (m && x) cout<< "Cierto.";
elsecout<< "Falso.";
Salida:
Falso.
El valor m, que es interpretado como un puntero al primer elemento de la matriz, es
transformado a un bool. Como es distinto de cero (no es un puntero nulo) el resultado es
cierto. A continuación, el valor x es convertido también a bool. En este caso la conversión
produce falso, con lo que este es el resultado del paréntesis de la sentencia if.
Ejemplo
#include<iostream.h>
bool alto = true, bajo = false, blanco = true, negro = false;
intmain (void) {
if (alto && bajo) { cout<< "Uno cierto" <<endl; }
elsecout<< "Uno falso" <<endl;
if (alto && blanco) { cout<< "Dos cierto" <<endl; }
elsecout<< "Dos falso" <<endl;
if (bajo && negro) { cout<< "Tres cierto" <<endl; }
elsecout<< "Tres falso" <<endl;
}
Salida:
Uno falso
Dos cierto
Tres falso
§3 || Operador O lógico
Este operador binario devuelve true si alguno de los operandos es cierto. En caso
contrario devuelve false.
Sintaxis
expr-OR-logica || expresion-AND-logica
6. Comentario
Este operador sigue un funcionamiento análogo al anterior. El primer operando (izquierdo)
es convertido a bool. Para ello, si es una expresión, se evalúa para obtener el resultado
(esta computación puede tener ciertos efectos laterales). A continuación el valor obtenido
es convertido a bool cierto/falso siguiendo las reglas de conversión estándar ( 3.2.1b).
Si el resultado estrue, el proceso se detiene y este es el resultado, sin que en este caso
sea necesario evaluar la expresión de la derecha (recuérdese que en el diseño de C++
prima la velocidad).
Si el resultado del operando izquierdo es false, se continúa con la evaluación de la
expresión de la derecha, que también es convertida a bool. Si el nuevo resultado es true,
entonces el resultado del operador es true. En caso contrario el resultado es false.
Nota: el Estándar establece que antes de ser evaluada la expresión derecha, han
sucedido todos los posibles efectos laterales de la expresión izquierda, a excepción
de la destrucción de los posibles objetos temporales que se hubieran creado.
Ejemplo
#include<iostream.h>
bool alto = true, bajo = false, blanco = true, negro = false;
intmain (void) {
if (alto || bajo) { cout<< "Uno cierto" <<endl; }
elsecout<< "Uno falso" <<endl;
if (alto || blanco) { cout<< "Dos cierto" <<endl; }
elsecout<< "Dos falso" <<endl;
if (bajo || negro) { cout<< "Tres cierto" <<endl; }
elsecout<< "Tres falso" <<endl;
}
Salida
Uno cierto
Dos cierto
Tres falso
§4 ! Operador NO lógico:
Este operador es denominado también negación lógica y se representa en el texto escrito
por la palabra inglesa NOT (otros lenguajes utilizan directamente esta palabra para
representar el operador en el código).
Sintaxis
! expresion-cast
Comentario
7. El operando expresion-cast (que puede ser una expresión que se evalúa a un
resultado 1.2.1) es convertido a tipo bool, con lo que solo puede ser uno de los
valores cierto/falso. A continuación el operador cambia su valor: Si es cierto es
convertido a falso y viceversa.
Resulta por tanto, que el resultado de este operador es siempre un tipo bool, aunque al
existir una conversión estándar por la que un cero es convertido a false, y cualquier valor
distinto de cero atrue ( 3.2.1b), coloquialmente se dice que este operador convierte un
operando 0 en 1 y uno no-cero en 0. En otras palabras: este operador devuelve cierto
(true) si la expresión se evalúa a distinto de cero, en caso contrario devuelve falso (false).
Ejemplo
#include<iostream.h>
bool alto = true, bajo = false;
intmain (void) {
if (alto) { cout<< "Uno cierto" <<endl; }
elsecout<< "Uno falso" <<endl;
if (!alto) { cout<< "Dos cierto" <<endl; }
elsecout<< "Dos falso" <<endl;
if (!bajo) { cout<< "Tres cierto" <<endl; }
elsecout<< "Tres falso" <<endl;
}
Salida:
Uno cierto
Dos falso
Tres cierto
Si E es una expresión, !E es equivalente a (0 == E). Como consecuencia, las expresiones
que siguen son equivalentes dos a dos:
if (! valid);
if (valid == 0);
...
if (valid);
if (valid != 0);
§7 Representación explícita
Los operadores lógicos entre valores lógicos &&, ||, !; la relación de desigualdad !=;
algunos de los operadores lógicos entre bits (&, |, ^, ~) y sus expresiones compuestas
(&=, |=, ^=), tienen una representación realmente difícil de leer, con la desventaja
adicional que sus símbolos no siempre están fácilmente accesibles en ordenadores con
teclados distintos del estándar USA. Para resolver este problema, el Estándar C++ ha
introducido nuevas formas para su representación; las denominamos formas explícitas o
8. naturales, en razón de que se parecen más a las palabras correspondientes del lenguaje
natural. Las nuevas formas constituyen palabras-clave, y la tabla de equivalencias es la
siguiente:
Palabra
clave
Símbolo Referencia Descripción
and && Operador Y lógico
or || Operador O lógico
not ! Operador negación lógica
bitand & 4.9.3 Operador AND entre bits
xor ^ 4.9.3 Operador OR exclusivo entre bits
bitor | 4.9.3 Operador OR inclusivo entre bits
compl ~ 4.9.3
Operador complemento a uno de
bits
and_eq &= 4.9.3
Asignación compuesta (AND entre
bits)
xor_eq ^= 4.9.3
Asignación compuesta (XOR entre
bits)
or_eq |= 4.9.3
Asignación compuesta (OR entre
bits)
not_eq != 4.9.12 Operador relacional de desigualdad
Nota: ni el compilador Borland C++ 5.5 ni MS VC++ 6.0 soportan esta característica del
estándar, aunque el de Microsoft anuncia en su documentación que pueden utilizarse
"defines" ( 4.9.10b). Por ejemplo:
#define bitand&
#define bitor |
#define and_eq&=
#define or_eq |=
#define not_eq !=
Por su parte, el compilador GNU gcc dispone de la opción de compilación -fno-operator-
names, que permite que las palabras-clave and, bitand, bitor, compl, not, y or, no sean
tratadas como sinónimos de los operadores correspondientes.
9.
Operadores aritméticos
§1 Sinopsis
Los operadores aritméticos se usan para realizar cálculos de aritmética de números
reales y de aritmética de punteros. C++ dispone de los siguientes:
+ Dos posibilidades: Suma binaria ; más unitario .
++ Incremento unitario (dos clases )
- Dos posibilidades: Resta binaria ; menos unitario .
-- Decremento unitario (dos clases )
* Multiplicación (este símbolo tiene también otros usos )
/ División .
% Resto o módulo .
Nota: la aritmética de números reales es la clásica de la escuela primaria. La de
punteros es una aritmética un tanto especial y rudimentaria ( 4.2.2).
§2 Observaciones
Los operadores aritméticos pertenecen a dos grupos: unos aceptan operandos de tipo
numérico; otros aceptan operandos de tipo puntero-a-tipoX [3]. Además son de dos
tipos; unarios (que aceptan un solo operando) y binarios (que aceptan dos). La
clasificación es la siguiente:
Operadores aritméticos unarios:
+ más unitario.
++ Incremento unitario (dos clases)
- menos unitario.
-- Decremento unitario (dos clases)
Operadores artiméticosbinaros:
+ Suma binaria.
- Resta binaria.
* Multiplicación
/ División.
% Resto o módulo.
Estos últimos pueden combinarse con el de asignación = para dar origen a operadores
compuestos ( 4.9.2) son los siguientes:
10. += Asigna suma
-= Asigna diferencia (resta)
*= Asigna producto
/= Asigna división
%= Asigna resto (módulo)
Tenga en cuenta que existen distintos operadores enmascarados bajo los mismos
símbolos + y -. Es un caso de sobrecarga incluida en el propio lenguaje [1]. Como en el
resto de los casos de sobrecarga, el compilador deduce por el contexto de que versión del
operador se trata. Como veremos inmediatamente, en C++ es perfectamente válida una
expresión del tipo:
int x = *ptr+-*++ptr;
En el ejemplo siguiente se muestran los casos posibles:
intai[] = {2, 3};
int* ptr = ai;
int r1 = +ai[0]; // L.3: más unitario sobre tipo numérico
int r2 = -ai[1] // L.3: menos unitario sobre tipo
numérico
int r3 = ai[0] + ai[1]; // L.4: 2 + 3 suma binaria (de enteros)
int r4 = ai[1] - ai[0] // L.5: 3 - 2 resta binaria (de enteros)
int r5 = ai[0] + -ai[1]; // L.6: 2 +(-3) suma binaria seguida de
menos unitario
int r6 = *ptr + -*++ptr; // L.7: Suma binaria (de enteros) a + (-
b)
En L.7 coexisten tres operadores aritméticos no homogéneos (de izquierda a derecha):
+ Suma binaria entre valores numéricos tipo int ( ). Los valores *ptr y -*++ptr
- Negación unitaria de un valor numérico tipo int ( ); el valor *(++ptr)
++ Preincremento de un puntero-a-int ( ). Equivale a suma binaria de puntero y
entero: ++ptr == ptr = ptr + 1
Nota: aunque válida, la sentencia de L.7 es un ejemplo de expresión peligrosa y
desaconsejada. En 4.9.0a se ha presentado una explicación del sorpresivo
resultado ( 0 ) que se obtiene para L.6.
§3 Suma y resta binaria
En el primer caso: suma y resta binaria, caben dos posibilidades sintácticas:
a- expresión-suma + expresión-de-multiplicación
11. b- expresión-suma - expresión-de-multiplicación
§3.1 Operador Suma binaria
Las posibilidades para los operandos en la expresión A + B son los siguientes:
1. A y B son tipos aritméticos, enteros o fraccionarios ( 2.2.1). En este caso ambos
operandos están sujetos a las posibles conversiones aritméticas estándar (
2.2.5) y el resultado es la suma aritmética de ambos. Ejemplo:
int x = 10, y = 20;
int z = x + y; // z == 30
2. A es un entero y B es un puntero a objeto. Ejemplo:
intarr[5] = {1, 2, 3, 4, 5};
int* ptr = &arr[0]; // Señala a 1
int x = *(2 + ptr); // x == 3
3. A es un puntero a objeto y B es un entero. En estos dos últimos casos se aplican
las reglas de aritmética de punteros ( 4.2.2). Ejemplo:
int z = *(ptr + 3); // x == 4
§3.2 Operador Resta binaria.
Las posibilidades para los operandos en la expresión A - B son los siguientes:
1. A y B son de tipo aritmético, entero o fraccionario; las posibilidades son las
mismas que en el caso 1 de la suma binaria expuesta anteriormente. El resultado
es la resta aritmética de ambos operandos. Ejemplo:
int x = 10, y = 20;
int z = x - y; // z == -10
2. A y B son punteros a objetos de tipos compatibles. Ejemplo:
intarr[5] = {1, 2, 3, 4, 5};
int* pt1 = &arr[0]; // Señala a 1
int* pt2 = &arr[4]; // Señala a 5
int x = pt2 - pt1; // x == 4
3. A es un puntero a objeto y B es un entero. En estos dos últimos casos se aplican
las reglas de aritmética de punteros ( 4.2.2). Ejemplo:
12. intarr[5] = {1, 2, 3, 4, 5};
int* ptr = &arr[4]; // señala a 5
int x = *(ptr - 2); // x == 3
§4 Operadores ± Unitarios
Cuando los operadores + y - se utilizan como operadores unitarios, las posibilidades
sintácticas son:
+ <expresión-cast>
- <expresión-cast>
En ambos casos <expresión-cast> debe ser de tipo numérico. Los resultados son
respectivamente:
Valor del operando expresión-cast después de cualquier promoción interna
que sea necesaria.
Valor negativo del operando expresión-cast después de cualquier promoción
interna que se necesite.
Nota: recuerde que cuando + y - se utilizan como operadores unitarios, tienen mayor
precedencia que cuando se utilizan como suma y resta binarias ( 4.9.0a).
Ejemplo
int x = 7, y = 3;
int r1 = - (y - x); // r1 == 4
int r2 = + (y - x); // r2 == -4
int r3 = - (x - y); // r3 == -4
int r4 = + (x - y); // r4 == 4
§5 Operadores multiplicación y división
Los operadores binarios * (multiplicación) y / (división) realizan sus operaciones
aritméticas correspondientes con todos los tipos numéricos (enteros y fraccionarios).
Sintaxis
expresión-de-multiplicación * expresión-cast
expresión-de-multiplicación / expresión-cast
§6 Operador módulo
El operador binario % (operador de módulo) devuelve el resto de la división de
dos enteros, no puede ser utilizado con números fraccionarios float o double [2].
13. Sintaxis
expresión-de-multiplicación % expresión-cast
Ejemplo
int resto = (6 % 4);
cout<< "El resto de 6/4 es " << resto <<endl;
Salida:
El resto de 6/4 es 2
§7 Operadores incremento y decremento
Los operadores unitarios ++ (incremento) y -- (decremento), suman y restan
respectivamente una unidad al valor de la expresión. Existen dos variedades "Pre" y
"Post" para cada uno de ellos.
Las posibilidades sintácticas son:
postfix-expression ++ (postincremento)
++ expresión-unitaria (preincremento)
postfix-expression -- (postdecremento)
-- expresión-unitaria (predecremento)
En los ejemplos que siguen suponemos que originariamente n == 5.
El postincremento añade uno a la expresión después de que se ha evaluado:
x = n++ ; // -> x == 5 y n == 6
El preincremento añade uno antes de que sea evaluada la expresión.
x = ++n ; // -> x == 6 y n == 6
El postdecremento resta uno del valor de la expresión después de que sea evaluada.
x = n-- ; // -> x == 5 y n == 4
El predecremento resta uno antes de la evaluación de la expresión.
x = --n ; // -> x == 4 y n == 4
En ambos casos, el operando debe ser una variable, no una expresión. Por
ejemplo: (x+y)++ es ilegal.
§7.1 Para evidenciar la diferencia entre preincremento y postincremento, observe las
14. salidas que se obtienen con este pequeño programa según se van ejecutando las
diversas líneas. Para interpretarlas correctamente debe tener en cuenta la precedencia de
los operadores y recordar que, en todos los casos, el argumento recibido por printf es un
puntero-a-carácter (char*). También deben recordarse las reglas de ámbito de los
argumentos pasados a funciones.
char * s = "Hola mundo";
printf("Letra: "%c"n", *s); // Letra "H"
printf("Letra: "%c"n", *s+1); // Letra "I"
printf("Letra: "%c"n", *(s+1)); // Letra "o"
printf("Letra: "%c"n", *s++); // Letra "H"
printf("Letra: "%c"n", *s); // Letra "o"
printf("Letra: "%c"n", *++s); // Letra "l"
printf("Letra: "%c"n", *s); // Letra "l"
Como notas importantes a recordar siempre;
En problemas de división entre enteros, C++ trunca la parte residual, es decir;
</code> área de declaración de variables float a; área de operaciones
a = 10 / 4;
área de despliegue de resultados desplegar a; → En pantalla sale ( 2.000000 )
</code> El problema no es el tipo float, sino que por definición de la división
entre enteros C++ siempre trunca la parte residual, mas adelante se indica
como se resolverá este problema. El operador (%) devuelve el residuo entero
de una división entre enteros, ejemplo; <code> área de declaración
int alfa;
área de operaciones alfa = 23 % 4; área de despliegue
desplegar alfa; → El resultado en pantalla es 3
Otro ejemplo;
alfa = 108 % 10;
desplegar alfa; → El resultado en pantalla es 8
</code>
Para resolver los problemas de potencias y raíces, se usan ciertas instrucciones
especiales que proporciona el lenguaje, llamadas funciones matemáticas, en
C++ existe toda una librería de instrucciones o funciones matemáticas.
Recordar que todas las funciones reciben uno o más datos o valores y regresan
siempre un resultado, una de estas funciones matemáticas es:
#include<math.h>
doublepow(double base, doubleexp);
15. Esta función ocupa dos valores o datos( base y exp) ambos de tipo double, y
regresa un resultado también de tipo double, ejemplo;
Resolver el problema de calcular
#include<math.h>
// área de declaración de variables
double base, exponente, potencia;
// área de asignación o carga o inicialización de
// variables
base=5;
exponente=3;
// área de operaciones
potencia =pow( base, exponente);
// Despliegue
desplegar potencia; -> El resultado en pantalla es 125.000000000
16. Para resolver el problema de raíces, se aprovecha una de las mas elementales
y conocida de las leyes de exponentes que dice:
Es decir una raíz cualquiera se puede transformar a una potencia con un
exponente fraccionario.
Ejemplo:
problema <m> y = 3sqrt{x} </m> esto es equivalente a entonces
usando función pow
y= 3*pow(x, 0.5);
En este ejemplo se esta dando por supuesto que no interesa el tipo de dato
que requiere la función pow() para trabajar correctamente
RESUMEN: En C++ se puden resolver con la ayuda de estos operadores
toda clase de problemas, ya sean financieros, algebraicos de negocios,
contables, etc.