27 febrero 2015

C++ para C# 4: Datos básicos, arrays y listas

Vamos a ver otros tipos de datos (como los números reales), el manejo básico de arrays y de listas no ordenadas

Un programa que probara todo esto en C# podría ser así:

 1: using System;
 2: using System.Collections.Generic;
 3: 
 4: class DatosArraysListas
 5: {
 6:    
 7:     public static void Main()
 8:     {
 9:         // Algunos tipos de datos simples
10:         int i = 1;
11:         short s = 2;
12:         byte b = 3;
13:         long l = 4;
14:        
15:         float f = 1.0f;
16:         double d = 2.0;
17:        
18:         bool z = true;
19:        
20:         // Lectura de reales desde teclado
21:         Console.Write("Introduce un real (simple precisión): ");
22:         float f2 = Convert.ToSingle(Console.ReadLine());
23:         Console.Write("Y uno de doble: ");
24:         double d2 = Convert.ToDouble(Console.ReadLine());
25:        
26:         // Arrays
27:         int[] a1 = new int[3];
28:         a1[0] = 200;      // Les damos valores
29:         a1[1] = 150;
30:         a1[2] = 100;
31:         Console.WriteLine("a1 contiene: ");
32:         foreach (int n in a1)
33:             Console.WriteLine(n);
34:        
35:         int[] a2 = { 50, 30, 10};
36:         Console.WriteLine("a2 contiene: ");
37:         for (int j=0; j<a2.Length; j++)
38:             Console.WriteLine(a2[j]);
39:        
40:         int[,] a3 ={
41:             { 10, 20, 30},
42:             { 11, 21, 31}
43:         };
44:        
45:         Console.WriteLine("El primer dato de la segunda fila de a3 es "+
46:             a3[1,0]);
47:          
48:         // Lista de varios datos
49:         List<string> datos = new List<string>();
50:         datos.Add("Hola");
51:         datos.Insert(0,"Como estas?");
52:         datos.Add("Adios");
53:         datos.RemoveAt(1);
54:         Console.WriteLine("La lista contiene: ");
55:         foreach (string dato in datos)
56:             Console.WriteLine(dato);
57: 
58:    }
59: }

En C++ los cambios son:

  • Ya sabemos usar "cin" para entrada y "cout" para salida.
  • En general, los tipos de datos básicos se llaman igual en C++ que en C#.
  • En los arrays, los corchetes se ponen después del nombre de la variable y no se usa "new" para reservarles espacio: int a[2];
  • No hay una forma directa de saber el tamaño (cantidad de elementos) de un array: deberemos memorizarlo en una variable o constante, o bien calcular los bytes que ocupa toda la estructura y dividirlo entre los bytes que ocupa cada dato: (sizeof(a)/sizeof(*a))
  • Los arrays bidimensionales se separan con corchetes, no con comas: "int b[5][3];"  Si vamos a especificar los valores, aun así habrá que indicar el tamaño de todas las partes (excepto, como mucho, la primera): "int b[][3] = { ... } "
  • Las estructuras dinámicas en general son más incómodas de manejar en C++: El equivalente a una "List" de C# es un "vector". Se añade un elemento al final con "push_back", se podrían quitar del final con "pop_back", se inserta en una posición específica con "insert" y se borra con "erase". En estas operaciones, la posición se deberá indicar usando iteradores, a partir de "miVector.begin()". No existe "foreach", así que habrá que recorrer el vector con un "for" (el tamaño se obtiene con ".size()") o con un iterador. La clase "vector" internamente usa un array, de modo que se puede acceder con [] y este acceso es muy rápido, pero a cambio las operaciones "insert" son costosas porque hay que copiar todo el array. Como alternativa, también existe una clase "list", que se usaría de manera muy similar pero que no permite el acceso con [], sino que hay que recorrer de forma secuencial empleando iteradores. 

