我有这个 csv 文件:
NAME, NUMBER, ADDRESS, EMAIL
Kevin, +62 812-xxx-xxx, Jln.Anggrek Merah 3, kevin@gmail.com
Adwi, +62 821-xxxx-xxxx, Jln.Ruhui Rahayu, adwi@gmail.com
Wasis, +62 813-xxxx-xxxx, Jln.Pramuka 6 25, wasis@gmail.com
Alief, +62 811-xxxx-xxx, Jln.Padat Karya, alief@gmail.com
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
typedef struct Contact
{
char name[MAX];
char number[MAX];
char address[MAX];
char email[MAX];
struct Contact *next;
}
Contact;
void create_linkedList(Contact **start, Contact p)
{
Contact *new = malloc(sizeof(Contact));
strcpy(new->name, p.name);
strcpy(new->number, p.number);
strcpy(new->address, p.address);
strcpy(new->email, p.email);
new->next = *start;
*start = new;
}
void printList(Contact *start)
{
Contact *cursor = start;
while (cursor != NULL)
{
printf("%s\n", cursor->name);
cursor = cursor->next;
}
}
void sorting(Contact *start)
{
Contact *cursor = start, *traverse = NULL;
Contact *tmp, *tmp_next;
while (cursor != NULL)
{
traverse = cursor;
while (traverse->next != NULL)
{
if (strcasecmp(traverse->name, traverse->next->name) > 0)
{
tmp = traverse;
tmp_next = traverse->next->next;
traverse->next = tmp;
traverse->next->next = tmp_next;
}
traverse = traverse->next;
}
printf("Prepare!\n");
cursor = cursor->next;
}
}
int main(void)
{
FILE *file = fopen("contacts.csv", "r");
if (file == NULL)
return 1;
Contact person;
Contact *start = NULL;
// Loop inside csv file til' the end of file
while(fscanf(file, "%[^,], %[^,], %[^,], %[^\n] ", person.name, person.number, person.address, person.email) == 4)
{
# Skip header file from csv
if (strcmp("NAME", person.name) == 0)
continue;
create_linkedList(&start, person);
}
printList(start);
// Swapped
sorting(start);
printList(start);
return 0;
}
因此,在我成功创建了一个链接列表来连接我的 csv 文件中的每个人的数据后,我想按他们的名字对其进行排序,然后打印出来。但是如果你编译我的代码,它会导致分段错误。
在我的 sort()
函数中,我尝试更改每个人的 node (next)
。因为我认为如果我只交换每个元素的值,node (next)
仍然会像以前一样指向同一个人。所以我在想也许我只能交换 node (next)
。
如果它只是对数组中的值进行排序,我可以做到。但是链表对我这个初学者来说很难。
你能帮我吗?也许给我写一些新代码并解释解决方案,如果你们有的话。谢谢!
答案 0 :(得分:1)
当你想创建一个链表时,你应该使用一个包含两种类型日期的结构单元格:第一个是你的数据本身(在你的情况下是联系人)另一个是指向列表中下一个单元格的指针(下一个)。使用这种类型的实现,您可以使您的代码更具可读性、模块化和可重用性。
typedef struct Contact
{
char name[MAX];
char number[MAX];
char address[MAX];
char email[MAX];
struct Contact *next;
}
Contact;
typedef struct ContactCell {
Contact info;
struct ContactCell* next;
}
ContactCell;
typedef ContactCell* ContactList;
使用上述函数的实现将是:
void addContactToList(ContactList start, Contact p)
{
ContactCell* aux = malloc(sizeof(ContactCell));
aux->info = p;
aux->next = start;
start = aux;
}
void printList(ContactList start)
{
ContactList cursor = start;
while (cursor != NULL)
{
printf("%s\n", cursor->info.name);
cursor = cursor->next;
}
}
对于排序,我会在单元格之间交换 info(使用上面的实现),因为这种方法使交换更容易理解,尤其是对于像 Contact 这样的数据类型(对使用第三个变量进行交换)。以下版本使用选择排序算法(效率不高,但更简单)。
void sorting(ContactList start)
{
for (ContactList i= start; i!=NULL; i = i->next)
{
ContactList current_min = i;
for (ContactList j=i->next ;j!=NULL; j = j->next)
if (strcasecmp(current_min->info.name,j->info.name) > 0)
current_min = j;
//swap using a Contact aux variable
Contact tmp = i->info;
i->info = current_min->info;
current_min->info = tmp;
}
}
答案 1 :(得分:1)
与其传递双星指针(例如 Contact **start
),我更喜欢单独的 List
结构。这可以[轻松]扩展为双向链表。
此外,我总是将 struct
传递给带有指针的函数。按值传递 [正如您在创建列表时所做的那样] 速度较慢。并且,在一般情况下,如果 struct
很大(例如它有一个元素:int data[10000000];
)会导致堆栈溢出
我在理解您的排序逻辑时遇到了一些困难。而且,使用 traverse->next->next
对我来说似乎有问题。我无法确切说出您的排序算法基于什么。我猜它是在尝试进行插入排序 [但我很容易出错]。
对于在合并阶段从源列表中提取并附加到目标列表的链接列表,我更熟悉归并排序。那会很快(呃),而且它可以很好地适应链表。
但是,我并没有与您的代码相去甚远,而是从中改编了一些逻辑来创建一个选择排序 [我认为]。
无论如何,这是重构后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
typedef struct Contact {
char name[MAX];
char number[MAX];
char address[MAX];
char email[MAX];
struct Contact *next;
} Contact;
typedef struct {
Contact *head;
} List;
void
create_linkedList(List *list, Contact *p)
{
Contact *new = malloc(sizeof(Contact));
strcpy(new->name, p->name);
strcpy(new->number, p->number);
strcpy(new->address, p->address);
strcpy(new->email, p->email);
new->next = list->head;
list->head = new;
}
void
printList(List *list)
{
Contact *cursor = list->head;
printf("List:\n");
while (cursor != NULL) {
printf(" %s\n", cursor->name);
cursor = cursor->next;
}
}
void
sorting(List *list)
{
Contact *oldhead = list->head;
Contact *newhead = NULL;
Contact *newprev = NULL;
while (oldhead != NULL) {
// lowest element to be selected
Contact *bestcur = oldhead;
Contact *bestprev = NULL;
// find the lowest element in remaining list
Contact *travprev = NULL;
Contact *travcur = oldhead;
for (; travcur != NULL; travcur = travcur->next) {
if (strcasecmp(bestcur->name,travcur->name) > 0) {
bestcur = travcur;
bestprev = travprev;
}
travprev = travcur;
}
// remove selected element from old list
if (bestprev != NULL)
bestprev->next = bestcur->next;
else
oldhead = bestcur->next;
bestcur->next = NULL;
// append to new list
if (newprev != NULL)
newprev->next = bestcur;
else
newhead = bestcur;
newprev = bestcur;
}
list->head = newhead;
}
int
main(void)
{
FILE *file = fopen("contacts.csv", "r");
if (file == NULL)
return 1;
Contact person;
List *list = calloc(1,sizeof(*list));
// Loop inside csv file til' the end of file
while (fscanf(file, "%[^,], %[^,], %[^,], %[^\n] ",
person.name, person.number, person.address, person.email) == 4) {
// Skip header file from csv
if (strcmp("NAME", person.name) == 0)
continue;
create_linkedList(list, &person);
}
printList(list);
// Swapped
sorting(list);
printList(list);
return 0;
}