微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在C中将结构的哪个成员的指定符传递给函数

如何解决如何在C中将结构的哪个成员的指定符传递给函数

我有很多记录,每个记录由4个参数(id,field1,field2,field3)组成。记录包含在称为<!DOCTYPE html> <html> <head> <title>Save form Data in a Text File using JavaScript</title> <style> * { Box-sizing: border-Box; } div { padding: 10px; background-color: #f6f6f6; overflow: hidden; } input[type=text],textarea,select { width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 4px; } input[type=button]{ width: auto; float: right; cursor: pointer; padding: 7px; } </style> </head> <body> <div> <!--Add few elements to the form--> <div> <input type="text" id="txtName" placeholder="Enter your name" /> </div> <div> <input type="text" id="txtAge" placeholder="Enter your age" /> </div> <div> <input type="text" id="txtEmail" placeholder="Enter your email address" /> </div> <div> <select id="selCountry"> <option selected value="">-- Choose the country --</option> <option value="India">India</option> <option value="Japan">Japan</option> <option value="USA">USA</option> </select> </div> <div> <textarea id="msg" name="msg" placeholder="Write some message ..." style="height:100px"></textarea> </div> <!--Add to button to save the data.--> <div> <input type="button" id="bt" value="Save data to file" onclick="saveFile()" /> </div> </div> </body> <script> let saveFile = () => { // Get the data from each element on the form. const name = document.getElementById('txtName'); const age = document.getElementById('txtAge'); const email = document.getElementById('txtEmail'); const country = document.getElementById('selCountry'); const msg = document.getElementById('msg'); // This variable stores all the data. let data = '\r Name: ' + name.value + ' \r\n ' + 'Age: ' +age.value + ' \r\n ' + 'Email: ' + email.value + ' \r\n ' + 'Country: ' + country.value + ' \r\n ' + 'Message: ' + msg.value; // Convert the text to BLOB. const textToBLOB = new Blob([data],{ type: 'text/plain' }); const sFileName = 'formData.txt'; // The file to save the data. let newLink = document.createElement("a"); newLink.download = sFileName; if (window.webkitURL != null) { newLink.href = window.webkitURL.createObjectURL(textToBLOB); } else { newLink.href = window.URL.createObjectURL(textToBLOB); newLink.style.display = "none"; document.body.appendChild(newLink); } newLink.click(); } </script> </html> 的指针中。我的目标是创建一个InsertionSort函数以对这些记录进行排序。将对记录的每个参数进行排序(通过多次调用)。麻烦的是该功能必须通用。 我可以在InsertionSort函数的参数中写些什么,以便指针起作用?

main.c

records

InsertionSort函数

struct fields{
    int id;
    char field1[20];
    int field2;
    float field3;
};

int main() {
struct fields *records = malloc(100000 * sizeof *records);

/* Here,I fill *records with values */

InsertionSort(records,field1,100000);     // I order by parameter "field1"
InsertionSort(records,id,100000);      // I order by parameter "id"
InsertionSort(records,field2,100000);     // I order by parameter "field2"
}

解决方法

看看标准C(和POSIX)qsort()的设计。将指向比较器函数的指针传递到InsertionSort()函数,以代替char parameter参数。当需要在sort函数中进行比较时,请在要比较的两条记录上调用比较器。编写不同的比较器以对不同的字段进行排序。标准(qsort兼容)比较器的签名为int comparator(const void *p1,const void *p2)。您可能可以使用const fields *作为参数类型,但随后将无法使用标准的qsort()函数。

如果不调试任何其他类型的问题(我不确定是否存在任何问题),您可能会遇到以下问题:

void InsertionSort(fields *records,int (*cmp)(const void *p1,const void *p2),int size)
{
    for (int i = 1; i < size; i++)
    {
        void *temp = &records[i];
        int j = i - 1;
        while (j >= 0 && (*cmp)(&records[j].parameter,temp) > 0)
        {
            records[j + 1].parameter = records[j].parameter;
            j--;
        }
        records[j + 1].parameter = temp;
    }
}

您只能写cmp(records[j].parameter,temp)。我很久以前就学过C,希望通过函数指针调用函数来使用较旧的,更明确的表示法。 (我是在一个更简单的表示法不可行的时代学习C的。)

您的比较器函数可能看起来像这样(其他两个是cmp_id上的琐碎变体):

static int cmp_id(const void *p1,const void *p2)
{
    const fields *v1 = p1;
    const fields *v2 = p2;
    // +1 if v1 > v2; -1 if v1 < v2; else 0
    return (v1->id > v2->id) - (v1->id < v2->id);
}

static int cmp_field1(const void *p1,const void *p2)
{
    const fields *v1 = p1;
    const fields *v2 = p2;
    return strcmp(v1->field1,v2->field1);
}

数字比较器(cmp_id)避免溢出和分支。您可以这样写:

if (v1->id > v2->id)
    return +1;
if (v1->id < v2->id)
    return -1;
return 0;

作为函数的主体。这更容易理解。它也可以扩展为处理决胜局,因此,如果id的值相同,则可以比较field1字符串或field2或{{1}中的值}。您只需在field3语句之后和if之前添加额外的比较。

警告:此代码尚未在编译器附近,未经测试。注意警告。

,

所以Peppino想知道如何实际去做。好吧问题是,虽然我们可以传递成员,但不能传递成员的 type ,所以它将无法正确运行。如果我们所有成员的类型相同,那么它将起作用:

#include <stddef.h>

struct fields{
    int id;
    char field1[20];
    char field2[11];
    char field3[20];
};

void InsertionSort(fields *records,size_t parameter,int size) {
    int i,j;
    struct fields temp;
    for (i = 1; i < size; i++) {
        temp = records[i];
        j = i - 1;
        while (j >= 0 && strnatsort((char *)records[i] + parameter,(char *)records[i] + parameter) > 0) {
            records[j + 1] = records[j];
            j--;
        }
        records[j + 1] = temp;
    }
}

InsertionSort(records,offsetof(fields,field1),100000);

其中strnatsort进行自然排序:How to implement a natural sort algorithm in c++?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。