El resultado sería:

 1: #include <iostream>
 2: #include <vector>
 3: using namespace std;
 4:  
 5: int main () 
 6: {
 7:     // Algunos tipos de datos simples
 8:     int i = 1;
 9:     short s = 2;
10:     char b = 3;
11:     long l = 4;
12:    
13:     float f = 1.0f;
14:     double d = 2.0;
15:    
16:     bool z = true;
17:    
18:     // Lectura de reales desde teclado
19:     cout << "Introduce un real (simple precisión): ";
20:     float f2;
21:     cin >> f2;
22:     cout << "Y uno de doble: ";
23:     double d2;
24:     cin >> d2;
25:    
26:     // Arrays
27:     int a1[3];
28:     a1[0] = 200;      // Les damos valores
29:     a1[1] = 150;
30:     a1[2] = 100;
31:     cout << "a1 contiene: " << endl;
32:     for (int j=0; j<3; j++)
33:         cout << a1[j] << endl;
34:    
35:     int a2[] = { 50, 30, 10};
36:     cout << "a2 contiene: " << endl;
37:     int tamanyo = (sizeof(a2)/sizeof(*a2));
38:     for (int j=0; j<tamanyo; j++)
39:         cout << a2[j] << endl;
40:    
41:     int a3[][3] ={
42:         { 10, 20, 30},
43:         { 11, 21, 31}
44:     };
45:    
46:     cout << "El primer dato de la segunda fila de a3 es " << 
47:         a3[1][0]  << endl;
48:      
49:     // Lista de varios datos
50:     vector<string> datos;
51:     vector<string>::iterator iterad;    
52:     datos.push_back("Hola");
53:     datos.insert(datos.begin(),"Como estas?");
54:     datos.push_back("Adios");
55:     iterad=datos.begin();
56:     iterad++;
57:     datos.erase(iterad);
58:     cout << "La lista contiene: " << endl;
59:     for (unsigned j=0; j<datos.size(); j++)
60:         cout << datos[j] << endl;
61:     cout << "O con iteradores: " << endl;
62:     
63:     for (iterad=datos.begin(); iterad<datos.end(); iterad++)
64:         cout << *iterad << endl;
65: }

Dentro de poco, acceso a ficheros en C++... 

25 febrero 2015

C++ para C# 3: Cadenas y teclado

Llega el momento de retomar la "chuleta rápida de C++ para gente que conoce C#". Vamos con ello... hoy toca hablar de las cadenas y del manejo de teclado...

El manejo de cadenas de texto en C++ es muy parecido al de C#. La lectura de teclado es muy simple: "cin" puede leer tanto números como cadenas. Vamos a ver primero un ejemplo en C# y su resultado, para luego convertirlo a C++:

 1: using System;
 2: 
 3: public class CadenasTeclado
 4: {
 5: 
 6:   public static void Main()
 7:   {
 8: 
 9:     string ejemplo = "Hola, que tal estas";
10:    
11:     string ejemplo2 = "Hola";
12:     string ejemplo3;
13:     ejemplo3 = " y hola";
14:     string ejemplo4 = ejemplo2+ejemplo3;
15:    
16:     if (ejemplo2 == "Hola")
17:       Console.WriteLine("El texto 2 es Hola");
18:        
19:     Console.WriteLine("El texto es: {0}",
20:       ejemplo);
21:      
22:     Console.WriteLine("La primera letra es: {0}",
23:       ejemplo[0]);
24:    
25:     Console.WriteLine("Las tres primeras letras son: {0}",
26:       ejemplo.Substring(0,3));
27: 
28:     Console.WriteLine("La longitud del texto es: {0}",
29:       ejemplo.Length);
30:    
31:     Console.WriteLine("La posicion de \"que\" es: {0}",
32:       ejemplo.IndexOf("que"));
33:    
34:     Console.WriteLine("La ultima A esta en la posicion: {0}",
35:       ejemplo.LastIndexOf("a"));
36:      
37:     Console.WriteLine("En mayúsculas: {0}",
38:       ejemplo.ToUpper());
39:      
40:     Console.WriteLine("En minúsculas: {0}",
41:       ejemplo.ToLower());
42:      
43:     Console.WriteLine("Si insertamos \", tio\": {0}",
44:       ejemplo.Insert(4,", tio"));
45:    
46:     Console.WriteLine("Si borramos las 6 primeras letras: {0}",
47:       ejemplo.Remove(0, 6));
48:    
49:     Console.WriteLine("Si cambiamos ESTAS por ESTAMOS: {0}",
50:       ejemplo.Replace("estas", "estamos"));
51:      
52:     // Y ahora vamos a leer desde teclado
53:    
54:     Console.Write("Dime tu nombre: ");
55:     string nombre = Console.ReadLine();
56:     Console.WriteLine("Hola {0}", nombre);
57:    
58:     Console.Write("Vamos a sumar dos números... Primero? ");
59:     int n1 = Convert.ToInt32( Console.ReadLine() );
60:     Console.Write("Segundo? ");
61:     int n2 = Convert.ToInt32( Console.ReadLine() );
62:     Console.WriteLine("Suma: {0}", n1+n2);
63:   }
64: }

Que mostraría algo como

El texto 2 es Hola
El texto es: Hola, que tal estas
La primera letra es: H
Las tres primeras letras son: Hol
La longitud del texto es: 19
La posicion de "que" es: 6
La ultima A esta en la posicion: 17
En mayúsculas: HOLA, QUE TAL ESTAS
En minúsculas: hola, que tal estas
Si insertamos ", tio": Hola, tio, que tal estas
Si borramos las 6 primeras letras: que tal estas
Si cambiamos ESTAS por ESTAMOS: Hola, que tal estamos
Dime tu nombre: yo
Hola yo
Vamos a sumar dos números... Primero? 1
Segundo? 3
Suma: 4


Al pasarlo a C++, deberemos tener en cuenta que:


  • Existen "cadenas al estilo C", definidas como "char*" o como "char[]", pero es preferible evitarlas. C++ propone un tipo "cadena de texto", llamado "string".
  • No usaremos "{0}" para posicionar los parámetros, sino que escribiremos varios valores separados por "<<".
  • Para comprobar el valor de una cadena no se debe usar "==", porque estaríamos comparando realmente si están en la misma posición de memoria. En vez de eso, debemos usar "cadena1.compare(cadena2)" (que tendrá como resultado 0 si son iguales).
  • Para extraer un carácter de la cadena se emplean corchetes, al igual que en C#, o bien se podría usar ".at(pos)".
  • La longitud no se halla con ".Length" sino con ".length()"
  • Para obtener una subcadena, no usaremos "Substring" sino ".substr", al que se le indica posición inicial y longitud.
  • Para buscar la primera aparición de un texto se usa "find" y para la última (primera desde la derecha), "rfind". Ambas devuelven el valor especial "string::npos" si no se encuentra.
  • No hay una forma de convertir a mayúsculas y minúsculas toda una cadena. En el fichero de cabecera "locale" existen un "toupper" y un "tolower" que se pueden aplicar letra a letra.
  • Para insertar una cadena en medio de otra se usa "insert" y para eliminar un fragmento se emplea "erase".
  • No podemos reemplazar un texto por otro todas las veces que aparezca. Existe un "replace", pero recibe la posición inicial, la longitud y la cadena que hay que incluir entre esas posiciones.
  • Las operaciones de modificación, como "insert", "erase" y "replace" no necesitan volcarse a una nueva cadena (aunque se puede), porque modifican la cadena de texto original.
  • Se puede leer tanto cadenas como números con "cin". Si la cadena puede contener espacios, habrá que usar "cin.getline", al que se le indica tanto la cadena en la que se quiere guardar como la longitud máxima permitida: "cin.getline(texto, 80);"

 

Con todos estos cambios, el fuente podría quedar así...

 1: #include <iostream>
 2: #include <locale>
 3: using namespace std;
 4:  
 5: int main () 
 6: {
 7:     locale zona;
 8:     string ejemplo = "Hola, que tal estas";
 9: 
10:     string ejemplo2 = "Hola";
11:     string ejemplo3;
12:     ejemplo3 = " y hola";
13:     string ejemplo4 = ejemplo2+ejemplo3;
14:    
15:     if (ejemplo2 == "Hola")
16:       cout << "El texto 2 es Hola" << endl;
17:        
18:     cout << "El texto es: " << ejemplo << endl;
19:      
20:     cout << "La primera letra es: " << ejemplo[0] << endl;
21:    
22:     cout << "Las tres primeras letras son: "  <<
23:         ejemplo.substr(0,3) << endl;
24: 
25:     cout << "La longitud del texto es: " << ejemplo.length() << endl;
26:    
27:     cout << "La posicion de \"que\" es: " <<
28:       ejemplo.find("que") << endl;
29:    
30:     cout << "La ultima A esta en la posicion: " <<
31:       ejemplo.rfind("a") << endl;
32:      
33:     cout << "En mayúsculas: ";
34:     for (size_t i=0; i<ejemplo.length(); i++)
35:         cout << toupper(ejemplo[i], zona);
36:     cout << endl;
37:      
38:     cout << "En minúsculas: ";
39:     for (size_t i=0; i<ejemplo.length(); i++)
40:         cout << tolower(ejemplo[i], zona);
41:     cout << endl;
42:      
43:     cout << "Si insertamos \", tio\": " <<
44:       ejemplo.insert(4,", tio") << endl;
45:    
46:     cout << "Si borramos las 6 primeras letras: " <<
47:       ejemplo.erase(0, 6) << endl;
48:    
49:     cout << "Si cambiamos ESTAS por ESTAMOS: " <<
50:       ejemplo.replace(ejemplo.find("estas"),5, "estamos") << endl;
51:      
52:     // Y ahora vamos a leer desde teclado
53:    
54:     cout << "Dime tu nombre: ";
55:     string nombre;
56:     cin >> nombre;
57:     cout << "Hola " << nombre << endl;
58:    
59:     cout << "Vamos a sumar dos números... Primero? " << endl;
60:     int n1, n2;
61:     cin >> n1;
62:     cout << "Segundo? " << endl;
63:     cin >> n2;
64:     cout << "Suma: " << n1+n2 << endl;
65:     
66:     return 0;
67: }

Para mañana, algo de arrays y de estructuras dinámicas...

Como siempre, si tienes dudas, ya sabes: usa los comentarios o el foro de C++ de AprendeAProgramar.