问题描述
我有很多记录,每个记录由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++?