Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - K-YreX

#281
Lo que veo son varios problemas de acceso y eso es lo que está generando tu problema.

Función lectura():
  • Si el bucle de la línea 31 sale porque j == C, en la línea 37 tienes un acceso a memoria fuera de los límites del array.
  • Si el bucle de la línea 29 sale porque i == F, en la línea 42 tienes otro acceso fuera del array.

    Además no sé si es obligatorio que hagas así la lectura pero sino es mucho mejor que uses la función fgets():

    // Guarda el contenido de un archivo en un array bidimensional por lineas y devuelve el numero de lineas leidas
    int lectura(char array[][C]){
      FILE *archivo = fopen("loquesea.txt", "r");
      int fila = 0;
      // fgets guarda C-1 caracteres de una linea del archivo y pone '\0' al final
      while(fila < F && fgets(array[fila], C, archivo)) ++fila;
      return fila;
    }


    Y en la función auxiliares() tienes los mismos problemas que en lectura() además de que no controlas el límite de líneas leídas. Si el array tiene 2 filas y el fichero tiene n filas estás realizando n-2+1 accesos a memoria fuera del array.
    Al ejecutarse la línea 74, el programa se detendría si intenta acceder a memoria fuera del ámbito de tu ejecutable. Si no se detiene está modificando algo y en tu caso ese algo es el elemento arreglo[0][0].
#282
Buscando CTF (Capture The Flag) en Internet no deberías de tener problemas para encontrar lugares similares.
Si te aparecen enlaces al tradicional juego de capturar la bandera, añade "hacking" o algo por el estilo a la búsqueda.

Espero que te sirva.
Suerte.
#283
Cita de: gomezjuan en 18 Mayo 2020, 18:05 PM
Muchas gracias, no entiendo muy bien a que te refieres con la primera linea la de validar monomio.
La estructura del monomio seria así?
struct monomio {
int coeficiente;
int exponente;
};

Y como puedo guardar los monomios en la estructura?

La primera línea era solo para definir una función llamada validarMonomio() que recibe como parámetro un string y devuelve un Monomio. El prototipo de la función sería:
Código (cpp) [Seleccionar]
Monomio validarMonomio(string monomio);




Para usar la struct Monomio:
Código (cpp) [Seleccionar]

struct Monomio {
  int coeficiente;
  int exponente;
};

int main(){
  Monomio mon;
  int coeficiente = 2, exponente = 5;
  mon.coeficiente = coeficiente;
  mon.exponente = exponente;
}


También puedes crear constructores, gets()/sets(),... Incluso crear una class para hacer los atributos privados y manejar los objetos a partir de los métodos.
#284
Cita de: gomezjuan en 18 Mayo 2020, 13:39 PM
La estructura que debe tener el monomio es:
```
1. Signo + o -
2. COEFICIENTE: uno o mas dígitos enteros (0,...,9)
3. x
4. signo ^
5. EXPONENTE: uno o mas dígitos enteros (0,...,9)
```

Esta estructura que dices que debe cumplirse no se cumple. Casos:
  • Término independiente -> solo tiene signo y coeficiente.
  • Monomio grado 1 -> solo tiene signo, coeficiente y x.




    De todas maneras, una vez que ya lo tienes separado en monomios, te digo cómo puedes validar cada uno de estos. Mi recomendación es que crees una clase Monomio con coeficiente y exponente. Así podrás manejar los datos fácilmente y no desperdigarlos. Una idea del algoritmo sería:

    validarMonomio(string) : Monomio // Funcion que recibe un string (monomio) y devuelve un objeto de tipo Monomio
    INICIO
      exponente = 0 // Exponente por defecto
      i := 1 // El 0 ya sabes que es '+' o '-'
      // Calcular la longitud del coeficiente:
      MIENTRAS i < monomio.size() AND es_digito(monomio[i]) HACER // Recuerda la primera condicion para no salirte del string
        i := i + 1
      FIN MIENTRAS
      SI i = 1 ENTONCES // No hay digitos despues del signo
        Mostrar Error
        Salir
      FIN SI
      coeficiente = monomio.substring(0, i)  // Ya tienes el COEFICIENTE y con signo

      // Comprobar si es el termino independiente:
      SI i < monomio.size() ENTONCES // Si no acaba ahi y entonces no es el termino independiente...
        SI monomio[i] != 'x' ENTONCES // ...debe continuar con una 'x'
          Mostrar Error
          Salir
        FIN SI
        coeficiente = 1 // y ahora el coeficiente por defecto sera 1, no 0
        i := i + 1

        // Si no acaba con la x, tiene que seguir '^' y el exponente
        SI i < monomio.size() ENTONCES
          SI monomio[i] != '^' ENTONCES
            Mostrar Error
            Salir
          FIN SI

          // Procedemos a calcular el exponente
          i := i + 1
          inicio := i
          MIENTRAS i < monomio.size() AND es_digito(monomio[i]) HACER
            i := i + 1
          FIN MIENTRAS
       
          // Si no hay digitos despues de '^' o hay algo mas despues de los digitos, esta mal
          SI i = inicio OR i < monomio.size() ENTONCES
            Mostrar Error
            Salir
          FIN SI
          exponente = monomio.substring(inicio, i) // Ya tienes el EXPONENTE
        FIN SI
      FIN SI

      RETURN new Monomio(coeficiente, exponente)
    FIN


    Es un poco largo pero no lo podía probar así que he ido separando y explicando cada posible situación para procurar no dejarme nada.
    Ahora pásalo a C++ y si te da algún problema, coméntalo.
    Suerte.

    PD: Además puede darse que tengas varios monomios del mismo grado (como en tu ejemplo: -4 y +1). Una vez separados todos, deberías comprobarlo y juntarlos.
