Структура Расположение в C - PullRequest
0 голосов
/ 30 ноября 2018

Я пытаюсь создать программу, которая будет упорядочивать мои структуры по идентификаторам людей.Я использовал long double, потому что идентификаторы имеют длину 20 цифр.Например, если я представлю 3 человека:

1.Alex Alex / id = 219(...)
2.John John / id = 200(...)
3.Robert Robert / id = 199(...)

Я хочу, чтобы моя программа переставила так, чтобы Роберт был первым, Джон - вторым, а Алекс - третьим.У меня проблема со структурой "for" - я точно не знаю, как поменять две структуры, поскольку у меня объединены символы и целые.

typedef struct 
{
    char name;
    char prename;
    long double id;
    int j;
} PERSON;

int main() 
{
    int n,i,j;
    printf ("How many people = ");
    scanf("%d", &n);
    PERSON v[n];
    for(i=1;i<=n;i++)
    {
        printf("For person number nr. %d\n", i);
        printf("name = ");
        scanf("%s", &v[i].name);
        printf("Prename = ");
        scanf("%s", &v[i].prename);
        printf("id = ");
        scanf("%d", &v[i].id);
    }

    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n-1; j++)
        {
            if( v[i].id > v[j+1].id )
            {
                int temp = v[j].id;
                char temp2[100];
                char temp3[100];

                strcpy(v[j].prename,temp3);
                strcpy(v[j].name,temp2);
                v[j].id = v[j+1].id;
                v[j+1].id = temp;
            }
        }
    }

    return;
}

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Хорошо, потому что вы сделали так много вещей, которые не очевидны для нового разработчика C, я хочу указать на них, чтобы помочь вам выучить:

typedef struct 
{
    // These need to be arrays if they are to be strings
    // Preferably using a constant for size or dynamic
    // if you want them to be variable sized to match input.
    char name;
    char prename;
    // Do not use floating point numbers to represent integer values.  
    // IRL, you'd use a library, but here, you may want to use an array of 
    // some sort of integer type instead.
    long double id;  

    // This is a really poor name for a struct variable and probably shouldn't be here.
    int j;
} PERSON;

int main() 
{
    int n,i,j;
    printf ("How many people = ");
    // Dropping raw output from scanf into a memory allocation is crazy dangerous.
    // At least error check the results to be sure it is meaningful.
    scanf("%d", &n);
    // This is a variable length array and often is not supported directly.
    // You probably want to use a malloc()/free() pair to handle this.
    // (Update: VLA is now part of newer standards, but are not safe because they cannot fail gracefully on out of memory.)
    PERSON v[n];

    // Anytime in C I see an array start at 1 and use <= for condition, I get very nervous because
    // it tends to lead to indexing errors.
    for(i=1;i<=n;i++)
    {
        printf("For person number nr. %d\n", i);
        printf("name = ");

        // Oops - and this is why.  You just skipped the first entry at 0
        // and will overwrite memory on the last loop.
        // Also, scanf into a string without a length can blow up memory...
        scanf("%s", &v[i].name);
        printf("Prename = ");
        // Ditto
        scanf("%s", &v[i].prename);
        printf("id = ");
        // Ditto - worse because you've crossed your types - %d doesn't go into a long double.
        scanf("%d", &v[i].id);
    }

    // Should be its own function to make it easier to swap later to a better sort.
    for(int i=0; i<n; i++)
    {
        // Bubble sort usually wants j=i here.
        for(int j=0; j<n-1; j++)
        {
            if( v[i].id > v[j+1].id )
            {
                // Make a swap function here.  Makes it clearer what you want to do.
                int temp = v[j].id;

                // What is 100?  How do you know that is enough?
                // These are called magic numbers and lead to code death.
                char temp2[100];
                char temp3[100];

                // Ah, strcpy - 3 things wrong here.
                // 1 - You have the parameters backwards - you are copying temp3 to your struct.
                // 2 - You have no way to know if the destination will fit the source because it copies until it finds a '\0' - very dangerous.
                // 3 - Because your parameters are backwards and temp123 is not initialized, this very well could copy forever.
                // strncpy (also crazy dangerous) at the least should be used and consider using better means like strlcpy() and such.
                strcpy(v[j].prename,temp3);
                strcpy(v[j].name,temp2);
                v[j].id = v[j+1].id;
                v[j+1].id = temp;

                // You kinda forgot to swap the strings, but the program is already dead so no worries.
            }
        }
    }

    // Please enable compiler warnings - you must return a value here.
    return;
}

Серьезно, яЯ уверен, что пропустил несколько других вещей, но этого достаточно для бесплатного просмотра кода в интернете и обучения.:)

Информация о strcpy () и strncpy () Почему strncpy небезопасен?

Информация о безопасности scanf () Как предотвратить сканирование, вызывающее буферпереполнение в C?

Информация о безопасности массива переменной длины: Безопасно ли использовать массивы переменной длины?

0 голосов
/ 30 ноября 2018

Основная проблема с вашим кодом здесь:

typedef struct
    char name;      <--- just a char! no room for a string
    char prename;   <--- just a char! no room for a string
    long double id;
     int j;
    } PERSON;

Вам нужно сделать эти массивы так, чтобы они могли содержать имена.

Как:

#define MAX_NAME_LEN 100

typedef struct {
    char name[MAX_NAME_LEN];
    char prename[MAX_NAME_LEN];
    long double id;
    int j;
} PERSON;

Кроме того, вы всегда должны проверять значение, возвращаемое scanf и , никогда do scanf("%s", &v[i].prename);, так как это может привести к переполнению буфера.Вместо этого сделайте scanf("%99s", v[i].prename);, но еще лучше используйте fgets

А для сортировки ... просто используйте qsort - см. http://man7.org/linux/man-pages/man3/qsort.3.html

Кстати: A long double не может бытьсканирование с использованием scanf("%d", &v[i].id); - %d для целых чисел.Тем не менее, я сомневаюсь, что вы хотите использовать long double.Вы, вероятно, хотите какой-то тип интергера - может быть long long unsigned или uint64_t

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...