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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [15] 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ... 102
141  Programación / .NET (C#, VB.NET, ASP) / Re: Corregir o quitar elementos del comBoBox en: 6 Abril 2021, 23:23 pm
Sin tener más datos sobre cómo lo has implementado, la solución más genérica que se me ocurre es comparar si el valor es igual a ":" antes de agregarlo al combobox y en caso afirmativo, ignorar ese elemento.

Viendo el código de esa parte del programa igual se puede obtener una solución más "limpia" por decirlo de alguna manera.
142  Foros Generales / Sugerencias y dudas sobre el Foro / Re: Duda a cerca de la norma de no resolver tareas a los usuarios del foro. en: 5 Abril 2021, 21:17 pm
Bueno, viendo que nos encontramos aquí todos los habituales del foro para debatir este tema, aprovecharé para dejar también mi opinión al respecto.
Desde que empecé yo en el foro y habiéndome movido en mi mayoría por subforos de programación, hubo una cosa que me llamó especialmente la atención y que ya se ha citado por ahí:
Citar
Se pregunta por conceptos abstractos. Aquí no estamos para hacerle el trabajo a nadie
Creo que de todos los temas que he leído sólo me he encontrado dos casos en los que se podría decir que se preguntó por conceptos abstractos:
1. El código es demasiado grande y se publica un ejemplo simplificado que muestre el problema -> Esto puede dar problemas si el usuario considera irrelevante algo que realmente no lo es.
2. El usuario cree que está desarrollando un programa que nadie ha hecho antes y que valdrá millones cuando lo termine por lo que no se fía de publicar el código fuente tan alegremente.
Quitando esos dos casos que han ocurrido en alguna extraña ocasión, normalmente no se pregunta por conceptos abstractos. Yo entiendo que si tienes un problema y sobre todo si estás empezando no tengas ni idea de cuál pueda ser el motivo del error así que lo mejor para todos es publicar el código tal cual (además a ser posible Ctrl+C - Ctrl+V porque luego vienen los errores al reescribirlo) porque se han dado casos de que por no publicarlo el tema acaba con un puñado de mensajes pidiendo que se publique x parte del código.

Sobre el tema de hacer o no hacer las tareas, yo sé que en ocasiones he pecado de acabar haciendo más código del que pensaba. Eso sí, como dice el-brujo, con un poco de sentido común.
Usuario recién registrado, con muy pocos mensajes y todos pidiendo la misma tarea poniendo únicamente el enunciado -> Tiene todas las papeletas de ser ignorado/eliminado o llevarse una respuesta que no es la que está buscando.
Usuario habitual o que publica su código o que tras varias respuestas se le ve con interés por aprender y que realmente hace caso de lo que se le dice (no digo que no sea crítico con las respuestas pero se ve el que quiere mejorar y el que sólo quiere que eso funcione para aprobar) -> En este caso, dependiendo del tiempo que tenga también, pues sí me explayo un poco más sobre todo para corregir cosas que aunque funcionan no se deben hacer así (a veces con el propio programa y si tiene mucha paja con un ejemplo más compacto)
Todo esto sin contar los que directamente te mandan un mensaje privado con un historia (algunas muy imaginativas) para explicarte por qué no pueden hacerlo ellos (como si fueras tú el profesor) y que si se lo haces tú -> Mi respuesta tampoco les suele gustar demasiado... :-\

Siempre se ha dicho que el que hizo la ley, hizo la trampa y todas las reglas tienen siempre sus excepciones y sus vacíos legales. En un tema como este yo creo que debe primar el sentido común y sobre todo entre habituales del foro que todos estamos aquí voluntariamente (supongo  :silbar:) y por bastante tiempo.
Y yendo al tema concreto que ha dado lugar a toda esta trama y en el que yo también participé (con fragmentos de código), se puede ver un usuario que acaba de empezar y que no utiliza ni estructuras/clases ni colecciones de datos frente a una respuesta de @XSStringManolo utilizando estructuras, contenedores de la STL, parámetros por referencia, etc. En caso de querer hacer pasar ese código como suyo, cualquier profesor que se precie un poco debería tardar menos de 2 segundos en ver que ese código no es suyo.

PD: Por encima de hacer o no hacer la tarea, mi opinión es que esa respuesta en concreto era innecesaria porque no creo que proporcione ayuda a un usuario si se añaden tantas cosas que él no utiliza (ni sabrá utilizar). Ya irá aprendiendo poco a poco hasta poder llegar a soluciones bien escaladas como esa. En cuanto a mostrarle un código bien organizado, estoy de acuerdo.
143  Programación / .NET (C#, VB.NET, ASP) / Re: Lenguaje C# VS 19 problema con Win Forms en: 5 Abril 2021, 12:55 pm
En el código del fichero .cs tienes declarada alguna clase/estructura antes de la clase que hereda de Form?
De ser así modifica el orden para que la primera clase del fichero sea la que hereda de Form.

Si lo anterior no era el causante del problema, ve al Explorador de soluciones, selecciona el fichero .cs de la vista (el designer no, el más externo) y haciendo click derecho selecciona "Excluir del proyecto". Después haz click derecho en el proyecto - Agregar - Elemento existente... y selecciona nuevamente de la carpeta del proyecto el fichero .cs.

PD: Yo recompilaría el proyecto al hacer alguno de estos cambios por si acaso. Compilar - Recompilar solución.
144  Programación / .NET (C#, VB.NET, ASP) / Re: Lenguaje C# VS 19 problema con Win Forms en: 4 Abril 2021, 23:28 pm
Si abres el "Explorador de soluciones" de VS2019 para ver la estructura del proyecto, puedes hacer click derecho en el fichero .cs que quieras modificar y elegir "Ver diseñador".
Otra opción es tener abierto el código del fichero e ir a la barra superior de VS: Ver - Diseñador (Shift + F7).

Prueba ambas opciones y nos comentas los resultados.

Buenas tardes.

No está protegido contra escritura. Puedo modificar el código, pero el Form no aparece, está el archivo "designer" pero no me muestra la ventana, solo me muestra el código. Puedo modificar la acción de los botones, pero no puedo añadir un botón dentro del form porque no aparece la ventana. En cambio si ejecuto el programa, si funciona pero no es editable porque está en ejecución.
El fichero designer muestra únicamente el código. Para ver la ventana tienes que abrir el .cs superior al designer.
Si no te aparece igual es un problema con la vista del Explorador.
145  Programación / Programación C/C++ / Re: Crash en la consola en: 4 Abril 2021, 21:05 pm
Bueno, vamos a ir viendo qué errores o mejoras hay en tu código...
  • No utilizar variables globales. Las variables globales, en contraposición con las variables locales, son las que se declaran fuera de cualquier función. Esto está desaconsejado. En todo caso se pueden utilizar para declarar constantes.
  • En la línea 11 llamas a la función bucle() pasando <a> (con valor 0) como argumento. Pasas un parámetro para ignorar su valor lo cual no debe hacerse y segundo que ese bucle no se va a ejecutar porque <estu> en ese punto vale 0 y <a> vale 1.
  • Después todo funciona normal hasta la línea 15. Aquí se llama de nuevo a bucle() y dentro de bucle() se llama a PromEdadIng() que tiene el error. Has definido que esa función devuelve un valor entero (int) pero en el caso de que se cumpla el if() no se devuelve nada.
    Si no se crea un bloque con llaves después de una estructura de control se entiende que únicamente la siguiente instrucción pertenece al bloque (no importa la indentación en C/C++).
Código
  1. // Esto:
  2. if(condicion) cout << "Hola" << endl; cout << "Adios" << endl;
  3. // es equivalente a esto:
  4. if(condicion) {
  5.  cout << "Hola" << endl;
  6. }
  7. cout << "Adios" << endl;
    En tu caso el <return edad> pertenece al bloque del else por lo que si se cumple la condición del if() no hay ningún return. Además la condición del if() va a ser siempre cierta. En C/C++ el operador '=' es el operador de asignación (asigna un valor a una variable) y si asignas a una variable cualquier valor distinto de 0, el resultado es true. El operador de comparación de igualdad es '=='.


Encontrado el error, a mejorar el código...
Primero, como ya he dicho, hay que evitar el uso de variables globales. Vamos a utilizar una constante para ver mejor su uso adecuado.
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. const int MAX_ESTUDIANTES = 10; // Como maximo el programa admitira 10 estudiantes
  5.  
  6. int main() {
  7.  int estudiantes; // variable local para el numero de estudiantes a introducir
  8.  // Ahora pedimos el numero de estudiantes y debera estar entre 1 y el maximo que hayamos definido antes
  9.  // Para ello se utiliza un filtro con un bucle do-while() que pedira un valor mientras el que se haya introducido no sea valido
  10.  do {
  11.    cout << "Introduce el numero de estudiantes [1 - " << MAX_ESTUDIANTES << "]: ";
  12.    cin >> estudiantes;
  13.  } while(estudiantes < 1 || estudiantes > MAX_ESTUDIANTES);
  14. }

Ahora toca ver el resto de la funcionalidad. Primero voy a hacerlo todo en el main() sin utilizar más funciones y después utilizando funciones para ver el proceso. Según veo en el código, el propósito es mostrar la edad promedio de los estudiantes de ingeniería.
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. const int MAX_ESTUDIANTES = 10; // Como maximo el programa admitira 10 estudiantes
  5.  
  6. int main() {
  7.  int estudiantes; // variable local para el numero de estudiantes a introducir
  8.  // Ahora pedimos el numero de estudiantes y debera estar entre 1 y el maximo que hayamos definido antes
  9.  // Para ello se utiliza un filtro con un bucle do-while() que pedira un valor mientras el que se haya introducido no sea valido
  10.  do {
  11.    cout << "Introduce el numero de estudiantes [1 - " << MAX_ESTUDIANTES << "]: ";
  12.    cin >> estudiantes;
  13.  } while(estudiantes < 1 || estudiantes > MAX_ESTUDIANTES);
  14.  
  15.  int estudios;
  16.  int edad, edadTotalIngenieria = 0; // Importante inicializar a 0 el acumulador
  17.  for(int i = 0; i < estudiantes; ++i) { // Es mejor contar desde 0 para cuando avances mas en el lenguaje
  18.    cout << "Introduce la edad del estudiante " << (i+1) << ": ";
  19.    cin >> edad; // Guardamos la edad introducida en <edad>
  20.    cout << "Introduce los estudios del estudiante " << (i+1) << "(1 - Ingenieria | 2 - Otro): ";
  21.    cin >> estudios;
  22.    if(estudios == 1) edadTotalIngenieria += edad; // Si es estudiante de ingenieria, sumamos su edad a la del resto de ingenieria
  23.  }
  24.  // Hay que convertir al menos una variable en double para que el resultado sea double y no int
  25.  double edadPromedioIngenieria = (double)edadTotalIngenieria / estudiantes;
  26.  cout << "La edad promedio de los estudiantes de ingenieria es: " << edadPromedioIngenieria << endl;
  27.  return 0; // En la funcion main() no es necesario. En el resto de funciones que devuelven algo, el return es obligatorio
  28. }

Ahora para crear una función hay que buscar un fragmento de código que forme como un bloque y que pueda ser utilizado varias veces preferiblemente. En este caso el mejor ejemplo que veo es el principio del programa. Hay un fragmento de código para pedir un valor entre dos límites y repetirse hasta que se introduce un valor válido.
Es una buena práctica que las funciones tengan verbos en su nombre para indicar lo que hacen. Por ejemplo se puede llamar pedirEstudiantesEnRango()
Código
  1. int pedirEstudiantesEnRango() {
  2.  int estudiantes;
  3.  do {
  4.    cout << "Introduce el numero de estudiantes [1 - " << MAX_ESTUDIANTES << "]: ";
  5.    cin >> estudiantes;
  6.  } while(estudiantes < 1 || estudiantes > MAX_ESTUDIANTES);
  7.  return estudiantes; // Importante devolver el valor
  8. }
  9.  
  10. int main() {
  11.  int estudiantes = pedirEstudiantesEnRango();
  12.  // el resto del programa
  13. }
En la función anterior podemos usar MAX_ESTUDIANTES sin pasarlo como argumento porque es una constante global. Sin embargo, ¿qué pasaría si en algún momento del programa queremos pedir un número de estudiantes en otro rango? Habría que cambiar todo el programa. Entonces podemos agregar parámetros para indicar el mínimo y el máximo.
Código
  1. int pedirEstudiantesEnRango(int minimo, int maximo) {
  2.  int estudiantes;
  3.  do {
  4.    cout << "Introduce el numero de estudiantes [" << minimo " - " << maximo << "]: ";
  5.    cin >> estudiantes;
  6.  } while(estudiantes < minimo || estudiantes > maximo);
  7.  return estudiantes; // Importante devolver el valor
  8. }
  9.  
  10. int main() {
  11.  int estudiantes = pedirEstudiantesEnRango(1, MAX_ESTUDIANTES);
  12.  // el resto del programa
  13. }
Como se ve en el código anterior, si se utilizan parámetros es para pasar valores necesarios de una función a otra.

A partir de todo esto ya te toca seguir a ti y siempre puedes preguntar de nuevo si tienes algún problema o alguna duda.
Suerte.  :-X

PD: Las dos siguientes líneas son iguales con la diferencia de que la primera se entiende mejor que la segunda...
Además, si cuentas el bucle for() desde 0, no hace falta ni restar 1. ;) ;)
Código
  1. int retorno = f() - 1;
  2. int retorno = (1 - f()) * -1;
146  Programación / Programación C/C++ / Re: Mediana en un Array en: 2 Abril 2021, 23:58 pm
La media no es lo mismo que la mediana.
La mediana es el valor central de un conjunto de datos ordenados. En el caso de tener dos elementos centrales, la mediana es la media de los dos.

El proceso sería:
1 - Ordenar el vector
Siendo n el número de elementos del vector:
2.1 - Si n es impar, la mediana es el elemento (n+1)/2 del vector ordenado
2.2 - Si n es par, la mediana es la media entre el elemento (n/2) y (n/2+1)

Para una ayuda más concreta debes postear tu código (entre etiquetas de Código GeSHi). Las etiquetas de Código GeSHi las puedes seleccionar en el desplegable que dice "Código GeSHi" encima del cuadro de texto o escribiendo directamente:
[code=X]
Tu código aquí
[/code]
* Sustituye 'X' por 'cpp' para código C++ o por 'c' para código C.
147  Programación / Scripting / Re: Quiero aprender Shell-script con bash en: 29 Marzo 2021, 14:50 pm
Saludos,

Supongo que estás buscando algo recomendado desde cero y muy fácil de entender, yo te recomiendo estas guías (están en español):

Módulo I. Órdenes UNIX y Shell Bash

Sesión Nº1: Introducción a un entorno gráfico de Unix
http://www.ugr.es/~benghazi/practica/Sesion1.pdf

Sesión Nº2: Órdenes de UNIX/Linux (Parte I)
http://www.ugr.es/~benghazi/practica/Sesion2.pdf

Sesión Nº3: Permisos y redirecciones
http://www.ugr.es/~benghazi/practica/Sesion3.pdf

Sesión Nº4: Variables, Alias y Órdenes de Búsqueda
http://www.ugr.es/~benghazi/practica/Sesion4.pdf

Sesión Nº5: Expresiones con variables y expresiones regulares
http://www.ugr.es/~benghazi/practica/Sesion5.pdf

Sesión Nº6: Programación del shell
http://www.ugr.es/~benghazi/practica/Sesion6.pdf

Sesión Nº7: Depuración y Control de trabajos
http://www.ugr.es/~benghazi/practica/Sesion7.pdf

Con eso ya vas a tener una buena base para manejarte en Linux y Bash

 :o :o Acabo de volver 4 años atrás... Que recuerdos me acaban de venir de cuando empecé a estudiar en la UGR con estos mismos apuntes.
Recuerdo que pasé noches practicando con todos esos comandos y con algún que otro dolor de cabeza (ya no sé si sería cosa de los apuntes o porque yo no tenía ni idea por aquel entonces  :xD)

Son de los pocos apuntes en pdf que imprimí y que aún conservo.

Perdón por salirme del tema. Y mucha suerte y ánimo a los que estén empezando ahora con ello. Al final se le coge mucho cariño a la Terminal  ;D
148  Programación / .NET (C#, VB.NET, ASP) / Re: ¿Cómo listar solo unidades DVD y ver su información? en: 28 Marzo 2021, 13:59 pm
Te dejo dos opciones que te pueden servir. Ambas están sacadas del siguiente link: https://bytes.com/topic/c-sharp/answers/257251-how-detect-hard-drives

  • Opción 1
Código
  1. using System;
  2. using System.Runtime.InteropServices;
  3.  
  4. public class ListDrives {
  5.  
  6.  public enum DriveType : int {
  7.    Unknown = 0,
  8.    NoRoot = 1,
  9.    Removable = 2,
  10.    Localdisk = 3,
  11.    Network = 4,
  12.    CD = 5,
  13.    RAMDrive = 6
  14.  }
  15.  
  16.  [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  17.  public static extern int GetDriveType(string s);
  18.  
  19.  public static void Main(string[] args) {
  20.    foreach(string s in Environment.GetLogicalDrives())
  21.      Console.WriteLine(string.Format("Drive {0} is a {1}", s, Enum.GetName(typeof(DriveType), GetDriveType(s))));
  22.  }
  23. }

  • Opción 2:
Código
  1. using System;
  2. using System.Management;
  3.  
  4. public class ListDrives {
  5.  public static void Main(string[] args) {
  6.    string query = "SELECT * FROM win32_logicaldisk";
  7.    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
  8.    foreach(ManagementObject obj in searcher.Get())
  9.      Console.WriteLine("Objeto: " + obj.GetText(TextFormat.Mof)); // Aqui tendrias que filtrar segun DriveType
  10.  }
  11. }
149  Programación / Scripting / Re: listar archivos a texto con formato en: 26 Marzo 2021, 23:50 pm
Si te sirve de ayuda, te puedo decir cómo hacerlo utilizando los comandos de Linux (se pueden usar desde Windows instalando Cygwin):
Código:
ls *.jpg | tr '\n' ' ' > salida.txt
Básicamente sería:
1. Mostrar todos los ficheros .jpg del directorio actual (ls *.jpg)
2. Sustituir el salto de línea por un espacio (tr '\n' ' ')
3. Guardar la salida en el fichero salida.txt (> salida.txt)

No sé si habrá algún equivalente al comando tr en Windows.
150  Programación / Programación C/C++ / Re: [C++] Series de Taylor: sen(x) en: 26 Marzo 2021, 22:36 pm
El problema de que te muestre nan como resultado es porque estás calculando números demasiado grandes. Realizar una serie de Taylor para el sen(x) con una precisión de 360 (como estás calculando tú) es una locura.
Llamando precisión al número de elementos de la serie que se calculan, tenemos lo siguiente:
Código:
Elemento 1: denominador = 1! = (1 * 2 - 1)!
Elemento 2: denominador = 3! = (2 * 2 - 1)!
Elemento 3: denominador = 5! = (3 * 2 - 1)!
Elemento 4: denominador = 7! = (4 * 2 - 1)!
...
Elemento 360: denominador = (360 * 2 - 1)! = 719!
Puedes intentar calcular 719! a ver qué pasa...

Una precisión de 10 es más que suficiente para una aproximación decente.
Dicho esto volvamos con el código en sí. La cosa es calcular cada uno de los elementos de la serie correctamente. Empezamos.
La estructura general del programa es la siguiente:
Código
  1. #include <iostream>
  2. #include <cmath>
  3.  
  4. using namespace std;
  5.  
  6. const int PRECISION = 10;
  7.  
  8. int main() {
  9.  double x = 2; // Un valor cualquiera para calcular sen(x)
  10.  
  11.  double resultado = 0;
  12.  for(int i = 0; i < PRECISION; ++i) {
  13.    resultado += signo * numerador / denominador;
  14.  }
  15.  
  16.  cout << "El resultado aproximado de sen(" << x << ") es: " << resultado << endl;
  17.  cout << "El resultado real de sen(" << x << ") es: " << sin(x) << endl;
  18. }
Ahora falta calcular cada una de las variables (signo, numerador, denominador).

Para calcular el signo, como ya te dije, basta con ir multiplicando por -1 en cada iteración.
Código
  1. //...
  2. int signo = 1; // Empezamos con 1 porque el primer elemento es positivo
  3. for(int i = 0; i < PRECISION; ++i) {
  4.  resultado += signo * numerador / denominador;
  5.  signo *= -1; // Cambiamos el signo a -1 para la siguiente iteracion
  6. }
  7. //...

Ahora para calcular el numerador, como ya dije también, hay que darse cuenta de que en cada iteración está elevado a un exponente 2 veces mayor.
Código:
Elemento 1: numerador = x^1 = x ^ (1 * 2 - 1)
Elemento 2: numerador = x^3 = x ^ (2 * 2 - 1)
Elemento 3: numerador = x^5 = x ^ (3 * 2 - 1)
...
La primera opción es calcular:
Código
  1. for(int i = 0; i < PRECISION; ++i) {
  2.  numerador = pow(x, i * 2 - 1);
  3.  //...
  4. }
Pero esto requiere demasiados cálculos innecesarios. Como ya dije:
Citar
Lo mismo pasa con una potencia: si tienes x y lo multiplicas por x, ya tienes x^2. Si x^2 lo multiplicas por x, ya tienes x^3 y así sucesivamente también.
Entonces la mejor opción es:
Código
  1. //...
  2. double numerador = x; // El primer numerador es x^1 entonces lo dejamos ya almacenado
  3. for(int i = 0; i < PRECISION; ++i) {
  4.  resultado += signo * numerador / denominador;
  5.  signo *= -1; // Cambiamos el signo a -1 para la siguiente iteracion
  6.  numerador *= (x * x); // Si tenemos x^1 y lo multiplicamos por x^2 (x*x), obtenemos x^3
  7. }
  8. //...

Y ya sólo quedaría el denominador. Vuelvo a mencionar lo que dije en el mensaje anterior:
Citar
Piensa que si en una iteración tienes 1! y lo multiplicas por 2, ya tienes 2!. Si 2! lo multiplicas por 3, ya tienes 3!; y así sucesivamente sin tener que hacer todas las operaciones en cada iteración.
Aquí también podríamos calcular el factorial de (2^n-1) pero volverían a ser un montón de cálculos innecesarios. Vamos a ver cómo funcionan los factoriales otra vez:
Código:
Elemento 1: denominador = 1! = (1 * 2 - 1)!
Elemento 2: denominador = 3! = (2 * 2 - 1)! = 1! * 2 * 3
Elemento 3: denominador = 5! = (3 * 2 - 1)! = 3! * 4 * 5
Elemento 4: denominador = 7! = (4 * 2 - 1)! = 5! * 6 * 7
...
Como ves, si en la primera iteración tenemos 1!, luego hay que multiplicar por 2 y por 3 para conseguir 3!. Para conseguir el 5! como ya tenemos 3! sólo hay que multiplicar por 4 y por 5 y así sucesivamente.
Código
  1. //...
  2. double denominador = 1; // El primer denominador es 1! (1) entonces lo dejamos ya almacenado
  3. for(int i = 0; i < PRECISION; ++i) {
  4.  resultado += signo * numerador / denominador;
  5.  signo *= -1; // Cambiamos el signo a -1 para la siguiente iteracion
  6.  numerador *= (x * x); // Si tenemos x^1 y lo multiplicamos por x^2 (x*x), obtenemos x^3
  7.  denominador *= ((i+2) * 2 - 2) * ((i+2) * 2 - 1);
  8. }
  9. //...
Tenemos que sumar 2 a i porque al empezar en 0, obtendríamos números negativos en las primeras iteraciones. Este valor que se suma a i dependerá del número (i) con el que se empiecen a contar las iteraciones.
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [15] 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ... 102
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines