elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Recuerda que debes registrarte en el foro para poder participar (preguntar y responder)


  Mostrar Mensajes
Páginas: 1 2 3 4 [5]
41  Programación / Programación C/C++ / Re: de wchar_t a unsigned char en: 20 Mayo 2015, 15:44 pm
No he visto tu código original, pero seguramente, el ejemplo que has pillado sería equivalente al siguiente:

Código
  1. const wchar_t* wstr = /* lo que sea */; // Cadena const.
  2. unsigned char* ustr = reinterpret_cast<unsigned char*>(const_cast<wchar_t*>(wstr));

Sin embargo, tú tendrás lo siguiente:

Código
  1. wchar_t* wstr = /* lo que sea */; // Cadena no-const.
  2. unsigned char* ustr = reinterpret_cast<unsigned char*>(const_cast<wchar_t*>(wstr));

El error está en el `const_cast`. El `const_cast` sirve para quitar/poner el calificativo `const` a un puntero o una referencia. Ejemplos:

Código
  1. int a = 3;
  2.  
  3. // Ok, const_cast recibe un puntero (int*) y lo convierto a puntero-a-constante (const int*).
  4. const int* ptr_a = const_cast<const int*>(&a);
  5. const int* ptr2_a = &a; // Ok, la conversion a const tambien funciona de forma implicita.
  6.  
  7. // Aqui el `const_cast` es absolutamente necesario. Quitarle `const` a un puntero/referencia nunca
  8. // es implicito (ponerselo si), y hay que forzarlo con `const_cast`.
  9. int* ptr3_a = const_cast<int*>(ptr_a);
  10.  
  11. // Este es el error de tu codigo! `ptr3_a` no es constante, y el tipo de salida del casting, tampoco (int*),
  12. // pero `const_cast` requiere que uno de los dos sea constante y el otro no! Si los dos son iguales
  13. // te da un error de compilacion.
  14. int* ptr4_a = const_cast<int*>(ptr3_a);

No he puesto ejemplos con referencias porque no es tu caso. ¿Cuál es tu problema? Que tu `const_cast<wchar_t*>(wstr)` está diciendo: "quítale el `const` a `wstr`", pero `wstr` resulta que no es `const`, así que no hay nada que quitar, y de ahí el error de compilación. De todas formas, utilizar un `const_cast` es peligroso, y podría provocar incluso violaciones de segmento (especialmente con cadenas). Si algo se marco como `const`, es por algo.

Bueno, continuemos. ¿Y qué es lo que hace `reinterpret_cast<tipo>(var)`? Pues sencillamente lo siguiente: coje la dirección de memoria de la variable que le has pasado, y a partir de ahí, coje `sizeof(tipo)` bytes y lo devuelve como un objeto de tipo `tipo`. Ajin! Completamente a pelo, y éso es muy peligroso.

Por ejemplo (relacionandolo con tu caso):

Código
  1. wchar_t wc = /* un caracter, el que sea */
  2. unsigned char c = reinterpret_cast<unsigned char>(wc);

Veamos el peligro: al menos en mi arquitectura, `sizeof(wc) == 4`, mientras que `sizeof(char) == 1`. Al realizar dicho `reinterpret_cast`, el compilador coje el primer byte the `wc` y devuelve la secuencia de bits como un `unsigned char`, sin adaptar la representación ni nada, y `c` tendría una copia del primer byte the `wc`.

¿Qué pasa con cadenas/punteros?

Código
  1. wchar_t* wc = /* lo que sea. Cadena de 5 caracteres. */
  2. unsigned char* c = reinterpret_cast<unsigned char*>(wc);

Aquí `wc` es un puntero (y todos los punteros tienen el mismo tamaño en una misma arquitectura), así que `reinterpret_cast`  devuelve la misma dirección de memoria, pero ahora desde `c` estás manipulando `unsigned char`s y no `wchar_t`s. Así que:

Código
  1. for (unsigned i = 0; i < 5; ++i)
  2.    cout << c[i] << endl;

