Aprendiendo a programar programando

    cabecera

terepebernal.com

De Pseudocódigo a C++. Algoritmo día de la semana de una fecha

En este artículo te voy a mostrar un algoritmo hecho en C++. Tengo nociones muy básicas de C++, por lo que hay que tener en cuenta que para obtener el mismo resultado que obtiene este algoritmo, lo más seguro es que podría realizarse utilizando menos líneas de código que las que yo utilizo aquí. Esto es solo un ejercicio de «traducción del algoritmo de pseudocódigo a C++». Es un ejercicio que no tenía previsto realizar, ya que lo hice en JavaScript, pero algunas personas me han preguntado si podría mostrarlo en C++, por eso este post.

Se trata de un algoritmo ya publicado en este blog, Algoritmo día de la semana de una fecha con PSeInt. Reutilizando funciones, que puedes verlo también traducido a JavaScript.

En la siguiente imagen puedes ver el resultado de la ejecución del algoritmo en C++ para las fechas 25/02/2020 y 26/09/2050:

Resultado Algoritmo Día Semana de Fecha en C++

 

Si quieres estar al tanto de las novedades y publicaciones de esta página web

Suscríbete

Librerías y namespace, declaración de funciones y función main

Primero se incluyen las librerías iostream, para la entrada y salida de datos, y string que se encarga de las cadenas de texto. También se incluye la declaración del uso del namespace std (estándar), para no tener que escribir más código (std::cout, en vez de solo cout, por ejemplo). Y después escribimos la declaración (prototipos) de todas las funciones que vamos a utilizar y que se definirán más adelante.

/**
   Mostrará por pantalla el día de la semana en el que
   cae la fecha que se pedirá al usuario por teclado.
   El valor del año estará entre 1601 y 3000
*/

#include <iostream>
#include <string>

using namespace std;

//Declaración de funciones
bool isDateOk(string dateC);
bool separadorOk(string dateC);
bool isNumberDate(string dateC);
bool isLeapYear(int year);
bool monthOk(int month);
bool yearOk(int year);
bool dayOk(int day, int month, int year);
int firstDayYear(int year);
int firstDayMonth(int year, int month);
string dayWeekText(int dW);

En C++ siempre se utiliza la función principal llamada main, que devuelve un valor entero, por eso al final de la función utilizamos un return 0, por que sino nos daría un error al compilar.

Dentro de esta función, primero declaramos las variables que nos van a hacer falta. A continuación utilizamos un bucle while que nos permitirá seguir ejecutando el programa mientras pulsemos la tecla S al final del programa.

Dentro de ese bucle:

  • se pide al usuario la fecha por teclado mediante cout (muestra datos por pantalla) y cin (recoge la fecha en la variable dateC por teclado)
  • se guarda dentro de la variable OK el resultado de la función isDateOk(dateC)
  • si OK resulta verdadero (la fecha es válida), mediante las funciones at y stoi, se convierten los caracteres de dateC en números para poder hacer cálculos
  • se guarda en fDM el día de la semana (en formato número) en que cae el primer día del mes, mediante la función firstDayMonth(year,month)
  • en D se guardan los días que hay que sumarle al primer día del mes, y en dW se guarda el día de la semana (en formato número) que corresponde a la fecha
  • se muestra por pantalla el resultado final utilizando la función dayWeekText(dW) para mostrarlo en formato texto
  • si el usuario quiere volver a ejecutar el programa, se le da esa opción pulsando la tecla «S». Si pulsa otra tecla sale del programa.

int main() {
    string dateC,d;
    int year,month,day,fDM,D,dW;
    bool S,OK;
    char seguir;

    S=true;
    while(S){
        //Pedir por teclado la fecha indicando el formato
        cout<<"\nINTRODUCE UNA FECHA (DD/MM/AAAA)....";
        cin>>dateC;

        //Comprobar que la fecha es válida
        OK=isDateOk(dateC);
        if (OK){
                //Se convierten los caracteres a números para poder operar con ellos
                d=dateC.at(0);
                d+=dateC.at(1);
                day=stoi(d);
                d=dateC.at(3);
                d+=dateC.at(4);
                month=stoi(d);
                d=dateC.at(6);
                d+=dateC.at(7);
                d+=dateC.at(8);
                d+=dateC.at(9);
                year=stoi(d);

                fDM=firstDayMonth(year,month);     //Primer día del mes
                D=(day-1)%7;
                dW=fDM+D;       // Día de la semana en que cae la fecha
                if (dW>7){
                          dW-=7;
                }
                cout<<endl;
                cout<<endl;
                cout<&lt"LA FECHA ";
                cout<<dateC;
                cout<&lt" CAE EN ";
                cout<&ltdayWeekText(dW);
                cout<<endl;
                cout<<endl;
        }
	else{
             // Si la fecha no es correcta
		cout<&lt"FECHA INCORRECTA. INTÉNTALO DE NUEVO."<<endl;
        }
	cout<&lt"Pulsar la tecla S para continuar ...";
	cin>>seguir;
        if ((seguir=='S') || (seguir=='s')){
			S=true;
        }
        else{
			S=false;
        }
    }

    return 0;
}

Función isDateOk y sus funciones auxiliares en C++

A partir de aquí se definen todas las funciones que se han declarado antes.

La función isDateOk devuelve un valor booleano mediante la variable OK y recibe como parámetro una cadena de caracteres en dateC. Esta función permite comprobar si la fecha tiene un formato correcto (DD/MM/AAAA o DD-MM-AAAA) y si es una fecha válida.

Primero mediante la función length comprueba que la cadena tenga 10 caracteres, después utilizando la función auxiliar separadorOk comprueba que los separadores sean ‘ / ‘ o ‘ – ‘ y que estén en las posiciones 3 y 6 de la cadena de caracteres. A continuación con la función auxiliar isNumberDate comprueba que el resto de caracteres de la cadena sean números. Si todos los caracteres son númericos, utilizando las funciones at y stoi, convierte los caracteres al tipo de dato entero para poder operar con ellos.


//Definición de funciones
/**
   Comprueba que la fecha tiene el formato correcto
   y que es una fecha válida
 */
bool isDateOk(string dateC){
    bool OK;
    int lDate, month, year, day;
    string d;

    lDate=dateC.length();
    if (lDate != 10) {
        OK=false;				// La cadena no tiene 10 caracteres, luego es incorrecta
    }
    else{
        // Comprobar si los caracteres de separación son los correctos
        OK=separadorOk(dateC);
        if (OK){
            //Comprobar que los demás caracteres sean todos numéricos
            OK=isNumberDate(dateC);
            if (OK){
                //Si todos son numéricos convertir a número para poder calcular
                d=dateC.at(0);
                d+=dateC.at(1);
                day=stoi(d);
                d=dateC.at(3);
                d+=dateC.at(4);
                month=stoi(d);
                d=dateC.at(6);
                d+=dateC.at(7);
                d+=dateC.at(8);
                d+=dateC.at(9);
                year=stoi(d);
                // Comprobar si el mes es correcto
                OK=monthOk(month);
                if (OK){
                    // Comprobar si el año es correcto
                    OK=yearOk(year);
                    if (OK){
                        // Comprobar si el día es correcto
                        OK=dayOk(day,month,year);
                    }
                }
            }
        }
    }

    return OK;
}

/**
   Comprueba que los caracteres separadores son los correctos y están en la posición correcta
*/
bool separadorOk(string dateC) {
    bool OK;
    if ((dateC.at(2)=='/') && (dateC.at(5)=='/')) {
        OK=true;
    }
    else {
            if ((dateC.at(2)=='-') && (dateC.at(5)=='-')) {
                OK=true;
            }
            else {
                OK=false;
            }
    }

    return OK;
}

/**
    Comprueba que los caracteres del día, mes y año sean numéricos
*/
bool isNumberDate(string dateC){
     // Declarar variables
     bool OK;
     int i;
     i=0;
     while (i<=9) {
           if ((i==2) || (i==5)) {
			i++;
           }
           else {
                 if (isdigit(dateC.at(i))) {
                       OK=true;
                       i++;
                 }
                 else {
                       OK=false;
                       i=10;
                 }
           }
     }

     return OK;
}

Por último, mediante las funciones auxiliares monthOk, yearOk y dayOk comprueba si el mes, año y día conforman una fecha válida.


/**
    Comprueba si el mes de la fecha es válido
*/
bool monthOk(int month){
     bool OK;

     if (month>=1 && month<=12){ OK=true; } else{ OK=false; } return OK; } /** Comprueba si el año de la fecha es válido */ bool yearOk(int year){ // Declarar variables bool OK; if (year>=1601 && year<=3000){ OK=true; } else{ OK=false; } return OK; } /** Comprueba si el día de la fecha es válido */ bool dayOk(int day, int month, int year){ bool OK; if (day>=1 && day<=31){ switch(day){ case 31: if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){ OK=true; } else{ OK=false; } break; case 30: if (month==2){ OK=false; } else{ OK=true; } break; case 29: if ((month==1) || (month>=3 && month<=12) || ((month==2) && isLeapYear(year))){
                             OK=true;
                       }
                       else{
                             OK=false;
                       }
                       break;
                 default:
                             OK=true;
           }
     }
     else{
          OK=false;
     }

     return OK;
}

Función isLeapYear y función dayWeekText en C++

Estas dos funciones también son auxiliares. La función isLeapYear es utilizada en la función dayOk, firstDayYear y firstDayMonth, y lo que hace es calcular si el año es un año bisiesto, en cuyo caso existe el día 29 de febrero. Y la función dayWeekText es utilizada por la función principal main para mostrar el día de la semana en formato texto.


/**
    Recibe el año (year) y devuelve (lY) si es bisiesto o no
*/
bool isLeapYear(int year){
    bool lY;

    //Si el año es múltiplo de 4
    if (year%4==0){
          lY=true;
          //Si además es múltiplo de 100 y de 400
          if ((year%100!=0) || (year%400==0)){
                lY=true;
          }
          else{
                lY=false;
          }
    }
    else{
          lY=false;
    }

    return lY;
}

/**
    Devuelve el día de la semana (dW) en texto
*/
string dayWeekText(int dW){
    string dWT;

    switch(dW){
          case 1:
                dWT="LUNES";
                break;
          case 2:
                dWT="MARTES";
                break;
          case 3:
                dWT="MIÉRCOLES";
                break;
          case 4:
                dWT="JUEVES";
                break;
          case 5:
                dWT="VIERNES";
                break;
          case 6:
                dWT="SÁBADO";
                break;
          case 7:
                dWT="DOMINGO";
                break;
          default:
                dWT="PARECE QUE HAY ALGÚN ERROR";
    }

    return dWT;
}

Función firstDayYear en C++

La función firstDayYear recibe como parámetro un año (year) y devuelve el día de la semana en que cae el primer día del año, mediante la variable dW. Los cálculos se hacen teniendo en cuenta que el primer día del año 1601 fue lunes, y utilizando la función auxiliar isLeapYear, vista en el apartado anterior, para saber si el año anterior a year fue bisiesto.


