made some fixes
This commit is contained in:
370
main.c
370
main.c
@@ -4,245 +4,233 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define BUFFER_LENGTH 128
|
#define BUFFER_LENGTH 128
|
||||||
|
#define LINE_LENGTH 1024
|
||||||
#define HASH_BUCKETS 4000037
|
#define HASH_BUCKETS 4000037
|
||||||
#define MIN_COUNT 10000
|
#define MIN_COUNT 10000
|
||||||
|
|
||||||
void string_ncopy(char *dest, const char *src, size_t max_len) {
|
void string_ncopy(char *dest, const char *src, size_t max_len) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < max_len - 1 && src[i]) {
|
while (i < max_len - 1 && src[i]) {
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
dest[i] = '\0';
|
dest[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct person {
|
typedef struct person {
|
||||||
struct person *next;
|
struct person *next;
|
||||||
char *name;
|
char name[BUFFER_LENGTH];
|
||||||
int count;
|
int count;
|
||||||
} person;
|
} person;
|
||||||
|
|
||||||
void newPerson(person *p, const char *name) {
|
void newPerson(person *p, const char *name) {
|
||||||
string_ncopy(p->name, name, BUFFER_LENGTH);
|
string_ncopy(p->name, name, BUFFER_LENGTH);
|
||||||
p->count = 1;
|
p->count = 1;
|
||||||
p->next = NULL;
|
p->next = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
void insert(person **head, person *node) {
|
|
||||||
if (*head == NULL) {
|
|
||||||
*head = node;
|
|
||||||
} else {
|
|
||||||
person *p = *head;
|
|
||||||
int p_exists = strcmp(p->name, node->name);
|
|
||||||
while (p->next != NULL && p_exists != 0) {
|
|
||||||
p = p->next;
|
|
||||||
p_exists = strcmp(p->name, node->name);
|
|
||||||
}
|
|
||||||
if (p_exists == 0) {
|
|
||||||
p->count++;
|
|
||||||
} else {
|
|
||||||
p->next = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sorted_name_insert(person **head, char *name) {
|
void sorted_name_insert(person **head, char *name) {
|
||||||
person *node = (person *)malloc(sizeof(person));
|
person *node = (person *) malloc(sizeof(person));
|
||||||
newPerson(node, name);
|
newPerson(node, name);
|
||||||
if (*head == NULL) {
|
if (*head == NULL) {
|
||||||
*head = node;
|
*head = node;
|
||||||
} else {
|
|
||||||
person *p = *head;
|
|
||||||
person *p_prev = NULL;
|
|
||||||
int p_exists = strcmp(p->name, name);
|
|
||||||
if (p_exists > 0) {
|
|
||||||
node->next = *head;
|
|
||||||
*head = node;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (p->next != NULL && p_exists != 0) {
|
|
||||||
p_exists = strcmp(p->next->name, name);
|
|
||||||
if (p_exists > 0) {
|
|
||||||
node->next = p->next;
|
|
||||||
p->next = node;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
if (p_exists == 0) {
|
|
||||||
p->count++;
|
|
||||||
free(node);
|
|
||||||
} else {
|
} else {
|
||||||
p->next = node;
|
person *p = *head;
|
||||||
|
person *p_prev = NULL;
|
||||||
|
int cmp = strcmp(p->name, name);
|
||||||
|
while (p->next != NULL && cmp < 0) {
|
||||||
|
p_prev = p;
|
||||||
|
p = p->next;
|
||||||
|
cmp = strcmp(p->name, name);
|
||||||
|
}
|
||||||
|
if (cmp == 0){
|
||||||
|
p->count++;
|
||||||
|
free(node);
|
||||||
|
}else if (p_prev == NULL) {
|
||||||
|
node->next = *head;
|
||||||
|
*head = node;
|
||||||
|
} else if (p->next != NULL && cmp < 0) {
|
||||||
|
node->next = p;
|
||||||
|
p_prev->next = node;
|
||||||
|
} else {
|
||||||
|
p->next = node;
|
||||||
|
node->next = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sorted_count_insert(person **head, person *node) {
|
void sorted_count_insert(person **head, person *node) {
|
||||||
if (*head == NULL) {
|
if (*head == NULL) {
|
||||||
*head = node;
|
*head = node;
|
||||||
} else {
|
|
||||||
person *p = *head;
|
|
||||||
person *p_prev = NULL;
|
|
||||||
int cmp = p->count - node->count;
|
|
||||||
while (p->next != NULL && cmp > 0) {
|
|
||||||
p_prev = p;
|
|
||||||
p = p->next;
|
|
||||||
cmp = p->count - node->count;
|
|
||||||
}
|
|
||||||
if (p_prev == NULL) {
|
|
||||||
node->next = *head;
|
|
||||||
*head = node;
|
|
||||||
} else if (p->next != NULL && cmp < 0) {
|
|
||||||
node->next = p;
|
|
||||||
p_prev->next = node;
|
|
||||||
} else {
|
} else {
|
||||||
p->next = node;
|
person *p = *head;
|
||||||
node->next = NULL;
|
person *p_prev = NULL;
|
||||||
|
int cmp = p->count - node->count;
|
||||||
|
while (p->next != NULL && cmp > 0) {
|
||||||
|
p_prev = p;
|
||||||
|
p = p->next;
|
||||||
|
cmp = p->count - node->count;
|
||||||
|
}
|
||||||
|
if (p_prev == NULL) {
|
||||||
|
node->next = *head;
|
||||||
|
*head = node;
|
||||||
|
} else if (p->next != NULL && cmp < 0) {
|
||||||
|
node->next = p;
|
||||||
|
p_prev->next = node;
|
||||||
|
} else {
|
||||||
|
p->next = node;
|
||||||
|
node->next = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void display(person *head) {
|
void display(person *head) {
|
||||||
person *p = head;
|
person *p = head;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
printf("%s %d\n", p->name, p->count);
|
printf("%s %d\n", p->name, p->count);
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//djb2 hash http://www.cse.yorku.ca/~oz/hash.html
|
||||||
u_long hash(const unsigned char *str) {
|
u_long hash(const unsigned char *str) {
|
||||||
u_long hash = 5381;
|
u_long hash = 5381;
|
||||||
int c;
|
int c;
|
||||||
while ((c = *str++)) {
|
while ((c = *str++)) {
|
||||||
hash = ((hash << 5) + hash) + c;
|
hash = ((hash << 5) + hash) + c;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hm_insert(person **hashmap, char *name) {
|
void hm_insert(person **hashmap, char *name) {
|
||||||
u_long hash_value = hash((unsigned char *)name);
|
u_long hash_value = hash((unsigned char *) name);
|
||||||
hash_value = hash_value % HASH_BUCKETS;
|
hash_value = hash_value % HASH_BUCKETS;
|
||||||
sorted_name_insert(&hashmap[hash_value], name);
|
sorted_name_insert(&hashmap[hash_value], name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_line(char *line, char *buffer) {
|
void parse_line(char *line, char *buffer) {
|
||||||
char *line_it = line;
|
char *line_it = line;
|
||||||
if (*line_it == '<') {
|
if (*line_it == '<') {
|
||||||
line_it++;
|
|
||||||
size_t i = 0;
|
|
||||||
while (i < BUFFER_LENGTH - 1 && *line_it != ' ' && *line_it != '>' &&
|
|
||||||
*line_it != '\0' && *line_it != '\n') {
|
|
||||||
buffer[i] = *line_it;
|
|
||||||
line_it++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
buffer[i] = '\0';
|
|
||||||
if (strcmp(buffer, "author") == 0 || strcmp(buffer, "editor") == 0) {
|
|
||||||
while (*line_it != '>') {
|
|
||||||
line_it++;
|
line_it++;
|
||||||
}
|
size_t i = 0;
|
||||||
line_it++;
|
while (i < BUFFER_LENGTH - 1 && *line_it != ' ' && *line_it != '>' &&
|
||||||
char *surname_end = line_it, *surname_start;
|
*line_it != '\0' && *line_it != '\n') {
|
||||||
while (*line_it != '<') {
|
buffer[i] = *line_it;
|
||||||
if (*line_it == ' ') {
|
line_it++;
|
||||||
surname_start = surname_end;
|
i++;
|
||||||
surname_end = line_it;
|
}
|
||||||
|
buffer[i] = '\0';
|
||||||
|
if (strcmp(buffer, "author") == 0 || strcmp(buffer, "editor") == 0) {
|
||||||
|
memset(buffer, 0, BUFFER_LENGTH);
|
||||||
|
while (*line_it != '>') {
|
||||||
|
line_it++;
|
||||||
|
}
|
||||||
|
line_it++;
|
||||||
|
char *surname_end = line_it, *surname_start = line_it;
|
||||||
|
while (*line_it && *line_it != '<') {
|
||||||
|
if (*line_it == ' ') {
|
||||||
|
surname_start = surname_end;
|
||||||
|
surname_end = line_it;
|
||||||
|
}
|
||||||
|
line_it++;
|
||||||
|
}
|
||||||
|
bool only_numbers = true;
|
||||||
|
char *c = surname_end;
|
||||||
|
while (only_numbers && c != line_it) {
|
||||||
|
if (!isdigit(*c)) {
|
||||||
|
only_numbers = false;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!only_numbers) {
|
||||||
|
surname_start = surname_end;
|
||||||
|
surname_end = line_it;
|
||||||
|
}
|
||||||
|
size_t name_length = surname_end - surname_start;
|
||||||
|
memcpy(buffer, surname_start, name_length);
|
||||||
|
buffer[name_length] = '\0';
|
||||||
|
} else {
|
||||||
|
memset(buffer, 0, BUFFER_LENGTH);
|
||||||
}
|
}
|
||||||
line_it++;
|
|
||||||
printf("%s\n", line_it);
|
|
||||||
}
|
|
||||||
printf("line_it: %s\n", line_it);
|
|
||||||
printf("sn start: %s\n", surname_start);
|
|
||||||
printf("sn end: %s\n", surname_end);
|
|
||||||
if (!isdigit(surname_end + 1)) {
|
|
||||||
surname_start = surname_end + 1;
|
|
||||||
surname_end = line_it - 1;
|
|
||||||
} else {
|
|
||||||
surname_start++;
|
|
||||||
surname_end--;
|
|
||||||
}
|
|
||||||
i = 0;
|
|
||||||
size_t name_length = surname_end - surname_start;
|
|
||||||
while (i < name_length) {
|
|
||||||
buffer[i] = surname_start[i];
|
|
||||||
}
|
|
||||||
buffer[i] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void make_list(person **hashmap, person **list, const int min_count) {
|
void make_list(person **hashmap, person **list, const int min_count) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < HASH_BUCKETS; i++) {
|
for (i = 0; i < HASH_BUCKETS; i++) {
|
||||||
person *p = hashmap[i];
|
person *p = hashmap[i];
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
person *p_next = p->next;
|
person *p_next = p->next;
|
||||||
if (p->count >= min_count) {
|
if (p->count >= min_count) {
|
||||||
p->next = NULL;
|
p->next = NULL;
|
||||||
sorted_count_insert(list, p);
|
sorted_count_insert(list, p);
|
||||||
} else {
|
} else {
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
p = p_next;
|
p = p_next;
|
||||||
|
}
|
||||||
|
hashmap[i] = NULL;
|
||||||
}
|
}
|
||||||
hashmap[i] = NULL;
|
free(hashmap);
|
||||||
}
|
|
||||||
free(hashmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_list(person *list) {
|
void clean_list(person *list) {
|
||||||
person *p = list;
|
person *p = list;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
person *next = p->next;
|
person *next = p->next;
|
||||||
free(p);
|
free(p);
|
||||||
p = next;
|
p = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_memory(person **hashmap) {
|
void clean_memory(person **hashmap) {
|
||||||
for (int i = 0; i < HASH_BUCKETS; i++) {
|
for (int i = 0; i < HASH_BUCKETS; i++) {
|
||||||
person *p = hashmap[i];
|
person *p = hashmap[i];
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
person *next = p->next;
|
person *next = p->next;
|
||||||
free(p);
|
free(p);
|
||||||
p = next;
|
p = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
free(hashmap);
|
||||||
free(hashmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
person **hashmap = (person **)malloc(sizeof(person *) * HASH_BUCKETS);
|
person **hashmap = (person **) malloc(sizeof(person *) * HASH_BUCKETS);
|
||||||
for (int i = 0; i < HASH_BUCKETS; i++) {
|
for (int i = 0; i < HASH_BUCKETS; i++) {
|
||||||
hashmap[i] = NULL;
|
hashmap[i] = NULL;
|
||||||
}
|
|
||||||
FILE *fp = fopen("dblp.xml", "r");
|
|
||||||
char *line = NULL;
|
|
||||||
size_t line_len = 0;
|
|
||||||
char *buffer = (char *)malloc(sizeof(char) * BUFFER_LENGTH);
|
|
||||||
if (fp) {
|
|
||||||
while (!(getline(&line, &line_len, fp) < 0)) {
|
|
||||||
parse_line(line, buffer);
|
|
||||||
if (buffer != NULL) {
|
|
||||||
hm_insert(hashmap, buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
FILE *fp = fopen("dblp.xml", "r");
|
||||||
} else {
|
// char *line = malloc(sizeof(char) * LINE_LENGTH);
|
||||||
while (!(getline(&line, &line_len, stdin) < 0)) {
|
// size_t line_len = LINE_LENGTH;
|
||||||
printf("%s", line);
|
char *line = NULL;
|
||||||
parse_line(line, buffer);
|
size_t line_len = 0;
|
||||||
if (buffer != NULL) {
|
char *buffer = (char *) malloc(sizeof(char) * BUFFER_LENGTH);
|
||||||
hm_insert(hashmap, buffer);
|
if (fp) {
|
||||||
}
|
while (getline(&line, &line_len, fp) >= 0) {
|
||||||
|
memset(buffer, 0, BUFFER_LENGTH);
|
||||||
|
parse_line(line, buffer);
|
||||||
|
if (*buffer != '\0') {
|
||||||
|
hm_insert(hashmap, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
while (getline(&line, &line_len, stdin) >= 0) {
|
||||||
|
memset(buffer, 0, BUFFER_LENGTH);
|
||||||
|
parse_line(line, buffer);
|
||||||
|
if (*buffer != '\0') {
|
||||||
|
hm_insert(hashmap, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
free(line);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
printf("Done parsing!\n");
|
printf("Done parsing!\n");
|
||||||
person *list = NULL;
|
person *list = NULL;
|
||||||
make_list(hashmap, &list, MIN_COUNT);
|
make_list(hashmap, &list, MIN_COUNT);
|
||||||
display(list);
|
display(list);
|
||||||
clean_list(list);
|
clean_list(list);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Reference in New Issue
Block a user