#285
Programación C/C++ / matriz transpuesta c
18 Mayo 2020, 15:09 PM
El mensaje 'matriz transpuesta c  ' fue bloqueado
Reapertura de tema antiguo
Leer reglas:
http://foro.elhacker.net/reglas
#286
Además de la opción que ya te ha dado EdePC para la que no necesitas de funciones preexistentes; hay otras opciones como utilizar la función strtok(): https://en.cppreference.com/w/cpp/string/byte/strtok que permite separar una cadena de caracteres en base a una serie de limitadores que puedes establecer tú (en este caso: "a").

Fíjate en su uso ya que es un poco peculiar.

Suerte.
#287
El problema está en que en la parte de verificar si son iguales o no, lo que realmente estás haciendo es comprobar si el último elemento de la matriz es igual o no. Para comprobarlo correctamente puedes hacerlo declarando una variable de tipo bool y usándola como condición de salida de los bucles:
Código (cpp) [Seleccionar]

bool iguales = true;
for(int i = 0; i < filas && iguales; ++i){
  for(int j = 0; j < columnas && iguales; ++j){
    iguales = (matriz1[i][j] == matriz2[i][j]);
  }
}

if(iguales)
  cout << "Las matrices son iguales" << endl;
else
  cout << "Las matrices no son iguales" << endl;




Además de eso, otras mejoras serían:
  • No utilizar un char[] para guardar la respuesta. Si solo es un carácter, usa un char.
  • Para comparar varias cadenas char[] es mejor usar strncmp() que strcmp(). La primera permite indicar la cantidad de caracteres a comparar.
  • C++ tiene la ventaja de las variables tipo <string>. Úsalas y te ahorrarás quebraderos de cabeza con char[].
  • Declara el tamaño de las matrices como constantes. Así podrás modificar su tamaño modificando el valor en un único lugar.
    Código (cpp) [Seleccionar]

    // cabeceras...
    const int FILAS = 3;
    const int COLUMNAS = 3;

    int main(){
      int matriz[FILAS][COLUMNAS];
      //...
    }


  • Para pedir los valores al usuario, utiliza un bucle. Así valdrá para cualquier tamaño y te ahorras las variables auxiliares:
    Código (cpp) [Seleccionar]

    for(int i = 0; i < FILAS; ++i){
      for(int j = 0; j < COLUMNAS; ++j){
        cout << "Introduce el valor M[" << i << "][" << j << "]: ";
        cin >> matriz[i][j];
      }
    }
#288
Hay varias incorrecciones pero digamos que el problema principal está en el operador =. Cuando se trabaja con punteros el operador = hace que el puntero de la izquierda apunte a la dirección de memoria que se especifique a la derecha.
En tu caso, cada uno de los punteros del array <array> están apuntando a la dirección de memoria de <input> e <input> contiene la última cadena introducida por la entrada estándar. Por lo tanto, todos los punteros del array están apuntando a una misma cadena, cuando muestras todas en el último bucle estás mostrando la misma cadena (<input>) n veces.

Otro error es el de usar un array de punteros. Como ves esto no sirve pues todos los punteros acabarán apuntando a un mismo sitio y cuando cambies el valor de esa variable, perderás todos los anteriores.
La solución: usar una matriz. Cada fila será una entrada y cada columna un carácter.

#define MAX_ENTRADAS 20 // Numero maximo de entradas por teclado
#define MAX_LONGITUD 50 // Longitud maxima de cada entrada

int main(){
  char matriz[MAX_ENTRADAS][MAX_LONGITUD];
}

Aprovecho el código para decirte que utilices mejor constantes. Así si en algún momento quieres cambiar un valor, solo tendrás que cambiarlo en el lugar en el que lo has declarado.

Además de eso, otra incorrección es utilizar sscanf() para eliminar el salto de línea final (que supongo que lo haces para eso). Esto no es válido porque sscanf() no recoge los espacios por lo que una cadena con espacios (ej: "hola mundo") la truncará al primer espacio que encuentre ("hola").
Una alternativa para hacerlo es la siguiente:

#define SIZE 100
//...
char entrada[SIZE];
fgets(entrada, SIZE, stdin);
if(entrada[strlen(entrada)-1] == '\n') // el ultimo caracter siempre es '\0'. Entonces si el anterior es un salto de linea '\n'...
  entrada[strlen(entrada)-1] = '\0'; // ... le pones el fin de cadena uno antes para eliminar el '\n'