Aquí, tu crees que estás imprimiendo los 5 primeros carácteres de la cadena original (transformada como `unsigned char`), pero resulta que estás imprimiendo ¡los 4 primeros bytes del primer carácter de la cadena `wchar_t` original, más el primer byte de la segunda! Habría que hacerlo de la siguiente forma:

Código
  1. for (unsigned i = 0; i < 5 * sizeof(wchar_t); ++i)
  2.    cout << c[i] << endl;

Además, utilizarlo de la siguiente forma tiene muchos riesgos, el más importante es que `wchar_t` es un tipo muy especial, cuya implementación es a gusto del compilador, así que en teoría, no hay forma de saber cómo está representado cada carácter. ¿Están los bytes puestos de abajo a arriba? ¿De arriba a bajo? ¿Con complemento a uno o a dos? ¿Cada carácter tiene 2 bytes, 4 u 8?

Así que, si trabajar con `reinterpret_cast` es peligroso de por sí (solo debe usarse en situaciones muy controladas), y utilizarlo para llegar de `wchar_t` a `char` lo es más aún.

Siempre que puedas, utiliza `char*`, a no ser que sea exclusivamente necesario.
42  Programación / Programación C/C++ / Re: [Aporte] fixedInteger.h en: 19 Mayo 2015, 22:33 pm
Ok. Aquí el mío, con las comprobaciones siguientes:

  • Detección de signo '+' (línea 34).
  • Escape de prefijo de 0s (línea 37).
  • Detección de número demasiado grande capturando desbordamiento (línea 15).
  • Paramétrico: acepta cualquier tipo númerico, sin importar si es signed o unsigned, ni su tamaño (short, long, long long), ni los detalles de la arquitectura: si la arquitectura utiliza complemento a dos para representar números, por ejemplo para el caso `sizeof(int) == 4`, el rango va desde -2^31 hasta 2^31-1, pero si utiliza complemento a uno, va desde -2^31+1 hasta 2^31-1, para números sin signo.
  • Si se desea un `unsigned`, pero se ha introducido el signo `-`, también lanza error (línea 31).
  • He hecho la función recursiva para ahorrar líneas (sustituir asignaciones por parámetros). No me gusta poner en foros códigos muy largos. De todas formas, el compilador seguramente la cambiará por una función iterativa sin mucho esfuerzo.

Código en coliru: http://coliru.stacked-crooked.com/a/bf7bfac2d1b46842 (haced click en `Edit` y cambiar la entrada por el número que queráis para probar el programa).

Aquí una lista de los límites numéricos según la arquitectura (sección Range of values): http://en.cppreference.com/w/cpp/language/types, por si queréis hacer pruebas.

Para cambiar el tipo que deseáis obtener, cambiad el que aparece en la línea 48: `getNum<tipo>(str)`.

Código
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <type_traits>
  4.  
  5. using namespace std;
  6.  
  7. template<typename Num_t> // Funcion recursiva, caracter a caracter.
  8. Num_t getNum(string const& str, Num_t num, signed char sign, size_t i, unsigned char nextc)
  9. {
  10.    if (i == str.size()) return num;
  11.    if (nextc > 9) throw invalid_argument("Eso no es un numero.");
  12.  
  13.    Num_t next = num * 10 + sign * nextc;
  14.  
  15.    if (sign == 1 ? (next < num) : (next > num))
  16.        throw invalid_argument("Numero demasiado grande.");
  17.  
  18.    return getNum(str, next, sign, i + 1, str[i + 1] - '0');
  19. }
  20.  
  21. template<typename Num_t>
  22. Num_t getNum(string const& str)
  23. {
  24.    if (str.size() == 0) throw invalid_argument("Introduzca un numero.");
  25.  
  26.    size_t i = 0;
  27.    signed char sign = 1;
  28.  
  29.    if (str[i] == '-') {
  30.        if (is_unsigned<Num_t>::value)
  31.            throw invalid_argument("Un numero natural no puede ser < 0.");
  32.  
  33.        ++i; sign = -1;
  34.    } else if (str[i] == '+')
  35.        ++i;
  36.  
  37.    while (str[i] == '0') ++i; // Ignoramos prefijo de 0s.
  38.  
  39.    return getNum<Num_t>(str, 0, sign, i, str[i] - '0');
  40. }
  41.  
  42. int main()
  43. {  
  44.    while (cin.good()) // Hasta que no me des un numero (y quede entrada) no te escapas.
  45.        try {
  46.            string str;
  47.            getline(cin, str); cin.ignore();
  48.            cout << getNum<unsigned>(str) << endl;
  49.            break;
  50.        } catch (invalid_argument const& e) {
  51.            cerr << e.what() << endl;
  52.        }
  53.  
  54.    return 0;
  55. }


Nota sobre chars: Mientras que el tipo `char` se utiliza para manipular carácteres, los tipos `signed char` y `unsigned char` se utilizan para manipular números de 1 byte (si `char` tiene signo o no, se deja a criterio del compilador). Si queréis utilizar éste programa para capturar números en el rango [-127, 127], [-128, 127] o [0, 255] (ya sabéis, números de 1 byte, signed/unsigned), la línea 48 no imprime el número, sino el carácter correspondiente devuelto por `getNum`. Tenéis que hacer un casting en ese caso a `int` por ejemplo para imprimir el número.

Aunque por supuesto, siempre hay solución para ello, sin tener que hacer casting manual :)

Código
  1. // Alias de `std::conditional`, para que `char2Short` y `RetNum` no queden muy largos.
  2. template<bool b, typename T, typename F>
  3. using conditional_t = typename conditional<b, T, F>::type;
  4.  
  5. // Transformacion char -> short conservando signo.
  6. template<typename T>
  7. using char2Short = conditional_t<is_signed<T>::value, short, unsigned short>;
  8.  
  9. // Nos aseguramos de devolver al menos un short, para que el
  10. // numero se imprima bien.
  11. template<typename T>
  12. using RetNum = conditional_t<sizeof(T) == 1, char2Short<T>, T>;
  13.  
  14. // Sobrecarga recursiva de `getNum` sin cambios, ya que si devolviese un `short` cuando
  15. // estamos trabajando con `char`s, podría fallar la comprobación de desbordamiento (no
  16. // estoy seguro en realidad).
  17.  
  18. template<typename Num_t>
  19. RetNum<Num_t> getNum(string const& str)
  20. { /* Implementacion */ }
  21.  
  22. // Main con getNum<char>(str) o getNum<signed char>(str), por ejemplo ...
43  Programación / Programación C/C++ / Re: [Aporte] fixedInteger.h en: 19 Mayo 2015, 16:23 pm
Si nos ponemos pedantes, ese código de Gunhack sufre dos defectos:

  • La operación de obtener el número y la de notificar al usuario del error y el reintento, están acoplados.
  • ¿Y si mañana quisieses cambiar el tipo de número a `unsigned`, `long long int` o `long double`?

En mi caso, bastaría con:

Código
  1. #include <iostream>
  2. #include <stdexcept>
  3.  
  4. using namespace std;
  5.  
  6. #define READ_TYPE int
  7.  
  8. template<typename Num_t>
  9. Num_t getNumero()
  10. {
  11.   Num_t numero; cin >> numero;
  12.  
  13.   // A partir de aquí, ya no hay más referencias al tipo.
  14.   if (cin.fail())
  15.      throw domain_error("Hey!!! Eso no es un numero!!");
  16.  
  17.   char c; cin >> c;
  18.  
  19.   if (!cin.fail())
  20.       throw domain_error("Hey!! Has escrito algo mas detras del numero!!");
  21.  
  22.   return numero;
  23. }
  24.  
  25. int main()
  26. {
  27.   while (true) { // Hasta que el número no sea correcto, no te escapas.
  28.     try {
  29.          cout << getNumero<READ_TYPE>() << endl;
  30.          break;
  31.     } catch (domain_error const& e) {
  32.         cerr << e.what() << endl;
  33.     }
  34.   }
  35.  
  36.   return 0;
  37. }
  38.  

Y el tipo que deseo obtener lo puedo especificar pasándole el valor de la macro al compilador (con la opción `-Dmacro=valor` en `gcc` si no me equivoco), así que no tengo que tocar el código si quiero cambiar el tipo.

En el caso de Gunhack, habría que cambiar el tamaño del búfer, y eso no es una tarea tan sencilla: ¿cuántos dígitos requiere un `long int`? http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models Seguramente con metaprogramación, `constexpr`s y la librería `<climits>` se pueden obtener buenas cotas, pero ¿y qué pasa con números flotantes? En fin...

La ventaja del código de Gunhack, por otro lado, es que en caso error, su alternativa es claramente menos costosa que la basada en excepciones, pero a veces hay que sacrificar eficiencia a cambio de diseño.

Aunque bueno, éstas consideraciones se escapan al objetivo del ejercicio de Mario, pero he dicho al inicio de la respuesta que estamos en pedantic mode.
44  Programación / Programación C/C++ / Re: Duda para ejercicio en C (principiante) en: 18 Mayo 2015, 23:19 pm
Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.   unsigned numero;
  6.  
  7.   scanf("%u", &numero);
  8.  
  9.   if (numero > 100) {
  10.      printf("Numero incorrecto\n");
  11.      return 1;
  12.   }
  13.  
  14.   for (unsigned i = 0; i < numero; ++i)
  15.      printf("%c", 'A');
  16.  
  17.   printf("\n"); // Salto de linea extra, para que la salida quede mas bonita.
  18.  
  19.   return 0;
  20. }
  21.  

Por razones que entenderás en el futuro, un programa, si termina exitosamente, debe devolver un 0, y si termina con errores, debe devolver un 1. Por eso en el `if` he devuelto 1 (ha ocurrido un error), mientras que al final del main, he devuelto un 0.
45  Programación / Programación C/C++ / Re: string & parametro dudas !! en: 18 Mayo 2015, 22:44 pm
Siempre ten presente que las funciones deben hacer una sola cosa (o construir una cadena inversa, o imprimirla, pero no ambas). Como tú solamente quieres imprimir, pues que `reverse` imprima, sin más dilación. Si sigues éste principio, tus códigos quedarán siempre mucho más claros. Por otro lado, siempre que trabajes con tamaños e índices, utiliza `size_t`, que no es más que un alias de `unsigned`, pero está pensado precisamente para recorridos y tamaños (`int` y `unsigned` deberían ser usados para problemas más "numéricos" o matemáticos).

Código
  1. void reverse(char const* str)
  2. {
  3.   // Bucle en dirección inversa.
  4.   for (size_t i = strlen(str) - 1; i >= 0; --i)
  5.      cout << str[i];
  6.  
  7.   cout << endl;
  8. }
  9.  
  10. int main()
  11. {
  12.   reverse("linda");
  13.  
  14.   system("pause");
  15.  
  16.   return 0;
  17. }
  18.  

Un truco aprendido por ahí, que simplifica mucho el trabajo, es utilizar "-->", que no es un operador, sino sencillamente, postdecremento y "mayor que", pero se escriben juntos para que parezca una flechita en dirección al 0 (salida del bucle):

Código
  1. void reverse(char const* str)
  2. {
  3.   size_t i = strlen(str);
  4.  
  5.   while (i --> 0)
  6.      cout << str[i];
  7.  
  8.   cout << endl;
  9. }
  10.  

Queda aún más claro, y más legible. Al utilizar un postdecremento de `i`, y suponiéndo que strlen(str) == 5, el `while` va a comparar `i` con los valores 5, 4, 3, 2 y 1 (5 elementos, todos mayores que cero), pero dentro del `while`, debido a que el postdecremento actúa más tarde, los valores serán 4, 3, 2, 1 y 0 (los índices de la cadena), y además, en órden inverso, que es justo lo que quieres.

Si lo que quisieras fuera construir la cadena inversa, e imprimirla fuera, siguiendo el principio de que cada función haga solamente una cosa, pues podría ser así:

Código
  1. // La cadena devuelta por `reverse` es dinámica, y el usuario de la función es responsable de
  2. // eliminarla.
  3. char* reverse(char const* str)
  4. {
  5.   size_t len = strlen(str);
  6.   char* rev = new char[len + 1]; // 1 extra para el '\0'.
  7.  
  8.   for (size_t i = 0; i < len; ++i)
  9.      rev[i] = str[len - i - 1];
  10.  
  11.   rev[len] = '\0';
  12.  
  13.   return rev;
  14. }
  15.  
  16. int main()
  17. {
  18.   char const* rev = reverse("linda");
  19.  
  20.   cout << rev << endl;
  21.  
  22.   delete[] rev;
  23.  
  24.   system("pause");
  25.  
  26.   return 0;
  27. }
  28.  
46  Programación / Programación C/C++ / Re: problema en un for con variables en: 18 Mayo 2015, 17:36 pm
En la sección de inicialización del `for` solo puedes tener una declaración compuesta. Es decir, tantas variables como quieras, pero del mismo tipo, separadas por comas:
 
Código
  1. #include <iostream>
  2.  
  3. using namespace std; // Mas comodo incluir todo el espacio de nombres.
  4.  
  5. int main()
  6. {
  7.   // Variables
  8.   int palindromo;
  9.   bool respuesta = true;
  10.  
  11.   cout << "palindromo: ";
  12.   cin >> palindromo;
  13.  
  14.   // He borrado el segundo `int`. En la sección de "tests", puedes tener varias expresiones separadas
  15.   // por comas, pero tu quieres que se cumplan todas, asi que utiliza un `and`.
  16.   for(int divMayor = 10000, divMenor = 10; divMenor <= 10000 and divMayor >= 10; divMenor *= 10, divMayor /= 10)
  17.   {
  18.      if ((palindromo / divMayor) != (palindromo / divMenor)) {
  19.         respuesta = false;
  20.         break;
  21.      }
  22.  
  23.      palindromo %= divMayor;
  24.      palindromo /= divMenor;
  25.   }
  26.  
  27.   // Con poner `if (respuesta)` es suficiente.
  28.   // Por otro lado, estructuras de control (`if/else`, `while`, `for` y `do-while`) que solo
  29.   // tengan una sentencia, no necesitan llaves.
  30.   // Por ultimo, puedes utilizar `std::endl` en vez de `\n`.
  31.   cout << endl;
  32.  
  33.   if (respuesta)
  34.      cout << "El numero es un palindromo.";
  35.   else
  36.      cout << "El numero no es un palindromo.";
  37.  
  38.   // No necesitas `cin.get();` aqui.
  39.   return 0;
  40. }
47  Programación / Programación C/C++ / Re: Necesitamos ayuda con este programa en: 18 Mayo 2015, 14:36 pm
Primera cosa. Añadid las etiquetas de "código" en el código para que se vea bien (como lo tengo yo abajo). Escribid "[ code=c]" (sin el espacio detrás de `[`) al principio de vuestro código, y "[ /code]" al final (sin el espacio también).

Segundo, ni idea de qué hace vuestro algoritmo, pero os comento un par de fallos que he visto.

Por otro lado, en vuestro relleno de columnas. En vuestro código teníais "columnas * sizeof(double*)", pero cada fila se rellena con una matriz de `double`s y no con punteros. Aunque `sizeof(double) == sizeof(double*)` normalmente, es casualidad. Si una arquitectura tiene palabras de 64 bits pero solo direcciona hasta 32 bits de memoria, `sizeof(double) == 8` pero `sizeof(double*) == 4`. Así que:

Código
  1. for(i = 0; i < filas; ++i) { // Preincremento (++i) siempre mejor que postdecremento (i++).
  2.   matriz = (double*)malloc(columnas * sizeof(double));
  3.  
  4.   if(matriz == NULL) {
  5.      printf("No se ha podido reservar espacio de memoria.\n");
  6.      // getchar(); Para que necesitas `getchar`?
  7.      exit(EXIT_FAILURE); // `EXIT_FAILURE` (= 1, pero mas sano). Necesitas <stdlib.h> para usarlo.
  8.   }
  9. }
  10.  

Al comienzo del algoritmo puede haber un riesgo con la memoria (te lo pongo en comentarios). Por otro lado, acostumbraos a quitad llaves cuando no son necesarias (si una estructura de control -if/else, for, while, do-while, solo contiene una sentencia, las llaves no son necesarias), y a utilizar preincrementos en vez de postincrementos (y a poner espacios entre operadores por cuestiones de legibilidad). Comparadad como queda el código (mucho más legible y corto):

Código
  1. // Cuidado con la linea (1): aqui asumes que el numero de filas y de columnas coinciden, sin embargo
  2. // al inicio del `main` has permitido que el usuario inicialice ambas. Y si el numero de filas es mayor
  3. // que el de columnas? Que cuando `iteracion >= filas`, la linea (1) provocara un `segmentation fault`.
  4. // Si necesitas que la matriz sea cuadrada, pide al usuario solo las filas e inicializa columnas con el
  5. // mismo valor.
  6. while(iteracion < filas) {
  7.  
  8.   pivote = matriz[iteracion][iteracion]; // (1)
  9.  
  10.   for(i = 0; i < columnas; ++i) // Aqui no necesitas llaves. Este `for` solamente tiene una sentencia.
  11.      num[iteracion] = matriz[iteracion];
  12.  
  13.   for(i = 0; i < filas; ++i) // Igual, fuera llaves. Y preincremento de nuevo.
  14.      if(iteracion != i) // Fuera llaves.
  15.         num[iteracion] = 0;
  16.  
  17.   for(i = 0; i < filas; ++i) // Fuera llaves. Preincremento.
  18.      for(j = 0; j < columnas; ++j)  // Idem.
  19.         if(i != iteracion && j != iteracion) // Union de ifs.
  20.            num[j] = (((matriz[j] * pivote) - (matriz[iteracion][j] * matriz[iteracion])) / pivant);
  21.  
  22.   ++iteracion; // Preincremento.
  23.   pivant = pivote; // Algo de espacio entre `for`s y sentencias normales, para que no haya claustrofobia.
  24.  
  25.   for(i = 0; i < filas; ++i) // Preincremento. Llaves
  26.      for(j = 0; j < columnas; ++j) // Preincremento. Llaves.
  27.         matriz[j] = num[j];
  28. }
  29.  
48  Programación / Programación C/C++ / Re: [Aporte] fixedInteger.h en: 17 Mayo 2015, 02:16 am
¿Excesivo? Te quedas corto xD.

Es mucho más fácil y corto así:

Código
  1. #include <iostream>
  2. #include <stdexcept>
  3.  
  4. using namespace std;
  5.  
  6. int getNumero()
  7. {
  8.   int numero; cin >> numero;
  9.  
  10.   if (cin.fail())
  11.      throw domain_error("Hey!!! Eso no es un numero!!");
  12.  
  13.   char c; cin >> c;
  14.  
  15.   if (!cin.fail())
  16.       throw domain_error("Hey!!! Has escrito algo mas detras del numero!!");
  17.  
  18.   return numero;
  19. }
  20.  
  21. int main()
  22. {
  23.   while (true) { // Hasta que el numero no sea correcto, no te escapas.
  24.     try {
  25.          cout << getNumero() << endl;
  26.          break;
  27.     } catch (domain_error const& e) {
  28.         cerr << e.what() << endl;
  29.     }
  30.   }
  31.  
  32.   return 0;
  33. }
  34.  

Si estás empezando con C++ y te quedas un poco a cuadros con éste código (nadie ha dicho que C++ fuera fácil), pues ve investigando por Internet una a una las funciones y operadores que he utilizado aquí para que lo vayas desgranando, pero fundamentalmente, lo que veo que has malinterpretado es cómo se comportan los flujos en C++ (cin). Ellos ya hacen un montón de trabajo de parseo por tí.

Consejo: no reinventes la rueda. Cada vez que veas algo que sea simple, pero que implique mucho trabajo, seguramente ya esté hecho en algún lugar.

Mod: etiqueta GeSHi modificada, debe ser code=cpp, no code=c++
49  Programación / Programación C/C++ / Re: Pasar string a time. Número de días entre dos fechas en: 17 Mayo 2015, 01:47 am
Código
  1. #include "stdio.h"
  2. #include "time.h"
  3.  
  4. #define SEGS_DIA 86400
  5.  
  6. int main()
  7. {
  8.  struct tm fecha = {}; // Inicializamos la estructura a 0.
  9.  
  10.  // Asumimos que el formato de fecha introducido por el usuario es correcto.
  11.  printf("Introduce la fecha: ");
  12.  scanf("%u%u%u", &fecha.tm_mday, &fecha.tm_mon, &fecha.tm_year);
  13.  
  14.  --fecha.tm_mon; // La estructura tm numera los meses del 0 al 11.
  15.  fecha.tm_year -= 1900; // Los annos comienzan en 1900.
  16.  
  17.  // No utilizo difftime porque devuelve un `double` y me da coraje.
  18.  int diff = (mktime(&fecha) - time(NULL)) / SEGS_DIA;
  19.  
  20.  printf("\nLa diferencia es: %d\n", diff);
  21.  
  22.  return 1;
  23. }
  24.  

Si quisiéramos comprobar el formato de entrada mejor, el `scanf` sería algo más "complejo":

Código
  1. char truco;
  2.  
  3. int leidos = scanf("%2u%2u%4u%c", &fecha.tm_mday, &fecha.tm_mon, &fecha.tm_year, &truco);
  4.  
  5. if (leidos != 3)
  6.  exit(EXIT_FAILURE);
  7.  
  8. if (tm_year < 1000) // Asumimos que el anno debe tener al menos 4 digitos.
  9.  exit(EXIT_FAILURE);
  10.  

Los numeritos (el 2 o el 4) son para indicar el "ancho" máximo que tendrá cada campo. El otro "truco" (la `%c` final) sirve para evitar que el usuario introduzca cadenas más largas de la cuenta; por ejemplo: "24 11 19900asd". El formato de entrada sería correcto para `scanf`, porque los cuatro primeros dígitos del campo "año" se guardan correctamente.

El problema es que `scanf` deja de "leer" e ignora el resto de la cadena, así que lo forzamos a leer al menos uno más, y si ha recuperado 4, es que la cadena era demasiado larga.
50  Programación / Programación C/C++ / Re: Borrar números repetidos en vector en: 17 Mayo 2015, 00:46 am
Si el órden de los elementos no importa, puedes utilizar un `set` auxiliar (no he probado el código):

Código
  1. void eliminarRepetidos(vector<int>& v)
  2. {
  3.    set<int> sinReps;
  4.  
  5.    for (auto& i : v)
  6.       sinReps.insert(i); // Los elementos repetidos no se insertan en un set.
  7.  
  8.    vector<int> nuevo;
  9.  
  10.    for (auto& i : sinReps)
  11.        nuevo.push_back(i);
  12.  
  13.    // `nuevo` no tendrá elementos repetidos. Efecto secundario: ahora estará ordenado.
  14.    // Sustituimos `v` por `nuevo`.
  15.    v = nuevo;
  16. }
  17.  
Páginas: 1 2 3 4 [5]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines