简体   繁体   English

如何在C语言中对指向结构的指针数组进行排序?

[英]How to sort an array of pointers to structures in C?

Hey guys this is my first post here and i was wondering if any of you can help me figure out how to sort array of pointers to structures. 大家好,这是我的第一篇文章,我想知道是否有人可以帮助我弄清楚如何对结构指针数组进行排序。 Here's my code and here's my assignment if anyone is interested http://i.imgur.com/yBKnZTx.png . 这是我的代码,如果有人有兴趣的话,这是我的任务。http://i.imgur.com/yBKnZTx.png

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#define MAX 50

struct address
{
   char name[50];
   char street[50];
   char citystate[50];
   char zip[20];
};

int main()
{
   struct address *ptr[50];
   struct address tptr;
   char buffer[80];
   int count = 0;

   for (int i = 0; i <MAX; i++)
   {
      ptr[i] = malloc(sizeof(struct address));

      if (gets(buffer)== NULL)
      {
         break;
      }
      else
      {
         strcpy((*ptr[i]).name, buffer);
         gets((*ptr[i]).street);
         gets((*ptr[i]).citystate);
         gets((*ptr[i]).zip);
         free(ptr[i]);
         count++;
      }
   }

   for (int x = 0; x<count; x++)
   {
      for (int y = 0; y<count - 1; y++)
      {
         if ((*ptr[y]).zip>(*ptr[y + 1]).zip)
         {
            tptr = ptr[y + 1];
            ptr[y + 1] = ptr[y];
            ptr[y] = tptr;
         }
      }
   }

   for (int i = 0; i < count; i++)
   {
      puts((*ptr[i]).name);
      puts((*ptr[i]).street);
      puts((*ptr[i]).citystate);
      puts((*ptr[i]).zip);
   }
}

Problems I see in your code: 我在您的代码中看到的问题:

  1. You are using gets . 您正在使用gets See another SO post that addresses the poblem of using gets . 请参阅另一篇SO帖子 ,它解决了使用gets的难题。 Use fgets instead. 请改用fgets

     if (fgets(buffer, sizeof(buffer), stdin)== NULL) fgets((*ptr[i]).street, sizeof((*ptr[i]).street), stdin); fgets((*ptr[i]).citystate, sizeof((*ptr[i]).citystate), stdin); fgets((*ptr[i]).zip, sizeof((*ptr[i]).zip), stdin); 
  2. You are calling free on a pointer in the following line 您在以下行中的指针上进行free调用

     free(ptr[i]); 

    and continue to use it later in the code. 并在以后的代码中继续使用它。 Remove that line. 删除该行。 Add the code to free the allocated memory at the end of the function. 在函数末尾添加代码以释放分配的内存。

     for (int i = 0; i < count; i++) { free(ptr[i]); } 
  3. You are assigning a struct address* to a variable of type struct address in the following line: 您正在分配struct address*给类型的变量struct address在下面一行:

     tptr = ptr[y + 1]; 

    and you are assigning a struct address to a variable of type struct address* in the following line: 和您正在分配struct address给类型的变量struct address*下面一行:

     ptr[y] = tptr; 

    both of them can be fixed by changing the type of tptr to struct address* . 可以通过将tptr的类型tptrstruct address*来固定它们。

     struct address *tptr; 
  4. The following code is not appropriate for comparing two strings: 以下代码不适用于比较两个字符串:

      if ((*ptr[y]).zip>(*ptr[y + 1]).zip) 

    it only compares two pointer values. 它仅比较两个指针值。 Use 采用

      if (strcmp((*ptr[y]).zip,(*ptr[y + 1]).zip) > 0) 
  1. Why do you want to free() the allocated memory once you fetch the data from the user? 从用户获取数据后,为什么要free()分配的内存?
  2. You should free() the allocated memory at the end of the program, once after the printing is done. 打印完成后,应在程序末尾free()分配的内存。
  3. struct address tptr; should be of type struct address *tptr; 应该是struct address *tptr; as you are assigning the value of the pointer. 在分配指针的值时。

Below are the changes: 1. 以下是更改:1。