Otra cuestión es el tema de comparar cadenas. Si utilizas strcmp() y usas una longitud máxima de 5, al escribir "exit\n" solo se va a guardar "exit" y al compararlo no va a coincidir. Por esto es más seguro utilizar strncmp():
strncmp(matriz[n], "exit\n", strlen(matriz[n]))
Así compararás tantos caracteres como tenga la primera cadena. Si introduces "exit\n" y solo se guarda "exit", se compararán los 4 primeros caracteres de cada cadena y por tanto saldrá del bucle. Además si introduces "ex" pensando que va a comparar los dos primeros de la cadena, no saldrá porque comparará "ex\n" con "exi".

Y para futuras ocasiones, para copiar el contenido de una cadena en otra, tienes que utilizar las funciones strcpy() o strncpy(). Recomendable usar la segunda ya que puedes especificar la longitud.

Dicho esto puedes utilizar algo así:

while(n < MAX_ENTRADAS && fgets(matriz[n], MAX_LONGITUD, stdin) && strncmp(matriz[n], "exit\n", strlen(matriz[n]))){
    if(matriz[n][strlen(matriz[n])-1] == '\n')
        matriz[n][strlen(matriz[n])-1] = '\0';
    ++n;
}

Como puedes ver te ahorras los otros arrays auxiliares. Y debes comprobar primero que n no sobrepase el límite de entradas para que matriz[n] no produzca un error en memoria al intentar acceder a espacio de memoria no permitido.
#289
Para guardar cualquier información en un archivo tienes que realizar los siguientes pasos:
  • Incluir los archivos de cabecera necesarios:
    Código (cpp) [Seleccionar]

    #include <iostream> // Para entrada y salida de datos: cout / cin
    #include <fstream> // Para flujos de entrada (ifstream) y salida (ofstream)
    #include <cstdlib> // Para la funcion exit() y la constante EXIT_FAILURE

    using namespace std;


  • Abrir el flujo de salida:
    Código (cpp) [Seleccionar]

    string nombreFichero = "salida.txt";
    ofstream fichero(nombreFichero);

    Puedes definir una ruta en el nombre del archivo si quieres que se cree en otra diferente a la actual.

  • Comprobar que se ha abierto correctamente:
    Código (cpp) [Seleccionar]

    if(!fichero){
      cout << "Error al abrir el fichero: " << nombreFichero << endl;
      exit(EXIT_FAILURE);
    }


  • Guardar los datos que quieras en el fichero:
    Código (cpp) [Seleccionar]

    for(size_t i = 0; i < filas; ++i){
      for(size_t j = 0; j < columnas; ++j){
        fichero << matriz[i][j] << "  ";
      }
      fichero << endl;
    }


  • Cerrar el flujo:
    Código (cpp) [Seleccionar]
    fichero.close();
#290
Problema 1: la variable <fila> no está inicializada. Tienes que darle un valor. No puedes crear la matriz primero en la línea 9 y pedir el número de filas que tendrá en la función que llamas después (línea 10).
Además es recomendable que utilices constantes o variables para guardar los datos, por ejemplo, el 3. Así si quieres cambiar dicho valor solo tendrás que cambiarlo en el lugar en el que declaras la variable/constante y no a lo largo de todo el programa. Digamos que es una buena práctica.

Consejo: Si la función es llenar(), que se encargue únicamente de rellenar la matriz. No tiene sentido que metas todo el programa dentro de dicha función. Separando el programa correctamente en funciones te será más fácil encontrar posibles errores en el futuro o poder hacer modificaciones en tu código.

Problema 2: El método para ordenar la matriz.
Lo mejor es tratar la matriz como un array unidimensional. Puedes utilizar un único índice que recorra todos los elementos.
Código (cpp) [Seleccionar]

for(int i = 0; i < FILAS * COLUMNAS; ++i){
  cout << "Fila: " << i / COLUMNAS << " - Columna: " << i % COLUMNAS << endl;
}


Utilizando esto puedes implementar el algoritmo burbuja como si de un array unidimensional se tratara. Te dejo el pseudocódigo para que lo conviertas a C++:

PARA i := 1 HASTA filas * columnas - 1 INCREMENTO 1 HACER
  PARA j := 0 HASTA filas * columnas - 2 INCREMENTO 1 HACER
    SI M[j / columnas][j % columnas] > M[(j+1) / columnas][(j+1) % columnas] ENTONCES
      swap(M[j / columnas][j % columnas], M[(j+1) / columnas][(j+1) % columnas])
    FIN SI
  FIN PARA
FIN PARA


Prueba a implementar el algoritmo en C++. Seguro que funciona.


PD: Al poner en el pseudocódigo (filas * columnas - 1) se incluye dicho valor. En C++ sería equivalente poner cualquiera de las dos siguientes expresiones:
Código (cpp) [Seleccionar]

for(int i = 1; i < filas * columnas; ++i){...}
for(int i = 1; i <= filas * columnas - 1; ++i){...}