数字气泡排序动态创建的结构数组

时间:2018-07-29 16:23:09

标签: c struct memcpy bubble-sort

我试图弄清楚这一点,但是现在我机智了。

This是我可以找到的与问题最相关的链接,但由于结构是单个字段,因此无济于事,因此可以使用strcpy而不是memcpy(对于具有多个字段的结构)。

这是最后的代码更改,这是我唯一可以完全编译的代码。

#include <stdio.h>
#include <errno.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>

#define DIR_SIZE    400
#define FILE_SIZE   500

struct _data
{
    long int size;
    char file[FILE_SIZE + 1];
};

int fill_struct (struct _data **data, char *dir);
void sort_struct (struct _data **data, int count);

// Used for error reporting.
char *program_name = NULL;

void sort_struct (struct _data **data, int count)
{
// Declare variables.
    int i = {0};
    int j = {0};
    struct _data temp = {0};

// Bubble sort struct.
    for (i = 0; i < count; i++)
    {
        for (j = 0; j < count - i; j++)
        {
            if ((*data[j]).size > (*data[j + 1]).size)
            {
                memcpy(&temp, (&data)[j], sizeof(struct _data));
                memcpy(&data[j], &data[j + 1], sizeof(struct _data));
                memcpy(&data[j + 1], &temp, sizeof(struct _data));
            }
        }
    }
}

int main (int argc, char *argv[])
{
// Declare variables.
    int count = {0};
    struct _data *data = NULL;

// Get program name for error reporting.
    program_name = basename(argv[0]);

// Check for correct number of arguments.
    if(argc != 2)
    {
        fprintf(stderr, "usage: %s DIRECTORY\n", program_name);
        exit(EXIT_FAILURE);
    }

// Get all file info from directory.
    count = fill_struct(&data, argv[1]);

// Sort the struct based on size.
    sort_struct(&data, count);

// Free allocated memory.
    free(data);
// Exit gracefully.
    exit(EXIT_SUCCESS);
}

int fill_struct (struct _data **data, char *dir)
{
// Declare variables.
    int count = 0;
    DIR *dp = NULL;
    struct dirent *ep = NULL;
    struct _data *temp = NULL;
    struct stat file_info = {0};
    char file[FILE_SIZE + 1] = {0};

// Open directory for reading.
    if((dp = opendir(dir)) == NULL)
    {
        fprintf(stderr, "%s: fill_struct error: opendir failed (%s) (%s)\n", program_name, dir, strerror(errno));
        exit(EXIT_FAILURE);
    }

// Loop through all entries.
    while((ep = readdir(dp)) != NULL)
    {
// Skip everything but files.
        if(ep->d_type != DT_REG)
            continue;

// Increase count.
        count++;

// Build filename path.
        strcpy(file, dir);

// Add slash if needed.
        if(dir[strlen(dir) - 1] != '/')
            strcat(file, "/");

// Add filename.
        strcat(file, ep->d_name);

// Get file info.
        if(stat(file, &file_info) == -1)
        {
            fprintf(stderr, "%s: fill_struct error: stat failed (%s) (%s)\n", program_name, file, strerror(errno));
            exit(EXIT_FAILURE);
        }

// Allocate more memory for additional records.
        if((temp = realloc(*data, sizeof(struct _data) * count)) == NULL)
        {
            fprintf(stderr, "%s: fill_struct error: realloc failed\n", program_name);
            free(*data);
            exit(EXIT_FAILURE);
        }

// Store file data.
        strcpy(temp[count - 1].file, file);
        temp[count - 1].size = file_info.st_size;

// Change pointer on success.
        *data = temp;
    }

// Return total count of records.
    return(count);
}

尽管可以干净地编译,但是运行它会导致Segmentation fault (core dumped)

之前,我尝试使用(*data)[x]而不是(&data)[x],但是我永远无法使它干净地编译。

2 个答案:

答案 0 :(得分:3)

#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define FILE_SIZE   500

struct _data
{
    long int size;
    char file[FILE_SIZE + 1];
};

void sort_struct (struct _data *data, size_t count)
{
    bool swapped;
    struct _data temp;

    do {
        swapped = false;
        for (size_t i = 0; i < count - 1; ++i)
        {
            if (data[i].size > data[i + 1].size)
            {
                memcpy(&temp, &data[i], sizeof(*data));
                memcpy(&data[i], &data[i + 1], sizeof(*data));
                memcpy(&data[i + 1], &temp, sizeof(*data));
                swapped = true;
            }
        }
    } while (swapped);
}

int main(void)
{
    _data foo[]{
        {10, "theodor"},
        {13, "anja"},
        { 9, "robert"},
        {11, "nadine"},
        {15, "lucy"}
    };

    for (size_t i = 0; i < sizeof(foo) / sizeof(*foo); ++i)
        printf("%li: \"%s\"\n", foo[i].size, foo[i].file);

    sort_struct(foo, sizeof(foo) / sizeof(*foo));
    putchar('\n');

    for (size_t i = 0; i < sizeof(foo) / sizeof(*foo); ++i)
        printf("%li: \"%s\"\n", foo[i].size, foo[i].file);
}

答案 1 :(得分:2)

有几个问题:

在以下代码中:

if ((*data[j]).size > (*data[j + 1]).size)
{
    memcpy(&temp, (&data)[j], sizeof(struct _data));
    memcpy(&data[j], &data[j + 1], sizeof(struct _data));
    memcpy(&data[j + 1], &temp, sizeof(struct _data));
}

data是指向指针的指针。 data[j]是一个指针,因此&data [j]返回指向指针的指针,而不仅仅是memcpy期望得到的指针。

当您有指向指针的指针时,应首先将其转换为前缀为*的指针,然后将其用作常规指针。为避免发生尺寸错误,请在括号内使用它,例如:(*data)

应该是:

if ((*data)[j].size > (*data)[j + 1].size)
{
    memcpy(&temp, (*data)[j], sizeof(struct _data));
    memcpy((*data)[j], (*data)[j + 1], sizeof(struct _data));
    memcpy((*data)[j + 1], &temp, sizeof(struct _data));
}

为什么首先要使用指向指针的指针?

您没有2维数组,并且您没有更改分配。因此,您不应该将指针指向混乱。 因此该函数应声明为:

void sort_struct (struct _data *data, int count)

要在结构实例之间切换,可以使用常规分配而不是memcpy,例如:

temp = data[j];
data[j] = data[j+1];
data[j+1]= temp;

或如果您坚持使用指向指针版本的指针...

temp = (*data)[j];
(*data)[j] = (*data)[j+1];
(*data)[j+1]= temp;