linux中list结构应用及构造hashtable进行英文文章单词数统计

一。传统的list和linux中内核list结构对比,内核中的list更灵活


六程序如下

hashtable.h

#include "list.h"
#include<string.h>
#include<malloc.h>

#define HASHTABEL_LEN 26
//以每个单词前面两个字母叠加作为hashtable的key值

struct hash_node
{
	struct list_head openlist;//开链法用来索引的链表
	int sum;
	char* word;
};

struct hash_table
{
	hash_node hashtable[HASHTABEL_LEN];
};

void init_hash_table(hash_table &hashtable)
{
	int i;
    for (i=0;i<HASHTABEL_LEN;i++)
    {
		INIT_LIST_HEAD(&(hashtable.hashtable)[i].openlist);
    }
}



//将单词添加到hashtable中
void insert_list_node(hash_node *hashtable, hash_node *newnode)
{
	hash_node *tmp;
	char *tmpword=newnode->word;
	hash_node* bucket=&hashtable[(*tmpword-'a')];
	struct list_head*  pos;
	list_for_each(pos,&(bucket->openlist))
	{
		tmp=list_entry(pos,hash_node,openlist);
		if(strcmp(tmp->word,newnode->word)==0)
		{
			++(tmp->sum);
			free(newnode->word);
			free(newnode);
			break;
		}
		else
		{
			list_add_tail(&(newnode->openlist),&(tmp->openlist));
			break;
		}
	}
	if(pos==&(bucket->openlist))
	{
		list_add_tail(&(newnode->openlist),&(bucket->openlist));
		
	}


}

list.h

#ifndef _LIST_H_
#define _LIST_H_

/*
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */



struct list_head {
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do { \
        (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

/*
 * Insert a _new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next)
{
    next->prev = _new;
    _new->next = next;
    _new->prev = prev;
    prev->next = _new;
}

/**
 * list_add - add a _new entry
 * @_new: _new entry to be added
 * @head: list head to add it after
 *
 * Insert a _new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *_new, struct list_head *head)
{
    __list_add(_new, head, head->next);
}

/**
 * list_add_tail - add a _new entry
 * @_new: _new entry to be added
 * @head: list head to add it before
 *
 * Insert a _new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
    __list_add(_new, head->prev, head);
}

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
    next->prev = prev;
    prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
 */
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
}

/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(struct list_head *head)
{
    return head->next == head;
}

/**
 * list_splice - join two lists
 * @list: the _new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(struct list_head *list, struct list_head *head)
{
    struct list_head *first = list->next;

    if (first != list) {
        struct list_head *last = list->prev;
        struct list_head *at = head->next;

        first->prev = head;
        head->next = first;

        last->next = at;
        at->prev = last;
    }
}

/**
 * list_entry - get the struct for this entry
 * @ptr:        the &struct list_head pointer.
 * @type:       the type of the struct this is embedded in.
 * @member:     the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
        ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

/**
 * list_for_each        -       iterate over a list
 * @pos:        the &struct list_head to use as a loop counter.
 * @head:       the head for your list.
 */
#define list_for_each(pos, head) \
        for (pos = (head)->next; pos != (head); \
                pos = pos->next)

/**
 * list_for_each_safe   -       iterate over a list safe against removal of list entry
 * @pos:        the &struct list_head to use as a loop counter.
 * @n:          another &struct list_head to use as temporary storage
 * @head:       the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
        for (pos = (head)->next, n = pos->next; pos != (head); \
                pos = n, n = pos->next)

/**
 * list_for_each_entry  -       iterate over list of given type
 * @pos:        the type * to use as a loop counter.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member, type) \
        for (pos = list_entry((head)->next, type, member);\
             &pos->member != (head);\
             pos = list_entry(pos->member.next,type, member))

/**
 * list_for_each_entry_safe  - 遍历时删除节点list_for_each_entry的一种安全用法
 * @pos:        the type * to use as a loop counter.
 * @n:          another &struct list_head to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member, type) \
        for (pos = list_entry((head)->next, type, member), n = pos->member.next;\
             &pos->member != (head);\
             pos = list_entry(n, type, member), n = pos->member.next)

#endif

hashtabletest.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include "hashtable.h"


#include"list.h"

#include<iostream>
using namespace std;

#define FILE_NAME_MAX_LEN 256 /* the max length of the file */
//#define HASHTABEL_LEN     26  /* the length of hash table, cause there are 26 low case letters*/
#define SUCCESS           0   /* file operation flag */
#define FAILURE           1



/*getword
function: get the words in the file
*/
int getword(FILE *fp, char **word_temp)
{
    int ch;
    unsigned long num;
    num=0;
    while(!feof(fp))
    {
        ch=fgetc(fp);
        if(isalpha(ch))
        {
            num++;
            break;
        }
    }

    while (!feof(fp))
    {
        ch = fgetc(fp);
        if (isalpha(ch)) {
            num++;
        } else
        {
            break;
        }
    }

 if (!feof(fp))
    {
        (void)fseek(fp,-(num+1),1);
         *word_temp = (char *)malloc(num+1);
         if (word_temp == NULL)
         {

            (void)fprintf(stdout,"Sorry, the memory space is full");
            (void)fprintf(stdout,"Please input any key to exit the program\n");
            (void)getchar();
            exit(FAILURE);
         }
         (void)fgets(*word_temp,num+1,fp);
         (void)fseek(fp,1,1);
         return SUCCESS;
    }
    else
    {
        if (num != 0) {
            *word_temp = (char *)malloc(num+1);
            if (word_temp == NULL)
                {

                (void)fprintf(stdout,"Sorry,the memory space is full");
                (void)fprintf(stdout,"Please input any key to exit program....\n");
                (void)getchar();
                exit(FAILURE);
               }
            (void)fseek(fp,-(num),SEEK_CUR);
            (void)fgets(*word_temp,num+1,fp);
             return SUCCESS;
        }
    }
    return FAILURE;
}

//保存
void save_hashtable_node(hash_table &hashtable)
{
    hash_node *head, *tmp;
    struct list_head *pos, *q;
    int i;
    FILE *fp;

    char filename[50]; 
	cout<<"请输入要输出的文件名"<<endl;
	cin.getline(filename,50);

    if((fp=fopen(filename,"w"))==NULL)
       {
           (void)fprintf(stdout,"Sorry, failure to open the file\n");
           (void)fprintf(stdout,"Please input any key to exit the program\n ");
           (void)getchar();
           (void)exit(FAILURE);
       }

	for (i=0;i<HASHTABEL_LEN;i++)
	{
		head=hashtable.hashtable+i;
		list_for_each_safe(pos,q, &(head->openlist))
		{
			tmp=list_entry(pos, hash_node,openlist);
			(void)fprintf(fp,"%s,%d\r\n",tmp->word,tmp->sum);
			(void)list_del(pos);
			(void)free(tmp->word);
			(void)free(tmp);
		}
	}
	(void)fprintf(stdout,"file successfully saved \n");
	fclose(fp);
}



//显示
void display_hashtable_node(hash_node *hashtable)
{
 hash_node *head, *tmp;
 struct list_head *pos, *q;
 int i;
 (void) fprintf(stdout, "结果如下:\n");
 for(i=0; i<HASHTABEL_LEN; i++)
 {
     head=hashtable+i;
     list_for_each_safe(pos, q,&(head->openlist))
     {
         tmp=list_entry(pos, hash_node,openlist);
        (void)fprintf(stdout,"%s,%d\n",tmp->word,tmp->sum);
     }
 }
}

int main()
{
    FILE *fp;
	hash_table hashtable; 
    hash_node *_new;
    char *word_tmp;
	char filename[50]; 
	cout<<"请输入要统计的文件名"<<endl;
	cin.getline(filename,50);
    fp=fopen(filename,"rb");


	init_hash_table(hashtable);
	while(!feof(fp))
	{
		if(getword(fp,&word_tmp)==SUCCESS)
		{
			_new=(hash_node *)malloc(sizeof(hash_node));
			if(_new==NULL)
			{
				(void)fprintf(stdout,"Sorry,the memory space is full");
				(void)exit(FAILURE);
			}
			_new->sum=1;

			//将单词转换成小写
			int i=0;
			while (*(word_tmp+i)!='\0')
			{
				*(word_tmp+i)=tolower(*(word_tmp+i));
				i++;
			}

			_new->word=word_tmp;
			insert_list_node(hashtable.hashtable,_new);


		}

	}


    fclose(fp);
	display_hashtable_node(hashtable.hashtable);
    save_hashtable_node(hashtable);
    fprintf(stdout,"please input any key to exit the program\n");
    getchar();
    return 0;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值