Hack x Crack - Comunidad de Seguridad informática

Programación => C / C++ => Mensaje iniciado por: thug en Agosto 08, 2014, 07:17:13 am

Título: Vector bidimensional repite un valor en indices consecutivos al ingresar datos.
Publicado por: thug en Agosto 08, 2014, 07:17:13 am
Hola a todos. Bueno esta tarde estaba en la universidad cuando un compañero me pidió ayuda para un programa que su profesor les encargó. Yo acepté solo por que me gusta programar y con el pretexto de practicar. El chiste es que pasando la hora ya tenía el pequeño código (no soy tan bueno) pero me topé con un problema a la hora de probarlo. Explico.

El programa necesita crear un vector bidimensional de N filas y N columnas. Y otro vector unidimensional del mismo tamaño que N filas. Inicializar cada vector a 0. Que el usuario introduzca los datos de cada posición del vector bidimensional una a una y después tenga la capacidad de sumar los valores de cada fila, almacenando el resultado de cada una en su posición correspondiente dentro del vector unidimensional.

Bien ya dejando un lado todo ese rollo, pongo un ejemplo:

Vector Bidimensional 3x3

1 - 2 - 3
4 - 5 - 6
7 - 8 - 9

Partiendo de ahí para hacer la suma sería 1 + 2 + 3 = 6 y 6 sería el primer valor del vector unidimensional, y así sucesivamente. Entonces:

Vector Unidimensional

6
15
24

Ése se supone que debería ser el resultado del programa.

Ahora el fallo es que me repite el valor 4 en donde va el 3 y el 7 donde va el 7, quedando así ambos vectores:

1 - 2 - 4    |    7
4 - 5 - 7    |    16
7 - 8 - 9    |    24

Estuve haciendo un poco de análisis y al parecer si cambio el tamaño del vector, se repite el mismo comportamiento, así que de primera pense que el fallo estaba en la parte donde se imprimen los datos ya que puse un printf justo después del scanf que lee los datos del usuario para que me mostrara el dato que capturaba justo en seguida de capturarlo (el cual dejé comentado en el código que pondré enseguida).

Pero después pensé que si fuera eso, a la hora de sumarlos me daría los resultados de la suma correctamente, así que entonces supongo que el error está en la parte donde se capturan los datos, solo que no logro ver cual es el problema. Es muy probablemente un error en la lógica de mi programa, no creen?

Bueno ahora sí el código:

Código: [Seleccionar]
#include <stdio.h>
#define FILAS 3
#define COLUMNAS 3
#define line "---------------------------------------------"

int datos[FILAS][COLUMNAS]; // vector para DATOS
int resultados[FILAS];      // vector para RESULTADOS
void inicializar_vector_datos(int, int);
void inicializar_vector_resultados(int);
void entrada_datos(int, int);
void imprimir_datos(int, int);
void sumar_datos(int, int);

int main()
{
    inicializar_vector_datos(FILAS, COLUMNAS);
    inicializar_vector_resultados(FILAS);
    int opt;
    INICIO:
    puts(line);
    printf(" 1. VER DATOS\n 2. INTRODUCIR DATOS\n 3. SUMAR DATOS\n 4. SALIR\n SELECCIONE>> ");
    scanf("%d", &opt);
    puts(line);
    switch(opt)
    {
        case 1:
            imprimir_datos(FILAS, COLUMNAS);
            break;
        case 2:
            entrada_datos(FILAS, COLUMNAS);
            break;
        case 3:
            sumar_datos(FILAS, COLUMNAS);
            break;
        case 4:
            return 0;
        default:
            printf("\n OPCION NO VALIDA\n");
            goto INICIO;
    }
    goto INICIO;
    return 0;
}

//ENTRADA DE DATOS
void entrada_datos(int i, int j)
{
    printf("Entrada de datos:\n");
    for (i = 0; i <= FILAS; i++)
        for (j = 0; j <= COLUMNAS; j++)
        {
            printf("Dato [%d][%d]: ", i, j);
            scanf("%d", &datos[i][j]);
            //printf("DATO INT: %d\n", datos[i][j]);
        }
}

//IMPRIMIR DATOS
void imprimir_datos(int i, int j)
{
    for (i = 0; i <= FILAS; i++)
        for (j = 0; j <= COLUMNAS; j++)
            printf("VALOR [%d][%d]: %d\n", i, j, datos[i][j]);
}


//SUMAR DATOS
void sumar_datos(int i, int j)
{
    int contador = 0;
    while (contador <= COLUMNAS)
    {
        for (j = 0; j <= COLUMNAS; j++)
            resultados[contador] = resultados[contador] + datos[contador][j];

        contador++;
    }

    for (i = 0; i <= FILAS; i++)
        printf("Resultado Fila %d: %d\n", i, resultados[i]);

}

//inicializa vector DATOS
void inicializar_vector_datos(int i, int j)
{
    for (i = 0; i <= FILAS; i++)
        for (j = 0; j <= COLUMNAS; j++)
            datos[i][j] = 0;
}

//inicializa vector RESULTADOS
void inicializar_vector_resultados(int i)
{
    for (i = 0; i <= FILAS; i++)
        resultados[i] = 0;
}

Agrego que corro bajo un Debian, y compilo con GCC.

No es importante para mí, pero me mata la duda de saber por que no funciona!! xD
Agradecería muchísimo si alguien pudiera revisar mi código y comentarme si ven algo fuera de lugar, como dije soy un novato. Cualquier consejo, crítica, etc es bien recibida.

De antemano, gracias. Buen día.
Título: Re:Vector bidimensional repite un valor en indices consecutivos al ingresar datos.
Publicado por: C_printfer en Agosto 08, 2014, 11:49:21 am
Hola, en todas las funciones siempre pones un = en los bucles, más abajo te explico el motivo por el cual te sobra. Piensa el número de repeticiones que haces en cada bucle y el número de elementos que tienen tus arrays. Te dejo el código modificado, prueba ahora a ver si te funciona y me cuentas.
De todas formas, aunque tienes dos funciones que no sirven, cuando se realizan programas tan simples, no se suelen crear tantas funciones, ya que tiende a liar más que a aclarar. Es útil cuando hay que hacer programas complejos.

Código: [Seleccionar]
#include <stdio.h>
#define FILAS 3
#define COLUMNAS 3
#define line "---------------------------------------------"

int datos[FILAS][COLUMNAS]; // vector para DATOS
int resultados[FILAS];      // vector para RESULTADOS
//Te comento estas funciones para que no se ejecuten, veras que el resultado es el mismo
//void inicializar_vector_datos(int, int);
//void inicializar_vector_resultados(int);
void entrada_datos(int, int);
void imprimir_datos(int, int);
void sumar_datos(int, int);

int main()
{
    inicializar_vector_datos(FILAS, COLUMNAS);
    inicializar_vector_resultados(FILAS);
    int opt;
    INICIO:
    puts(line);
    printf(" 1. VER DATOS\n 2. INTRODUCIR DATOS\n 3. SUMAR DATOS\n 4. SALIR\n SELECCIONE>> ");
    scanf("%d", &opt);
    puts(line);
    switch(opt)
    {
        case 1:
            imprimir_datos(FILAS, COLUMNAS);
            break;
        case 2:
            entrada_datos(FILAS, COLUMNAS);
            break;
        case 3:
            sumar_datos(FILAS, COLUMNAS);
            break;
        case 4:
            return 0;
        default:
            printf("\n OPCION NO VALIDA\n");
            goto INICIO;
    }
    goto INICIO;
    return 0;
}

//ENTRADA DE DATOS
void entrada_datos(int i, int j)
{
    printf("Entrada de datos:\n");
    for (i = 0; i < FILAS; i++) //Sobra el =
        for (j = 0; j < COLUMNAS; j++) //Sobra el =
        {
            printf("Dato [%d][%d]: ", i, j);
            scanf("%d", &datos[i][j]);
            //printf("DATO INT: %d\n", datos[i][j]);
        }
}

//IMPRIMIR DATOS
void imprimir_datos(int i, int j)
{
    for (i = 0; i < FILAS; i++) //Sobra el =
        for (j = 0; j < COLUMNAS; j++) //Sobra el =
            printf("VALOR [%d][%d]: %d\n", i, j, datos[i][j]);
}


//SUMAR DATOS
void sumar_datos(int i, int j)
{
    int contador = 0;
    while (contador < COLUMNAS) //Sobra el =
    {
        for (j = 0; j < COLUMNAS; j++) //Sobra el =
            resultados[contador] = resultados[contador] + datos[contador][j];

        contador++;
    }

    for (i = 0; i < FILAS; i++) //Sobra el =
        printf("Resultado Fila %d: %d\n", i, resultados[i]);

}

//inicializa vector DATOS
void inicializar_vector_datos(int i, int j) //DE TODOS MODOS, ESTA FUNCION ES INNECESARIA, YA QUE LUEGO VAS A RECOGER VALORES, MACHACANDO LOS 0
{
    for (i = 0; i < FILAS; i++) //Si empiezas con i y j = 0, debes quitar el = de los bucles, ya que si no, inicializas a 0 una posicion del vector inexistente. Otra cosa seria empezar con i y j en 1
        for (j = 0; j < COLUMNAS; j++)
            datos[i][j] = 0;
}

//inicializa vector RESULTADOS
void inicializar_vector_resultados(int i) //Lo mismo que antes, innecesaria y sobra el =
{
    for (i = 0; i < FILAS; i++)
        resultados[i] = 0;
}

S2! ;D
Título: Re:Vector bidimensional repite un valor en indices consecutivos al ingresar datos.
Publicado por: thug en Agosto 08, 2014, 08:28:01 pm
Cielos, era así de sencillo! Anoche estuve haciendo una tipo tablita con los valores de cada variable en cada iteración y efectivamente me sobraría como dices tu, ya que cada vector comenzaba desde la posición 0 y yo siempre comenzaba a contar desde 1 a la hora de pensarlo. El programa funciona ya guarda los datos y opera los datos correctamente.

Debo agradecerte C_printfer, muchos me habrían dejado solo con mi sencillo problema, pero no me dejarán mentir a veces lo mas sencillo es lo mas difícil de detectar (me suele suceder xD).

Saludos!
Título: Re:Vector bidimensional repite un valor en indices consecutivos al ingresar datos.
Publicado por: C_printfer en Agosto 08, 2014, 10:45:52 pm
Jejeje pues ni si quiera lo compilé, bueno, mentalmente sí, y a mí me compilaba, aunque mi compilador mental acepta todo jajaja, el real no xDDDD

Bueno, al caso, no te preocupes por lo que tardes en lograr que el programa funcione, si yo te contara el tiempo que he estado haciendo algunas cosas... y cuando más tiempo crees que vas a tardar, menos tardas, y al revés, suele pasar. Yo he estado semanas alguna vez.

Respecto a la aclaración que me comentas por privado, no te preocupes, que no es desviar el tema...

El hecho de inicializar a 0, yo soy muy pijotero programando, y no inicializo aquello que no me va a hacer falta. Es cierto que es buena práctica hacerlo, poner todo a 0, pero imagina que tu array fuese de 1000 elementos, hay operaciones que si las puedes ahorrar es mejor (es opinión personal), ahorráis tiempo tú y el programa durante la ejecución. Nunca me ha dado algún problema no inicializar a 0 los elementos de un vector, lo que sí podría dar algún error es no inicializar alguna variable que uses en un while, por ejemplo, así que no sabes qué contiene.

En tu caso, ten en cuenta que estás metiendo todos los valores posibles, o sea, están rellenando el array valor a valor, por lo que no existe posibilidad de que se quede basura almacenada. Por eso digo, si ves que no hace falta, dependiendo del programa, pues no pongas todo a 0. No tiene más misterio jeje, es quizá más criterio personal que otra cosa.


De nada, cuanto más compilas más aprendes a ver los errores tontos, porque en el 90% de los casos en los que el dichoso programa no compila son debidos a tonterías.

Cualquier duda o lo que sea me lo dices.
Saludos. 8) :D ;)
Título: Re:Vector bidimensional repite un valor en indices consecutivos al ingresar datos.
Publicado por: thug en Agosto 09, 2014, 12:25:56 am
jajajaja Exacto! El compilador mental xDD

De hecho es verdad, solo que soy de esas personas que no se quedan tranquilas cuando dejan algo inconcluso, a veces me despierto a las 3 de la mañana con una idea, la escribo y vuelvo a dormir (mi cerebro es como una RAM xD)

Es cierto, se supone que debo hacer un código lo mas simple posible jaja solo que me apasiona la complejidad que le puedo dar a las cosas (seré masoquista? xD).
Y además de la simplicidad, en alguna parte leí que también es buena práctica evitar hacer que el ordenador ejecute operaciones de mas, tal y como lo explicas. Por cierto muy buena manera de explicar, mi profesor de programación no fué en su tiempo muy paciente con los que íbamos en clase jeje

Muy bien, mi duda fué resuelta exitosamente. De nuevo te agradezco por tu tiempo.

Saludos!