for (int i = 0; i <MAX; i++)
{
    ptr[i] = malloc(sizeof(struct address));

    if (gets(buffer)== NULL)
    {
        free(ptr[i]); /* free the memory if data not read */
        break;
    }
    else
    {
        strcpy((*ptr[i]).name, buffer);
        gets((*ptr[i]).street);
        gets((*ptr[i]).citystate);
        gets((*ptr[i]).zip);
        /* Do not free the mem here as you are bound to lose the data */
        count++;
    }
}

2. 2。

for (int i = 0; i < count; i++)
{
    puts((*ptr[i]).name);
    puts((*ptr[i]).street);
    puts((*ptr[i]).citystate);
    puts((*ptr[i]).zip);
    free(ptr[i]); /* free the memory here */
}

PS : Using gets() is not a good idea. PS:使用gets()不是一个好主意。 Check this Do not use gets for more info 选中此选项不要使用获取更多信息

First, when dealing with pointer to structs, proper member access is with the -> operator (eg ptr[i]->street ). 首先,在处理指向结构的指针时,使用->运算符(例如ptr[i]->street )进行适当的成员访问。 As others have pointed out, do NOT use gets . 正如其他人指出的那样,请勿使用gets It is no longer part of the C library and was deprecated because it was insecure. 它不再是C库的一部分,并且因为不安全而被弃用。 Use fgets or getline instead. 请改用fgetsgetline

Next, (and this is a matter of form) avoid hardcoded numbers in your code. 接下来,(这是形式问题)避免在代码中使用硬编码数字。 Use #define to set your values. 使用#define设置值。 This allows easy adjustment in a single place if values change. 如果值发生变化,则可以在单个位置轻松进行调整。

With that, you were not far off with your code. 这样一来,您与代码的距离就不远了。 Making only those changes, deleting the unnecessary math.h and adding strcmp for your sort, you can sort your structures in ascending order by zip as follows: 仅进行那些更改,删除不必要的math.h并为您的排序添加strcmp ,您可以按如下所示按zip升序对结构进行排序:

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

#define MAX 50
#define MAXL 80
#define MAXZ 20

struct address {
    char name[MAX];
    char street[MAX];
    char citystate[MAX];
    char zip[MAXZ];
};

int main ()
{
    struct address *ptr[MAX];
    struct address *tptr;
    char buffer[MAXL];
    int count = 0;

    for (int i = 0; i < MAX; i++) {
        ptr[i] = malloc (sizeof (struct address));

        if (fgets (buffer, MAXL, stdin) == NULL) {
            break;
        } else {
            strncpy (ptr[i]->name, buffer, MAXL);
            ptr[i]->name[MAX - 1] = 0;
            fgets (ptr[i]->street, MAX, stdin);
            fgets (ptr[i]->citystate, MAX, stdin);
            fgets (ptr[i]->zip, MAXZ, stdin);
            count++;
        }
    }

    for (int x = 0; x < count; x++) {
        for (int y = 0; y < (count - 1); y++) {
            if (strcmp (ptr[y]->zip, ptr[y + 1]->zip) > 0) {
                tptr = ptr[y + 1];
                ptr[y + 1] = ptr[y];
                ptr[y] = tptr;
            }
        }
    }

    for (int i = 0; i < count; i++) {
        printf ("\n%s", ptr[i]->name);
        printf ("%s", ptr[i]->street);
        printf ("%s", ptr[i]->citystate);
        printf ("%s", ptr[i]->zip);
    }
}

Input 输入项

$ cat dat/sortaddress.txt
some name
my street
my city, my state
55512
another name
another street
another city, another state
44412

Use/Output 使用/输出

$ ./bin/struct_address_sort <dat/sortaddress.txt

another name
another street
another city, another state
44412

some name
my street
my city, my state
55512

note: reading with fgets or getline will read the trailing newline and include that in the buffer. 注意:使用fgetsgetline读取将读取尾随的newline并将其包括在缓冲区中。 It is a good idea to strip the newline from your strings so you don't have miscellaneous newlines at the end of your data. 最好从字符串中删除换行符,这样在数据末尾就不会出现其他换行符。 There are many examples on StackOverflow. 关于StackOverflow有很多示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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