2 Pregunta: Problemas con pasar matrices como parámetros

pregunta creada en Fri, Apr 22, 2016 12:00 AM

Soy un programador novato en C y me encuentro con un problema que es casi dolorosamente simple. Estoy escribiendo un programa básico que crea dos arrays, uno de los nombres de los estudiantes y uno de los números de identificación de los estudiantes, luego los clasifica y los imprime de varias maneras, y finalmente permite al usuario buscar los arreglos por número de ID. Aquí está el código:

#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 3
#define MAX_NAME_LENGTH 32

int main()
{   
    // Student info arrays
    char NAME[ARRAY_SIZE][MAX_NAME_LENGTH];
    int ID[ARRAY_SIZE];

    // Array for student IDs, shifted twice to the right
    int shiftedID[ARRAY_SIZE];

    // Boolean value to keep while loop running and
    // the ID search prompt repeating
    int loop = 1;

    // Counter variable for the for loop   
    int counter;
    // Gets input values for the student info arrays
    for (counter = 0; counter < ARRAY_SIZE; counter++)
    {   
        printf("Input student name: ");
        scanf("%s", NAME[counter]);

        printf("Input student ID: ");
        scanf("%d", &ID[counter]);
    }

    // Sorts the arrays
    sort(NAME, ID);

    // Prints the arrays
    print_array(&NAME, ID);

    // Shifts the ID value two bits to the right
    shiftright(ID, shiftedID);

    print_array(NAME, shiftedID);

    // Repeatedely prompts the user for an ID to
    // search for
    while(loop == 1)
    {
        search_id(NAME, ID);
    }
}

Y aquí están las definiciones de funciones:

#define ARRAY_SIZE 3
#define MAX_NAME_LENGTH 32
// Sorts the two arrays by student ID. (Bubble sort)
void sort(char **nameArray, int idArray[])
{   

    // Counter variables for the for loop
    int firstCounter = 0;
    int secondCounter = 0;
    for(firstCounter = 0; firstCounter < ARRAY_SIZE; firstCounter++)
    {
        for(secondCounter = 0; secondCounter < ARRAY_SIZE - 1;   
                secondCounter++)
        {
            if(idArray[secondCounter] > idArray[secondCounter + 1])
            {

                // Temporary variables for the sort algorithm
                int tempInt = 0;
                char tempName[32];

                tempInt = idArray[secondCounter + 1];
                idArray[secondCounter + 1] = idArray[secondCounter];
                idArray[secondCounter] = tempInt;

                strcpy(tempName, nameArray[secondCounter + 1]);
                strcpy(nameArray[secondCounter + 1],   
                      nameArray[secondCounter]);
                strcpy(nameArray[secondCounter], tempName);
            }
        }
    }
}
// Searches the ID array for a user input student
// ID and prints the corresponding student's info.
void search_id(char **nameArray, int idArray[])
{
    // A boolean value representing whether or not
    // the input ID value was found
    int isFound = 0;

    // The input ID the user is searching for
    int searchID = 0;

    printf("Input student ID to search for: ");
    scanf("%d", &searchID);

    // Counter variable for the for loop
    int counter = 0;
    while (counter < ARRAY_SIZE && isFound == 0)
    {
        counter++;
        if (idArray[counter] == searchID)
        {
            // Prints the name associated with the input ID
            isFound = 1; 
            printf("%s", nameArray[counter]);
        }
    }

    // If the input ID is not found, prints a failure message.
    if (isFound == 0)
    {
        printf("ID not found.\n");
    }
}

// Prints the name and ID of each student.
void print_array(char **nameArray, int idArray[])
{   
    // Counter variable for the for loop
    int counter = 0;

    printf("Student Name & Student ID: \n");
    for (counter = 0; counter < ARRAY_SIZE; counter++)
    {   
        printf("%s --- %d\n", nameArray[counter], idArray[counter]);
    }
} 

// Shifts the ID value to the right by two bits
void shiftright(int idArray[], int shiftedID[])
{
    // Counter variable for the for loop
    int counter = 0;
    for (counter = 0; counter < ARRAY_SIZE; counter++)
    {
        shiftedID[counter] = idArray[counter] >> 2;
    }
}

Soy consciente de que este programa es de naturaleza bastante básica y, más que nada, es un ejercicio que me permite ser más versado en un lenguaje como C. He estado trabajando en él durante algún tiempo y he trabajado a través de varios problemas, pero parece estar atascado en tres cuestiones:

  1. Si los números de ID de entrada no están ya ingresados ​​en orden, se produce un fallo de segmentación. Si los números de ID ya están ingresados ​​en orden, la función de clasificación nunca pasa a través de la instrucción if y no surgen problemas.

  2. Al pasar las matrices de nombres /ID a la función print_array, las ID se imprimen muy bien, pero los nombres se imprimirán completamente en blanco o como una serie de caracteres extraños.

  3. Al buscar por ID al final del programa, el número de ID que se ingresó primero (por lo tanto, el número en ID [0]) muestra un mensaje de ID no encontrada, donde todos los números en el índice 1 o mayor funcionará bien, aparte de los nombres correspondientes que deben imprimirse imprimiéndose en blanco, como se menciona en la segunda edición.

¡Cualquier consejo que pueda obtener sería muy apreciado! Considero que el poder detrás de los detalles finos que se necesitan en C es realmente interesante pero también muy confuso, intimidante, y eso significa que cualquier ayuda que pueda obtener hace una gran diferencia.

    
5
  1. 2D-Array no es doble puntero (char **).
    2016-04-22 03: 48: 58Z
  2. El parámetro debe ser char nameArray[ARRAY_SIZE][MAX_NAME_LENGTH] para que coincida con la matriz que está pasando. Puede omitir ARRAY_SIZE
    2016-04-22 03: 50: 35Z
2 Respuestas                              2                         

El problema es que está asumiendo que char [ARRAY_SIZE][MAX_NAME_LENGTH] y char ** son intercambiables

void sort(char **nameArray, int idArray[])

debería ser

void sort(char nameArray[][MAX_NAME_LENGTH], int idArray[])

o

void sort(char (*nameArray)[MAX_NAME_LENGTH], int idArray[])

para utilizar un puntero a una matriz de MAX_NAME_LENGTH chars, igual para su función search_id.

Echa un vistazo a pregunta 6.13 de C-FAQ

    
5
2016-04-22 04: 05: 14Z
  1. Esto resolvió rápidamente todos mis problemas. Gracias por la pronta respuesta.
    2016-04-22 05: 05: 04Z

Le aconsejaría que reestructure su programa. En lugar de almacenar dos matrices independientes para nombres e ID, puede almacenar una matriz de estructuras que contengan todos los datos necesarios:

typedef struct student
{
    int id;
    char name[MAX_NAME_LENGTH];
} student_t;

student_t students[ARRAY_SIZE];

Ahora tienes una sola matriz que nunca puede "no coincidir" al ordenar las ID sin los nombres, etc.

Puede ordenar una matriz en C usando la función de biblioteca estándar qsort() :

qsort(students, ARRAY_SIZE, sizeof(student_t), comparator);

Esto requiere que definas un comparador, que es bastante simple. Un ejemplo sería:

int comparator(const void *lhs, const void *rhs)
{
    const student_t *s1 = lhs, *s2 = rhs;
    return s1->id - s2->id;
}

Puede usar el mismo comparador con otra función de biblioteca estándar bsearch() para buscar en la matriz de alumnos una vez ordenados:

student_t key = { 42 }; // name doesn't matter, search by ID
student_t* result = bsearch(&key, students, ARRAY_SIZE, sizeof(student_t), comparator);

Estas funciones estándar son más eficientes que las que tenía y requieren que escriba mucho menos código, con menos posibilidades der errores.

    
2
2016-04-22 04: 10: 27Z
  1. Esto parece ser una forma más eficiente de escribir el programa, por lo que probablemente use algo como esto en el futuro. Excelente respuesta de cualquier manera.
    2016-04-22 05: 04: 17Z
fuente colocada aquí