- 1 Cambios
- 1.1 Versión 1.0.0
- 2 Objetivos
- 3 Enunciado
- 4 Herramientas
- 5 Ayuda de C++
- 6 Ejercicio
- 7 División del código fuente en archivos
- 8 Requisitos técnicos
- 9 Detección de plagios/copias
1 Cambios
1.1 Versión 1.0.0
- Enunciado original.
2 Objetivos
Son varios los objetivos de esta práctica 0:
-
Habituarnos al estilo de los enunciados de las prácticas, p.e. observa que al principio del mismo hay una etiqueta de versión:
1.0.0
, la cual cambiará si se corrige algún fallo o se modifica por algún motivo el enunciado.De este modo siempre sabrás con qué versión del enunciado estas trabajando.
-
Conocer el formato de entrega de prácticas.
-
Probar el sistema de entregas en pracdlsi y asegurarnos de que podemos entregar prácticas allí sin problemas.
-
Aprender a usar algunas herramientas muy útiles a la hora de programar:
-
Repasar algunos conceptos de Programación I.
-
Hacer uso de tipos de datos numéricos enteros de tamaño fijo.
-
Conocer algunas de las nuevas características que nos ofrece
C++
(el lenguaje de programación que usaremos en modo C++-17). -
Dadas los objetivos anteriores y características especiales de esta práctica no se realizará corrección de la misma.
3 Enunciado
-
Esta práctica consiste en una colección de ejercicios que se describen a continuación.
-
Deben aparecer todos en el mismo fichero fuente,
p0.cc
, y en dicho fichero no debe haber una funciónmain
en el momento de la entrega. Este fichero se debe poder compilar con la ordenmake
y un ficheroMakefile
. -
Puedes crear un programa principal de prueba en un fichero aparte (
mainp0.cc
). Para compilar esteprograma principal
con el fuentep0.cc
puedes utilizar esta orden: ‘g++ -g -Wall --std=c++17 mainp0.cc p0.cc -o p0
’, pero lo lógico es que prepares un archivoMakefile
para que realice compilación separada. -
Las opciones empleadas en la llamada al compilador son:
-
-g
: Está relacionada con el uso del depurador a nivel de código fuente. -
--std=c++17
: Hace que el compilador funcione en modoC++17
. -
-Wall
: Activa la generación de un gran número de advertencias. No son fallos de compilación pero debes prestar atención a lo que te dicen ya que pueden dar lugar a errores en tiempo de ejecución.
-
-
La corrección de la práctica se realizará probando cada ejercicio por separado, añadiendo para ello una función
main
(en otro fichero fuente, parecido almainp0.cc
).
4 Herramientas
4.1 Make
Make
lee su configuración de un archivo de texto normalmente llamadoMakefile
.- En estos archivos encontraremos (entre otras cosas) una colección
de reglas:
objetivo : dependencia1 dependencia2 ... dependenciaN (TAB) orden1 (TAB) orden2 ... (TAB) ordenN
- Los objetivos suelen ser
archivos
que generamos con las órdenes asociadas a cada regla, pero también pueden ser otros objetivos definidos en el archivo Makefile. - Veamos algunos ejemplos.
4.2 Gdb
- Es un depurador a nivel de código fuente.
- Nos permite ejecutar nuestra aplicación paso a paso, consultar el valor de variables, tomar el control de ella en cualquier momento.
- Para que
Gdb
funcione correctamente necesitamos compilar todo nuestro código con la opción ‘-g
’ deg++
ogcc
. - Funciona en modo texto, pero es muy sencillo.
- Prueba la interfaz que tiene al lanzarlo con la opción ‘
--tui
’. - Usa
gdb
así:gdb tu-programa
- Para salir teclea:
q + ENTER
oquit + ENTER
- Disponemos de otros interfaces sobre
gdb
, p.e.: - Veamos un ejemplo.
#include <iostream>
#include <cstring>
using namespace std;
int busca_caracter(char cadena[],char c)
{
int i, posicion=-1;
for (i=0;i<strlen(cadena) || cadena[i]!=c;i++) { // debe ser con '&&'
cout << cadena[i];
}
if (i<strlen(cadena)) posicion=i;
return posicion;
}
int main()
{
int p;
char holamundo[]="hola, mundo";
cout << "---------------------" << endl;
p=busca_caracter(holamundo,'o');
cout << endl << "(o) p=" << p << endl;;
cout << "---------------------" << endl;
p=busca_caracter(holamundo,'u');
cout << endl << "(u) p=" << p << endl;;
cout << "---------------------" << endl;
p=busca_caracter(holamundo,'A');
cout << endl << "(A) p=" << p << endl;;
}
4.3 Valgrind
-
No es una única herramienta, son varias, según lo uses de una manera u otra tienes acceso a una u otra herramienta.
-
Estas herramientas analizan la ejecución de nuestra aplicación.
-
Nosotros lo emplearemos para saber si nuestra aplicación se deja bloques de memoria sin liberar.
-
Es muy útil que compilemos nuestro código con la opción ‘
-g
’. -
Ejecuta valgrind con la opción ‘
--help
’ para saber todas las opciones con las que lo puedes invocar. -
La forma más sencilla de emplearlo es así:
valgrind tu-programa
-
Veamos algunos ejemplos.
int main(int argc, char *argv[])
{
int* p;
int* q = new int;
//*p = 3;
return 0;
}
5 Ayuda de C++
5.1 Compilador de C++
- El compilador de
C++
del proyecto GNU se llama:g++
. - Los ficheros de
C++
suelen tener la extensión.cc
o.cpp
o.C
. Nosotros emplearemos siempre.cc
. - Los archivos de cabecera propios de
C++
no tienen extensión.h
. Si en algún momento necesitas incluir un archivo de cabecera deC
, estos se llaman quitándoles la extensión.h
y anteponiéndoles el prefijoc
, p.e.math.h
pasa a llamarsecmath
:#include <cmath>
- Lo usaremos con la opción
--std=c++17
para asegurarnos que trabajamos en modoC++17
.
5.2 Tipo bool
C++
define el tipo bool en el lenguaje. Son palabras reservadas
los valores true
y false
.
5.3 Entrada/salida en C++
-
En
C++
es recomendable usar laE/S
proporcionada por los iostreams. -
Para poder emplear
cout
debes incluir la cabecera<iostream>
y , de momento, llamarlo como en el ejemplo anterior:std::cout << "n = " << n << std::endl;
-
O emplear la construcción
using namespace std
y así poder emplearcout
sin el prefijo:
using namespace std;
// Fíjate que ahora ya no hay prefijo 'std::'
cout << "n = " << n << endl;
5.4 Mini tutorial sobre la clase std::string
de C++
-
Para usar el tipo string debemos incluir la cabecera
<string>
, de lo contrario es posible que tengamos un error de compilación. -
Las cadenas de
C++
se pueden concatenar con el operador+
, p.e.:std::string s = "hola"; s = s + " mundo";
-
Las cadenas de tipo
std::string
no acaban en un\0
. Si necesitas una cadena deC
(acabada en\0
) puedes usar el métodostd::string::c_str
así:const char* cstr = s.c_str();
. -
En esta práctica-0 (salvo en los lugares donde explícitamente se usen cadenas de
C
) puedes emplear cadenas de C++ si las necesitas.
#include<string>
using namespace std; // Para no usar std::string
// Creación de una cadena vacía, "")
string s;
// Creación de una cadena no vacía)
string s2 = "Programación-II";
// Lectura hasta el final de la línea
getline(cin,s);
// Mostrar por pantalla
cout << s << endl;
s="hola"; // Asignación
// Recorrido, s.length() es la longitud
for (uint i=0u; i < s.length(); i++)
cout << s[i]; // imprimir un carácter
s[3] = 'A'; // Asignación de un carácter
s = s + ','; // concatena un carácter "holA,"
s = s + " mundo"; // concatena una cadena "holA, mundo"
if (s <= "hola") // Comparacion de strings
if (s == "adios")
...
5.5 Mini tutorial sobre la clase std::vector
de C++
-
Para usar el tipo vector debemos incluir la cabecera
<vector>
, de lo contrario es posible que tengamos un error de compilación. -
Para declarar una variable de tipo
vector
debemos indicar también el tipo de los elementos del vector, esto se hace poniendo ese tipo entre ángulos, p.e:std::vector<float> fv; // vector de numeros reales
. -
Los vectores de tipo
std::vector
:-
Son dinámicos, pueden crecer y decrecer en tiempo de ejecución.
-
Saben cuantas componentes tienen, para ello se emplea la función
size
que, al igual que con el tipostring
se utiliza con la notación:mi_vector.size()
. -
Una de las maneras de añadir elementos a un vector por el final es usando la función
push_back
, como puedes ver en el ejemplo siguiente.
-
#include <cstdint>
#include <iostream>
#include <vector>
#include <string>
void print_int8_vector(const std::vector<int8_t> &v) {
for (auto &e : v) {
std::cout << "· " << (int)e << '\n';
}
}
void print_string_vector(const std::vector<std::string> &v) {
for (auto &e : v) {
std::cout << "· " << e << '\n';
}
}
int main(int argc, char *argv[]) {
std::vector<int8_t> iv;
std::vector<std::string> sv;
for (int8_t i = 0; i < 10; i++)
iv.push_back(i);
for (int8_t i = 0; i < 15; i++) {
std::string s = "cadena-";
s += std::to_string(i);
sv.push_back(s);
}
std::cout << "vector<int8>: elementos: " << iv.size() << '\n';
print_int8_vector(iv);
std::cout << "vector<string>: elementos: " << sv.size() << '\n';
print_string_vector(sv);
return 0;
}
5.6 Mini tutorial sobre memoria dinámica en C++
-
Tal y como hemos visto en clase de teoría la gestión de la memoria dinámica (reserva y liberación) corre a cargo del lenguaje y no de funciones de biblioteca como en C (
malloc
yfree
). -
La reserva de memoria la realizan los operadores
new
ynew[]
mientras que la liberación la hacen los operadoresdelete
ydelete[]
, es decir, cuando reservas memoria connew
debes liberarla posteriormente condelete
y cuando lo haces connew[]
debes liberarla condelete[]
. -
Ejemplos:
// iv es un vector de 4 enteros, empleamos 'new[]'
int n = 4;
int* iv = new int[n];
...
// Liberamos la memoria con 'delete[]', los '[]' van vacios
delete[] iv;
// Reservamos un puntero a un caracter, empleamos 'new'
char* cp = new char;
...
// Liberamos la memoria, empleamos 'delete'
delete cp;
- El lenguaje incorpora el literal
nullptr
que representa un puntero nulo de cualquier tipo. EnC++
no debemos emplear la macroNULL
usada en lenguajeC
.
int* v = nullptr;
6 Ejercicio
- En este ejercicio puedes crear las funciones auxiliares que
necesites. Para ello debes definirlas en el archivo
p0.cc
, recuerda que los archivos de cabecera entregados como p.e.p0.h
no deben ser modificados.
6.1 Extracción de palabras de una frase.
-
Nos piden que devolvamos las palabras quen componen una frase. Una cadena vacía no se considera una palabra.
-
La frase se representa como un dato de tipo
std::string
y el separador entre palabras es un carácter, un dato de tipochar
. -
Para ello nos piden que escribamos el código de una función con el siguiente prototipo
std::vector<std::string> split_on(const std::string& s, char c);
-
Esta función:
-
Devuelve como resultado un vector de cadenas en el que cada componente del mismo es una palabra de la frase original.
-
Si la frase original es una cadena vacía, devuelve un vector con cero componentes. El carácter separador nunca será un carácter vacío.
-
Si la frase original no contiene ningún carácter separador se considera que toda la frase es una única palabra.
-
7 División del código fuente en archivos
-
Tendremos un único archivo de cabecera (
p0.h
) con los prototipos de las funciones además de los#include
necesarios para que no de errores de compilación. -
Este archivo hará uso de la guarda para protegerlo de su inclusión más de una vez que hemos visto en el tema-1.
-
Tendremos un único archivo de implementación (
p0.cc
, trabajamos enC++
) con la implementación de todas las funciones además de los#include
necesarios para que no de errores de compilación (también incluirá ap0.h
). Este archivo no contendrá ningún programa principal (main). -
Para poder probar tus funciones puedes crearte la función
main
que quieras en otro archivo, p.e.mainp0.cc
(el cual incluirá ap0.h
) y compilarlo y enlazarlo con el anterior así:g++ -g -Wall --std=c++17 mainp0.cc p0.cc -o p0
. No es necesario entregarlo, si se hace no pasa nada. -
También puedes emplear el archivo Makefile para compilar y enlazar. Recuerda que lo tienes en la carpeta de la práctica.
-
Todos los archivos
`.h'
y`.cc'
se encontrarán dentro de una carpeta llamadairp2-p0
.
8 Requisitos técnicos
-
Requisitos que tiene que cumplir este trabajo práctico para considerarse válido y ser evaluado (si no se cumple alguno de los requisitos la calificación será cero):
-
El archivo entregado se llama
irp2-p0.tgz
(todo en minúsculas), no es necesario entregar ningún programa principal, sólo son necesarios tus archivos`.h'
y`.cc'
en una carpeta llamadairp2-p0
. A su vez, esta carpeta estará comprimida en el fichero llamadoirp2-p0.tgz
. Este archivo lo puedes crear así en el terminal:tar cfz irp2-p0.tgz irp2-p0
-
También puedes emplear el archivo
Makefile
que tienes en la carpeta de la práctica para generar el fichero de la entrega tal y como hemos visto en clase de prácticas. -
Al descomprimir el archivo
irp2-p0.tgz
se crea un directorio de nombreirp2-p0
(todo en minúsculas). -
Dentro del directorio
irp2-p0
estará al menos el archivop0.cc
(todo en minúsculas).Recuerda que el fichero ‘p0.h’ no se debe modificar, de lo contrario tus ficheros ‘.cc’ no compilarán con el corrector. No es necesario entregarlo, si se hace no pasa nada.
-
Las clases, métodos y funciones implementados se llaman como se indica en el enunciado (respetando en todo caso el uso de mayúsculas y minúsculas). También es imprescindible respetar estrictamente los textos y los formatos de salida que se indican en este enunciado.
-
Al principio de todos los ficheros fuente (`.h’ y `.cc’) entregados y escritos por ti se debe incluir un comentario con el nombre y el NIF (o equivalente) de la persona que entrega la práctica, como en el siguiente ejemplo:
// NIF: 12345678-Z // NOMBRE: GARCIA PEREZ, LAURA
-
Un error de compilación/enlace implicará un cero en esa parte de la práctica.
Aunque esta práctica no cuenta para la nota final, su entrega es obligatoria y sirve para comprobar que vuestro usuario para la entrega de prácticas posteriores funciona correctamente, además de permitirte evaluar cuál es tu nivel real de conocimientos de programación adquiridos en Programación-I. Si tienes cualquier problema con su entrega comunícaselo a tu profesor lo antes posible.
-
Lugar y fecha de entrega :
Recuerda que las entregas se realizan siempre en (y sólo en)
https://pracdlsi.dlsi.ua.es en las fechas y condiciones allí publicadas. Puedes entregar la práctica tantas veces como quieras, sólo se corregirá la última entrega (las anteriores no se borran). El usuario y contraseña para entregar prácticas es el mismo que se utiliza en UACloud.
9 Detección de plagios/copias
-
En el Grado en Ingeniería Robótica, la Programación es una materia muy importante. La manera más efectiva de aprender a programar es programando y, por tanto, haciendo las prácticas correspondientes además de otros programas (más sencillos o más complicados, eso da igual).
-
Tratar de aprobar las asignaturas de programación sin programar (copiando) es complicado y obviamente, te planteará problemas para seguir otras asignaturas así como en tu futura vida laboral.
-
En una asignatura como Programación-II es difícil que alguien que no ha hecho las prácticas supere los exámenes de teoría o el de recuperación de prácticas.
-
IMPORTANTE:
-
Cada práctica debe ser un trabajo original de la persona que la entrega.
-
En caso de detectarse indicios de copia de una o más prácticas se tomarán las medidas disciplinarias correspondientes, informando a las direcciones de Departamento y de la EPS por si hubiera lugar a otras medidas disciplinarias adicionales.
-