/**
    Recibe el año (year) correspondiente y
    devuelve el día de la semana (dW) en el que cae el primer día de dicho año
*/
int firstDayYear(int year){
    int dW,i;
    bool lY;

    if (year==1601){
          // Si es 1601, el primer día del año es Lunes
          dW=1;
    }
    else{
          // Si el año es mayor que 1601
          // Buscar primer día del año
          dW=1; // Se comienza en lunes
          for(i=1602; i<=year; i++){
                // Si el año anterior fue bisiesto el día la semana
                // habrá que sumarle dos más, y sino uno.
                lY=isLeapYear(i-1);
                if(lY){
                      dW+=2;
                }
                else{
                      dW++;
                }
                // Si se llega a 8, es lunes
                if (dW==8){
                      dW=1;
                }
                // Si se llega a 9, es martes
                if(dW==9){
                      dW=2;
                }
          }
    }

    return dW;
}

Función firstDayMonth en C++

La función firstDayMonth recibe como parámetros un año (year) y un mes (month) del año, y devuelve el día de la semana en que cae el primer día del mes de ese año, mediante la variable dW. Esta función utiliza como funciones auxiliares las funciones isLeapYear y firstDayYear.

La función primero comprueba si el año es bisiesto, para tenerlo en cuenta en el caso del mes de marzo. Después haya el día de la semana en que cae el primer día del año, y a partir de ahí calcula el día de la semana en que cae el primer día del mes correspondiente, dependiendo de si el mes que precede tiene 30 ó 31 días.


/**
    Recibe el año (year) y mes (month) correspondientes y
    devuelve el día de la semana (dW) en el que cae el primer día del mes de ese año
*/
int firstDayMonth(int year, int month){
    int fDY,dW,i;
    bool lY;
    lY=isLeapYear(year); // ¿Es un año bisiesto?
    fDY=firstDayYear(year); // Primer día de la semana del año

    for(i=1; i<=month; i++){
          // Si es enero, el primer día será el primer día del año
          if (i==1){
                dW=fDY;
          }
          // Si es marzo, el primer día dependerá de si el año es bisiesto o no
          if (i==3){
                if(lY){
                      dW++;
                }
                else{
                      dW=dW;
                }
          }
          // Si es un mes precedido de otro de 31 días, se le sumarán 3 días
          if ((i==2) || (i==4) || (i==6) || (i==8) || (i==9) || (i==11)){
                dW+=3;
          }
          // Si es un mes precedido de otro de 30 días, se le sumarán 2 días
          if ((i==5) || (i==7) || (i==10) || (i==12)){
                dW+=2;
          }
          // Si llega a 8, es lunes
          if (dW==8){
                dW=1;
          }
          // Si llega a 9, es martes
          if (dW==9){
                dW=2;
          }
          // Si llega a 10, es miércoles
          if (dW==10){
                dW=3;
          }
    }

    return dW;
}

Si quieres el código completo en un solo archivo puedes descargarlo del repositorio de github.

El enlace al algoritmo en pseudocódigo es Algoritmo día de la semana de una fecha con PSeInt. Reutilizando funciones, puedes verlo también traducido a JavaScript.

Si quieres estar al tanto de las novedades y publicaciones de esta página web

Suscríbete
  • Juan Carlos Palma Macias dice:

    Apoyo para realizar este algorimoLa empresa “Corruexpress S.A. de C.V” desea implementar un programa sencillo que le permita llevar un control de sus productos, ventas diarias, etc. Los productos que venden son los siguientes:
    Producto Precio Unitario
    A) Caja para archivos $45.00
    B) Caja para mudanza $76.00
    C) Caja de doblado fácil $38.00
    • Cuando se venden de 1 a 25 piezas se conserva el precio unitario
    • Cuando se venden de 26 a 50 piezas se hace un descuento (sobre el precio unitario) del 3%
    • Cuando se venden 51 o más piezas se hace un descuento (sobre el precio unitario) del 5%
    • Construye una propuesta de algoritmo, en pseudocódigo, que permita a la Empresa Corruexpres saber las piezas vendidas y las ventas totales ($) por caja A, B y C

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

* (obligatorio)

Derechos: Tienes derechos, entre otros, a acceder, rectificar, limitar y suprimir tus datos. Envíame un e-mail a contacto@terepebernal.com