简体   繁体   中英

C: Trying to insert a struct into a struct array

in my code I have student profiles with name, age, and GPA. I also have an array with each profile. I'm trying to create an insert function that inserts another student profile into the array and display an error if the index is not valid. I'm trying to do so by moving adding another space in the array for the new student, then moving over the places of students occupying the wrong space by one space to the right.

Ex. If I want to put a student in index 2, the function would move the student occupying that space to 3, and the student in 3 would be moved to space 4.

Here's what I have so far, but I'm getting an error on array[i+1] = i saying "incompatible types when assigning to type Student from type type int." I tried changing i to type Student, I got several more errors all over the loop saying that it was an invalid initializer and that I couldn't use >=, and that i was the "wrong type to decrement

For starters it is unclear why the parameter index has the signed type int instead of the unsigned type size_t . The unsigned type allows to avoid this redundant check

if (index < 0 || index > *size) {
    ^^^^^^^^^ 

Also if the value of index is greater than the current value of *size then it is enough just to append the passed item to the array.

So in general this check

if (index < 0 || index > *size) {

is redundant.

The function declaration is too complicated. There is no need to return pointer to the first element of the passed array. The function declaration will look more simpler if to write it like

size_t insert( Student a[], size_t n, size_t i, const Student *student );

That is the function returns the new size of the updated array.

This statement

array[i+1] = i; 

does not make any sense because the left operand has the type Student while the right operand has the type int. Moreover it has a logical error because instead of the index i + 1 you have to use the index i .

And instead of the manually written loop you could use the standard C function memmove .

Here is a demonstrative program that shows how the function can be defined.

#include <stdio.h>
#include <string.h>

#define MAX_LEN 10

typedef struct Student
{
    char name[MAX_LEN];
    unsigned int age;
} Student;

size_t insert( Student a[], size_t n, size_t i, const Student *student )
{
    if ( n < i ) i = n;
    
    if ( i < n )
    {
        memmove( a + i + 1, a + i, ( n - i ) * ( sizeof( Student ) ) );
    }
    
    a[i] = *student;
    
    return ++n;
}
   
int main(void) 
{
    enum { N = 10 };
    Student a[N] = { 0 };
    
    Student student = { "A", 20 };
    
    size_t n = insert( a, 0, 0, &student );
    
    for ( size_t i = 0; i < n; i++ )
    {
        printf( "{ %s, %u } ", a[i].name, a[i].age );
    }
    putchar( '\n' );
    
    strcpy( student.name, "B" );
    ++student.age;
    
    n = insert( a, n, 0, &student );
    
    for ( size_t i = 0; i < n; i++ )
    {
        printf( "{ %s, %u } ", a[i].name, a[i].age );
    }
    putchar( '\n' );
    
    strcpy( student.name, "C" );
    ++student.age;
    
    n = insert( a, n, 2, &student );
    
    for ( size_t i = 0; i < n; i++ )
    {
        printf( "{ %s, %u } ", a[i].name, a[i].age );
    }
    putchar( '\n' );
    
    strcpy( student.name, "E" );
    ++student.age;
    n = insert( a, n, 1, &student );
    
    for ( size_t i = 0; i < n; i++ )
    {
        printf( "{ %s, %u } ", a[i].name, a[i].age );
    }
    putchar( '\n' );
    
    return 0;
}

The program output is

{ A, 20 } 
{ B, 21 } { A, 20 } 
{ B, 21 } { A, 20 } { C, 22 } 
{ B, 21 } { E, 23 } { A, 20 } { C, 22 }
  1. The used indentation style makes it difficult to easily see if the parenthesis are correctly closed. Please use an automatic formatter, example: clang-format

  2. Your function is not very safe. It should take another parameter max_size so the assigned memory is known

  3. If a return is used in if branch, the else branch does not have to be explicitly declared.

  4. A for loop already has a condition, if the only functionality in the loop is an if , it can be hoisted up into that condition.

  5. To move students from a place in an array a "copy" of the student has to be made to the new location - not just it's index.

Fixed:

Student* insert(Student* array, int max_size, int* size, int index, Student s)
{
    //error message and return NULL if space is - or > array size
    if (index < 0 || index > *size || *size + 1 > max_size)
    {
        printf("ERROR\n");
        array = NULL;
        return array;
    }

    for (int i = *size; i > index && i > 0; --i)
    {
        //move students at index or > over to make open space
        array[i] = array[i - 1];
    }

    //put new student in correct location
    array[index] = s;

    *size += 1;
    
    return array;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM