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

 

 


Tema destacado: AIO elhacker.NET 2021 Compilación herramientas análisis y desinfección malware


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Programa que muestra la frecuencia de una lista de compras
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Programa que muestra la frecuencia de una lista de compras  (Leído 2,771 veces)
LuisUvtol

Desconectado Desconectado

Mensajes: 10


Ver Perfil
Programa que muestra la frecuencia de una lista de compras
« en: 9 Junio 2020, 16:40 pm »

Hola a todos, perdón por el retraso pero hasta ahorita tuve un poco de tiempo, les comparto mi programa, el cual dado una lista (separada por comas) calcula la frecuencia de esta misma, tambien lo guarda en un archivo de texto, les dejo el código, solo creen su archivo de texto, yo lo puse como "BaseDeDatos.txt", no es el mejor programa pero si funciona jeje
Código:
Código
  1. #include <stdio.h>  // printf
  2. #include <stdlib.h> // malloc y free
  3. #include <string.h> // strcasecmp
  4. #include <conio.h>
  5. #include <iostream>
  6. #include <fstream>
  7. #include <bits/stdc++.h>
  8.  
  9. using namespace std;
  10.  
  11. //Prototipos de funciones
  12. void agregar(struct frecuenciaCompras indice);
  13. void agregarLista(char id[100]);
  14. void imprimir();
  15. void guardar();
  16. bool OrdenarPorIndice(const pair<int, int>& a, const pair<int, int>& b);
  17. void OrdenarPorFrecuencia(int recibo[], int n);
  18. void menu();
  19.  
  20. struct Nodo *superior = NULL;      //Como estara vacio entonces es Null
  21.  
  22. //Declaro Una estructura con datos ID y NumeroCompras
  23. struct frecuenciaCompras{
  24. char id[200];
  25. int NumeroCompras;
  26. };
  27. //Declaro un nodo que me ayudara a crear mi pila
  28. struct Nodo{                                //Declaro una Estructura la cual es un Nodo y contiene los valores de indice
  29. struct frecuenciaCompras indice;
  30. struct Nodo *sigue;                     //Apunta a un nodo siguiente por tratarse de una pila
  31. };
  32.  
  33.  
  34.  
  35. //----------------------------------------------Funcion Main-----------------------------------------------------
  36. int main(){
  37.  
  38. cout<<"\tSupermercado \n\n " <<endl;
  39. menu();
  40.  
  41. getch();
  42.  
  43.  
  44. }
  45. //----------Declaracion de las funciones--------------------
  46. void agregar(struct frecuenciaCompras indice){                          //Esta funcion hace un push, es decir, agrega un struct
  47.  struct Nodo *agregaNodo = (Nodo*)malloc(sizeof(struct Nodo));
  48.  agregaNodo->indice = indice;
  49.  agregaNodo->sigue = superior;
  50.  superior = agregaNodo;
  51. }
  52. void buscarPorFrecuencia(char id[200]){                    //Esta funcion recorre toda la pila y compara cada caracter, si encuentra un caracter repetido la frecuencia aumenta
  53. struct Nodo *aux = superior;
  54. while (aux != NULL){
  55. int buscafrecuencia = strcasecmp(aux->indice.id, id);
  56. if(buscafrecuencia==0){
  57. aux->indice.NumeroCompras++; //Si se repite entonces se le sumara 1 al numero de compras
  58. return;
  59. }
  60. aux = aux->sigue;
  61. }
  62. struct frecuenciaCompras indice;
  63. strcpy(indice.id, id);
  64. indice.NumeroCompras = 1;                               //Si solo se repite 1 vez entonces el numero de compras es 1
  65. agregar(indice);
  66. }
  67.  
  68. void imprimir(){
  69.  char guiones[] = "---------------------";
  70.  printf("%s%s\n", guiones, guiones);
  71.  printf("|%-20s|%-20s|\n", "ID producto", "Veces Comprado");
  72.  printf("%s%s\n", guiones, guiones);
  73.  
  74. struct Nodo *aux = superior;
  75.  
  76. while (aux != NULL){
  77. printf("|%-20s|%-20d|\n", aux -> indice.id, aux->indice.NumeroCompras);
  78. aux = aux -> sigue;                                                         //Con esto imprimo el que sigue
  79. }
  80.  
  81. printf("%s%s\n", guiones, guiones);
  82.  
  83. }
  84.  
  85. void guardar(){
  86.    ofstream archivo;                                      //Se ejecuta la funcion ofstream
  87. char fecha[15];
  88.  
  89. cout<<"Fecha de Guardado: ";                            //Se le pide al usuario que digite la fecha
  90. cin.ignore();
  91. cin.getline(fecha,15, '\n');
  92.  
  93. archivo.open("BaseDatos.txt",ios::app);                 //Se abre el archivo
  94. archivo<<"Fecha de guardado: "<<fecha<<"\n";            //se escribe la fecha de guardado del archivo
  95.  
  96. struct Nodo *aux = superior;                                   //Creo una variable auxiliar y la iguala a superior
  97.  
  98. char guion[] = "--------------------";                  //Apartado unicamente para la interfaz grafica
  99.  
  100.    archivo<<"+"<<guion<<"+"<<guion<<"+\n";
  101.    archivo<<"   Producto          |     Frecuencia     \n";
  102.    archivo<<"+"<<guion<<"+"<<guion<<"+\n";
  103.  
  104. while(aux != NULL){                                     //Se declara un bucle para guardar los datos
  105. archivo<<aux->indice.id<<"                             "<<aux->indice.NumeroCompras<<"\n";  //accedo a los valores de mi estructura indice y el numero de compras
  106. aux = aux->sigue;
  107. }
  108.  
  109. archivo<<"+"<<guion<<"+"<<guion<<"+\n";                 //Apartado para graficos
  110.    archivo.close();                                        //Cierro mi archivo
  111. cout<<"Base de datos actualizada\n\n";
  112. }
  113.  
  114.  
  115. //------------------------------Esta funcion me ordena mi cadena de enteros dependiendo de la frecuencia-----------------------------------------
  116. //Si tengo una lista de enteros: 4,5,5,6,6,6 me la ordena de la siguiente forma: 6 6 6 5 5 4
  117. unordered_map<int, int> valor;                                              //unordered_map almacena elementos formados por la combinacion de un valor clave y un valor mapeado
  118.  
  119. bool OrdenarPorIndice(const pair<int, int>& a, const pair<int, int>& b){
  120.  
  121.    if (a.second == b.second)
  122.        return valor[a.first] < valor[b.first];
  123.  
  124.    return a.second > b.second;
  125. }
  126.  
  127. void OrdenarPorFrecuencia(int recibo[], int n){                   //Funcion que me ordena, recibe una lista de enteros, el int n solo sirve para los bucles for{
  128.    unordered_map<int, int> mapaa;
  129.    vector<pair<int, int> > vec;                                //El pair consta de 2 elementos, el primero elemento se hace referencia como primero(first) y el segundo(second)
  130.  
  131.    for (int i = 0; i < n; ++i) {
  132.        mapaa[recibo[i]]++;
  133.  
  134.        if (valor[recibo[i]] == 0) // Actualiza el valor del mapa solo una vez
  135.            valor[recibo[i]] = i + 1;
  136.    }
  137.  
  138.  
  139.    copy(mapaa.begin(), mapaa.end(), back_inserter(vec));      //copio mapa al vector mediante la funcion copy
  140.  
  141.    sort(vec.begin(), vec.end(), OrdenarPorIndice); //sort me  sirve para ordenar el vector en orden ascendente (por indice)
  142.    int elj; //declaro una variable int la cual convertire a char
  143.    string je;
  144.    for (int i = 0; i < vec.size(); ++i) { //Declaro una sentencia for anidada el primer for es para recorrer el vector y el sgundo para ir guardando los datos en mi variable elj
  145.        for (int j = 0; j < vec[i].second; ++j){
  146.            elj = vec[i].first;
  147. //----------------------Convierto el int a string ------------------
  148.            stringstream ss;
  149.            ss<<elj;
  150.            string s;
  151.            string space(" ");                              //Dejo un espacio por cada valor
  152.            ss>>s;
  153.            s.append(space);                               //Concateno los string
  154.            je.append(s);
  155.  
  156. }
  157. }
  158. //-------------------------Convierto de string a char---------------
  159. char c[je.size()+1];
  160. strcpy(c, je.c_str());
  161.    cout<<"La lista ordenda por frecuencia es: "<<c<<endl;
  162. //strrev(c);   //se invierte el orden de la cadena
  163.                char delimitador[] = ", ";                     //Esto me indica que al presentarse una coma o espacio se dividara la cadena
  164. char *token = strtok(c, delimitador);           //tokenizo mi char con la funcion strtok
  165. while (token != NULL){                      //Establesco un While para ingresar token por token a mi pila
  166. buscarPorFrecuencia(token);
  167. token = strtok(NULL, delimitador);
  168. }
  169.  
  170. cout << "Lista agregada correctamente\n\n";
  171.  
  172. }
  173.  
  174. //------------------------Menu interactivo------------------------------------------
  175. void menu(){
  176. int opcion;
  177. do{
  178. cout<<"\t Proyecto Supermercado\n";
  179. cout<<"(1) Insertar lista\n";
  180. cout<<"(2) Ver Tabla\n";
  181. cout<<"(3) Guardar Datos\n";
  182. cout<<"Ingrese una opcion: ";
  183. cin>>opcion;
  184.  
  185. switch(opcion){
  186. case 1:{    int lista[] = { 30,10,20,90, 30,30,40,40,40, 55,55,75,75,100,55,55 };       //Se ingresan las listas
  187. int bucle = sizeof(lista) / sizeof(lista[0]);                    // sizeof (lista) devuelve el número de bytes que ocupa la matriz. Como cada elemento puede ocupar más de 1 byte de espacio,
  188.                                                                                            //se divide el resultado con el tamaño de un elemento (sizeof (lista [0])). Esto le da un número de elementos en la matriz.
  189. OrdenarPorFrecuencia(lista, bucle);                                 //Llamo a mi funcion y envio mi lista y mi n
  190.  
  191. }break;
  192.  
  193. case 2:{ cout <<"Mostrando Datos \n";
  194. imprimir();                                               //Llamo a mi funcion imprimir
  195. }break;
  196. case 3:{guardar();                                                //Llamo a mi funcion guardar
  197. }break;
  198. }
  199. }while(opcion!=4);
  200.  
  201.  
  202.  
  203. }


En línea

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Programa que muestra la frecuencia de una lista de compras
« Respuesta #1 en: 9 Junio 2020, 20:54 pm »

Por comentar algunas cosas del código, diré lo siguiente:

Bibliotecas

  • Si trabajas con C++, utiliza siempre <iostream> para entradas/salidas y no lo mezcles con <stdio.h> que es propia de C.
  • Las biblioteca propias de C (acabadas en .h) tienen su propia versión para C++ (eliminando el .h e incluyendo una c al principio. Ej -> <cstdio>).
  • En C++ el uso de memoria dinámica no se realiza con malloc() / free() sino con new() / delete().
  • La biblioteca <conio.h> no pertenece al estándar y por tanto hay máquinas en las que da problemas. La función típica de esta biblioteca es getch() que puede y debe ser sustituida por cin.get() en C++ (<iostream>) o por getchar() en C (<stdio.h>).


Novedades de C++ frente a C

  • La diferencia fundamental entre C/C++ es la capacidad del segundo de utilizar el paradigma de programación orientado a objetos. Aunque C permite el uso de structs, están son más limitadas que las clases de C++ ya que no permiten utilizar el principio de ocultación (declarar miembros privados). Usando clases con sus miembros privados y métodos o funciones miembro públicas para interactuar con los miembros de la clase, aumentas la seguridad del programa.
  • Además, como curiosidad, me parece que en C++ se puede omitir la palabra struct si no me equivoco cada vez que se hace referencia a ese tipo de dato.
  • Otra ventana de C++ es la aparición de strings. Sobre todo para facilitar el trabajo con memoria dinámica y no tener que desperdiciar espacio reservando los char[] de manera estática. Aprovecho ahora que hablo sobre las cadenas de char para decir que cuando se define una cadena char como parámetro a una función no es necesario aportar su longitud siempre que sea de una dimensión. Son números que no aportan nada al programa y que pueden complicar las labores de modificación del código. Y las longitudes que sí tienen que estar presentes es mejor guardarlas como constantes para facilitar su modificación y mantenimiento.


Organización del Código

  • Normalmente cuando ves un programa en C/C++, si quieres ver lo que hace de un vistazo rápido, buscas la función main(). En este caso esa función no aporta nada a cualquier persona que quiera leer el código. Hay que tener un término medio entre usar funciones y no usarlas. La función menu() debería mostrar las opciones, controlar que la opción es válida (opcional) y devolver la opción elegida. Y en el main() debería llamarse a esa función y a continuación tener el código principal, es decir, el switch con las opciones.
  • Además de eso, otro mal hábito es utilizar variables globales. El uso de variables globales es excepcional y casi siempre son constantes lo que se declaran de esta manera. Las variables deberían ser locales a la función en la que van a ser necesitadas.


No me enrollo más. Esas son algunas, si no todas las cosas que yo mejoraría de ese código.
Por lo demás es un código limpio y con comentarios que explican las cosas que se hacen.

Mucha suerte en otros proyectos. :-X


En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Loretz

Desconectado Desconectado

Mensajes: 117


Ver Perfil
Re: Programa que muestra la frecuencia de una lista de compras
« Respuesta #2 en: 9 Junio 2020, 21:59 pm »

Algo que yo modificaría es la función OrdenarPorFrecuencia()

Primero haría que hiciese una sola cosa, si dice que lo que hace es ordenar la lista por frecuencia, que haga eso y nada más. Luego vendrá otra función que la muestre.

En segundo lugar, revisaría los algoritmos buscando algo más directo, más claro y, de ser posible, más eficiente. Quiero decir, le pegaría duro.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines