user-0 提问: 请问如何解决下列报错？

回复:
user: user-1
content: //使用哈希表进行单词词频的统计 //参考资料：课件：慕课；书本参考P258  #define MAXSIZETABLE 10000 #define CLOCKS_PER_SEC 1000 //宏定义CLOCKS_PER_SEC为1000，用于将difftime求得的单位从毫秒转化为秒 #include<stdio.h> #include<time.h> #include<stdlib.h> #include<string.h> #include<math.h> #define KEYLENTH 15 #define MAXWORDLEN 80 //所有单词最大长度  typedef char ElementType[KEYLENTH+1];//关键词类型用字符串 typedef int Index;//散列地址类型 typedef struct LNode *PtrToLNode;  struct LNode{ //定义链表的结构，包含链表元素和位置     ElementType Data;     int Count;//增加字段Count存储单词的出现次数     PtrToLNode Next ; }; typedef PtrToLNode Position; //Position是指针，指向结构体struct LNode 类型 typedef PtrToLNode List; typedef struct TblNode *HashTable; struct TblNode{ //定义哈希表结构,包含表长和含有链表头的数组     int TableSize;     List Heads; //指向链表头结点的数组 };  //返回一个不超过最大表长的最小素数 //输入：一个整形数 //输出：一个素数 int nextPrime(int N){      int p=(N%2)?(N+2):(N+1);//从大于N的最小奇数开始探测     int i;      while(p<MAXSIZETABLE)//超过MAXSIZETABLE时停止比较     {         for(i=(int)sqrt(p);i>2;i--)//判断p是否是素数         {             if (!(p%i)) break;//如果p被除了1和它本身整除，则不是素数，退出         }         if(i==2) break;//for 循环正常结束，说明p是素数         else p+=2;      }     return p; }  //计算哈希值的函数，哈希值为Key在哈希表中的地址 //输入：Key，TableSize //输出：一个整形数字 int hash(int Key,int TableSize) {     return Key%TableSize; }  //初始化哈希表 HashTable CreateTable(int TableSize){     HashTable H;     int i;      //先分配内存，内存大小为sizeof(struct HashTable)     H = (HashTable)sizeof(struct TblNode);     //保证散列表的最大长度是素数     H->TableSize = nextPrime(TableSize);     //分配链表头结点数组     H->Heads=(List)malloc(H->TableSize *sizeof(struct LNode));     //初始化表头节点     for(i=0;i<H->TableSize;i++)     {         //H->Heads[i].Data = '\0';//'\0'表示空的字符         memset(H->Heads[i].Data, 0, sizeof(H->Heads[i].Data));         H->Heads[i].Next = NULL;     }      return H;   //需要返回的 }  //在哈希表H中找Key Position Find(ElementType Key,HashTable H) {     Position p;     Index Pos;     int key_Int;//int型key值      //计算key的哈希值     //先将key变为int型数字     key_Int = atoi(Key);//atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数     Pos=hash(key_Int,H->TableSize);      p= H->Heads[Pos].Next;//用Pos这个哈希值，从链表的第一个位置开始      //根据哈希值，在哈希表中查找，找到返回位置，否则返回null     /*while(p && strcmp(p->Data,Key))*/     while(p && (p->Data!=Key)) //strcmp()中参数为字符串类型     {         p=p->Next;     }     return p;//此时P指向找到的结点，或者为NULL }   //销毁HashTable void DestoryTable(HashTable H){     int i;     Position p,Temp;      //删除链表节点的操作：p先指向链表节点,临时指针temp指向p->Next,释放p free(p),P->Temp     for (i = 0;i<H->TableSize;i++)     {         p = H->Heads[i].Next;//先确定要删除的表头，p是表头后面的链条         while(p)         {             Temp = p->Next;             free(p);             p=Temp;         }      }     free(H->Heads);     free(H); }  //将一个字符串进行哈希函数的计算， //输入：字符串，例如abcdd //输出：字符串的哈希地址 int  HashAdd(const char *key) {     //程序计时开始     clock_t start_t,end_t;     double total_t;       //字符串的哈希函数，将字符串进行哈希函数     int TableSize = 110;     unsigned int h = 0; //散列函数值，从初始化为0     int add;     start_t = clock();      while(*key!= '\0')//将字符串每个字符*32后相加再相乘，最后得到的这个字符串的哈希值     {         h = (h <<5) + *key++; //左移5位      }     add = h % TableSize;     end_t = clock();     printf("%d\n",add);      //程序计时结束     total_t = difftime(end_t,start_t)/CLOCKS_PER_SEC;     printf("diff:CPU占用的时间：%f\n",total_t);      return 0; }  //在哈希表中插入Key并且统计词频 //输入：ElementType类型的Key,哈希表H //输出：空值。但是哈希表已经经过Key插入，并且对应的词频已经统计 void InsertAndCount(HashTable H,ElementType Key) {     Position NewCell,P;     Index Pos;     int Key_Int;//将字符串key转变为int类型      //先在哈希表中找Key,调用find(key,H)     P=Find(Key,H);      //若没有找到，可以插入     if(!P)     {         //为新插入的节点开辟内存空间，sizeof(struct LNode)         NewCell = (Position)malloc(sizeof(struct LNode));         strcpy(NewCell->Data,Key);         NewCell->Count=1;//新单词第一次出现          //通过哈希函数计算Key的哈希地址，作为在表中插入的位置         Key_Int = atoi(Key);//将字符串转变为int         Pos = hash(Key_Int,H->TableSize);          //插入这个链表需要插入key，以及next指针，就是插入一个表结点         NewCell->Next = H->Heads[Pos].Next;         H->Heads[Pos].Next = NewCell;         H->Heads[Pos].Count++;//链表中增加了一个新单词     }      //若找到，将原来单词的词频加1     else{         P->Count++;     } }   //判断z字符是否合法：在0-9 a-z A-Z之间单词合法 //输入：char类型的字符 //输出：bool型结果true 或者false bool IsWordChar(char c) {     //若单词合法，返回true     if((c>='a'&&c<='z')||(c>='0'&&c<='9')||(c=='_')||(c>='A'&&c<='Z'))         return true;      //否则返回false     else         return false; }  //从给定文件读取一个单词，返回该单词的长度,若超过长度15将会被截去 //输入：指向文件的指针fp,ElementType类型word //输出：单词的长度 int GetAWord(FILE *fp,ElementType word) {     char tempword[MAXWORDLEN+1],c;     int len=0;//单词长度      //读取fp所指文件中的第一个字符，判断该字符是否合法,若合法则统计直到遇到结束     //字符“\0”     c = fgetc(fp);     while(!feof(fp))     {         if(IsWordChar(c))         {             tempword[len++]=c;//tempword数组存放单词，比如"boy":tempword[3]="boy"         }         c = fgetc(fp);         //跳过单词前的非法字符，或以非法字符结束一个单词         if(len && !IsWordChar(c))             break;//非法字符     }      tempword[len] = '\0'; //设定字符串结束符      //截断太长的单词，超过KEYLENTH就是太长,本例子中KEYLENTH定义为15     if(len>KEYLENTH)     {         tempword[KEYLENTH] = '\0';         len = KEYLENTH;     }     strcpy(word, tempword);     return len; }  //显示词频超过给定比例的所有单词 //输入：哈希表H 比例percent //输出： void Show(HashTable H, double percent) {     int diffwordcount=0;//不同的单词数量     int maxf=0;//最大单词频次     int i;     Position L;     int maxCollision=100;//最大冲突次数     int minCollision=0;//最小冲突次数初始化为100     int *diffwords;//每个词频对应的不同单词的数量      //用for循环扫描整个散列表，统计不同的单词数量和最大词频     //maxf     for(i=0;i<H->TableSize;i++)     {         //头结点统计的单词数量的和就是不同的单词个数         diffwordcount += H->Heads[i].Count;          //统计最大/最小冲突次数         if(maxCollision < H->Heads[i].Count) maxCollision = H->Heads[i].Count;         if(minCollision > H->Heads[i].Count) minCollision = H->Heads[i].Count;          //找出每个头结点链表中的最大maxf         L = H->Heads[i].Next; //L指向链表的表头         while(L)         {             //遍历链表             if(maxf < L->Count) maxf = L->Count;             L = L->Next;         }     }     printf("共有%d个不同单词，词频最大是：%d\n",diffwordcount,maxf);     printf("最大冲突次数是:%d,最小冲突次数是%d\n",maxCollision,minCollision);         //根据最大词频maxf申请一个数组diffwords用于存储词频从1到     //maxf的单词数量     diffwords = (int *)malloc(sizeof(int)*(maxf+1)); //创建一个数组     for (i = 0;i<= maxf ;i++)     {         diffwords[i] = 0;//初始化每个数组元素为0 这里为什么不是int diffwords[40]={0} ?     }     //计算每个数组元素的值，需要遍历链表，找到每个表结点的Count,diffwords[Count]+1     for(i=0;i<H->TableSize;i++)     {         L=H->Heads[i].Next;         //遍历链表         while(L)         {             diffwords[L->Count]++;//词频数组对应元素加一             L=L->Next;         }     }      //求特定的词频，使得大于等于该词频的单词总和超过给定的比例？？？？  }   //main函数,文件中单词词频统计 //统计文件中所有单词出现的频率，并输出词频最大的前10%的单词 //及其词频 int main() {     FILE *fp;     int TableSize = 10000;//散列表的估计大小     char document[30]= "HarryPotter.txt"; //要统计词频的文件名     HashTable H;     int length=0;     int Wordcount=0;     ElementType word;      //1.初始化一张散列表     H = CreateTable(TableSize);     //2.打开文件     //     //if( (fp=fopen(document,"r"))==NULL)      //   printf("无法打开文件\n");      if( (fp=fopen(document,"r"))==NULL) {   //文件打开失败就不要执行下面的读文件操作了         printf("无法打开文件\n");         return -1;     }     //3.对文件进行处理     while(!feof(fp))     {         length = GetAWord(fp,word);//从文件读一个单词         if(length > 3)         {  //只考虑长度大于3的单词             Wordcount++;//统计文件中单词总数             InsertAndCount(H,word);//在哈希表中寻找此word单词,如果在哈希表中则词频加1，不在则插入word}         }     }      //4.文件读取完毕     fclose(fp);     //printf("该文档共出现%d个有效单词",word);     printf("该文档共出现%d个有效单词",Wordcount);     //5.显示词频前10%的所有单词     Show(H,10.0/100);      //6、销毁散列表     DestoryTable(H);      return 0 ; } 供参考～  对比代码找出自己的问题吧

user: user-0
content: 引用 楼主 RunningBComeOn 的回复:语法百度后查找不出来，报错如下。麻烦大神赐教。  //使用哈希表进行单词词频的统计 //参考资料：课件：慕课；书本参考P258  #define MAXSIZETABLE 10000 #define CLOCKS_PER_SEC 1000 //宏定义CLOCKS_PER_SEC为1000，用于将difftime求得的单位从毫秒转化为秒 #include<stdio.h> #include<time.h> #include<stdlib.h> #include<string.h> #include<math.h> #define KEYLENTH 15 #define MAXWORDLEN 80 //所有单词最大长度  typedef char ElementType[KEYLENTH+1];//关键词类型用字符串 typedef int Index;//散列地址类型 typedef struct LNode *PtrToLNode;  struct LNode{ //定义链表的结构，包含链表元素和位置 	ElementType Data; 	int Count;//增加字段Count存储单词的出现次数 	PtrToLNode Next ; }; typedef PtrToLNode Position; //Position是指针，指向结构体struct LNode 类型 typedef PtrToLNode List; typedef struct TblNode *HashTable; struct TblNode{ //定义哈希表结构,包含表长和含有链表头的数组 	int TableSize; 	List Heads; //指向链表头结点的数组 };  //返回一个不超过最大表长的最小素数 //输入：一个整形数 //输出：一个素数 int nextPrime(int N){  	int p=(N%2)?(N+2):(N+1);//从大于N的最小奇数开始探测 	int i;  	while(p<MAXSIZETABLE)//超过MAXSIZETABLE时停止比较 	{ 		for(i=(int)sqrt(p);i>2;i--)//判断p是否是素数 		{ 			if (!(p%i)) break;//如果p被除了1和它本身整除，则不是素数，退出 		} 		if(i==2) break;//for 循环正常结束，说明p是素数 		else p+=2;  	} 	return p; }  //计算哈希值的函数，哈希值为Key在哈希表中的地址 //输入：Key，TableSize //输出：一个整形数字 int hash(int Key,int TableSize) { 	return Key%TableSize; }  //初始化哈希表 HashTable CreateTable(int TableSize){ 	HashTable H; 	int i;	  	//先分配内存，内存大小为sizeof(struct HashTable) 	H = (HashTable)sizeof(struct TblNode); 	//保证散列表的最大长度是素数 	H->TableSize = nextPrime(TableSize); 	//分配链表头结点数组 	H->Heads=(List)malloc(H->TableSize *sizeof(struct LNode)); 	//初始化表头节点 	for(i=0;i<H->TableSize;i++) 	{ 		H->Heads[i].Data = '\0';//'\0'表示空的字符 		H->Heads[i].Next = NULL; 	} }  //在哈希表H中找Key Position Find(ElementType Key,HashTable H) { 	Position p; 	Index Pos; 	int key_Int;//int型key值  	//计算key的哈希值 	//先将key变为int型数字 	key_Int = atoi(Key);//atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数 	Pos=hash(key_Int,H->TableSize); 	 	p= H->Heads[Pos].Next;//用Pos这个哈希值，从链表的第一个位置开始  	//根据哈希值，在哈希表中查找，找到返回位置，否则返回null 	/*while(p && strcmp(p->Data,Key))*/ 	while(p && (p->Data!=Key)) //strcmp()中参数为字符串类型 	{ 		p=p->Next; 	} 	return p;//此时P指向找到的结点，或者为NULL }   //销毁HashTable void DestoryTable(HashTable H){ 	int i; 	Position p,Temp;  	//删除链表节点的操作：p先指向链表节点,临时指针temp指向p->Next,释放p free(p),P->Temp 	for (i = 0;i<H->TableSize;i++) 	{ 		p = H->Heads[i].Next;//先确定要删除的表头，p是表头后面的链条 		while(p) 		{ 			Temp = p->Next; 			free(p); 			p=Temp; 		}  	} 	free(H->Heads); 	free(H); }  //将一个字符串进行哈希函数的计算， //输入：字符串，例如abcdd  //输出：字符串的哈希地址 int  HashAdd(const char *key) { 	//程序计时开始 	clock_t start_t,end_t; 	double total_t; 	  	//字符串的哈希函数，将字符串进行哈希函数 	int TableSize = 110;  	unsigned int h = 0; //散列函数值，从初始化为0 	int add; 	start_t = clock();  	while(*key!= '\0')//将字符串每个字符*32后相加再相乘，最后得到的这个字符串的哈希值 	{ 		h = (h <<5) + *key++; //左移5位  	} 	add = h % TableSize; 	end_t = clock(); 	printf("%d\n",add);  	//程序计时结束 	total_t = difftime(end_t,start_t)/CLOCKS_PER_SEC; 	printf("diff:CPU占用的时间：%f\n",total_t); 	 }  //在哈希表中插入Key并且统计词频 //输入：ElementType类型的Key,哈希表H //输出：空值。但是哈希表已经经过Key插入，并且对应的词频已经统计 void InsertAndCount(HashTable H,ElementType Key) { 	Position NewCell,P; 	Index Pos; 	int Key_Int;//将字符串key转变为int类型  	//先在哈希表中找Key,调用find(key,H) 	P=Find(Key,H);  	//若没有找到，可以插入 	if(!P)  	{ 		//为新插入的节点开辟内存空间，sizeof(struct LNode) 		NewCell = (Position)malloc(sizeof(struct LNode)); 		strcpy(NewCell->Data,Key); 		NewCell->Count=1;//新单词第一次出现  		//通过哈希函数计算Key的哈希地址，作为在表中插入的位置 		Key_Int = atoi(Key);//将字符串转变为int 		Pos = hash(Key_Int,H->TableSize);  		//插入这个链表需要插入key，以及next指针，就是插入一个表结点 		NewCell->Next = H->Heads[Pos].Next; 		H->Heads[Pos].Next = NewCell; 		H->Heads[Pos].Count++;//链表中增加了一个新单词 	}  	//若找到，将原来单词的词频加1 	else{ 		P->Count++; 	} }   //判断z字符是否合法：在0-9 a-z A-Z之间单词合法 //输入：char类型的字符 //输出：bool型结果true 或者false bool IsWordChar(char c) { 	//若单词合法，返回true 	if((c>='a'&&c<='z')||(c>='0'&&c<='9')||(c=='_')||(c>='A'&&c<='Z')) 		return true;  	//否则返回false 	else 		return false; }  //从给定文件读取一个单词，返回该单词的长度,若超过长度15将会被截去 //输入：指向文件的指针fp,ElementType类型word //输出：单词的长度 int GetAWord(FILE *fp,ElementType word) { 	char tempword[MAXWORDLEN+1],c; 	int len=0;//单词长度  	//读取fp所指文件中的第一个字符，判断该字符是否合法,若合法则统计直到遇到结束 	//字符“\0” 	c = fgetc(fp); 	while(!feof(fp)) 	{ 		if(IsWordChar(c)) 		{ 			tempword[len++]=c;//tempword数组存放单词，比如"boy":tempword[3]="boy" 		} 		c = fgetc(fp); 		//跳过单词前的非法字符，或以非法字符结束一个单词 		if(len && !IsWordChar(c)) 			break;//非法字符 	}  	tempword[len] = '\0'; //设定字符串结束符  	//截断太长的单词，超过KEYLENTH就是太长,本例子中KEYLENTH定义为15 	if(len>KEYLENTH) 	{ 		tempword[KEYLENTH] = '\0'; 		len = KEYLENTH; 	} 	strcpy(word, tempword); 	return len; }  //显示词频超过给定比例的所有单词 //输入：哈希表H 比例percent //输出： void Show(HashTable H, double percent) { 	int diffwordcount=0;//不同的单词数量 	int maxf=0;//最大单词频次 	int i; 	Position L;  	int maxCollision=100;//最大冲突次数 	int minCollision=0;//最小冲突次数初始化为100 	int *diffwords;//每个词频对应的不同单词的数量 	 	//用for循环扫描整个散列表，统计不同的单词数量和最大词频 	//maxf 	for(i=0;i<H->TableSize;i++) 	{ 		//头结点统计的单词数量的和就是不同的单词个数 		diffwordcount += H->Heads[i].Count;  		//统计最大/最小冲突次数 		if(maxCollision < H->Heads[i].Count) maxCollision = H->Heads[i].Count; 		if(minCollision > H->Heads[i].Count) minCollision = H->Heads[i].Count;  		//找出每个头结点链表中的最大maxf 		L = H->Heads[i].Next; //L指向链表的表头 		while(L) 		{ 			//遍历链表 			if(maxf < L->Count) maxf = L->Count; 			L = L->Next; 		} 	} 	printf("共有%d个不同单词，词频最大是：%d\n",diffwordcount,maxf); 	printf("最大冲突次数是:%d,最小冲突次数是%d\n",maxCollision,minCollision);     	//根据最大词频maxf申请一个数组diffwords用于存储词频从1到 	//maxf的单词数量 	diffwords = (int *)malloc(sizeof(int)*(maxf+1)); //创建一个数组 	for (i = 0;i<= maxf ;i++) 	{ 		diffwords[i] = 0;//初始化每个数组元素为0 这里为什么不是int diffwords[40]={0} ? 	} 	//计算每个数组元素的值，需要遍历链表，找到每个表结点的Count,diffwords[Count]+1 	for(i=0;i<H->TableSize;i++) 	{ 		L=H->Heads[i].Next; 		//遍历链表 		while(L) 		{ 			diffwords[L->Count]++;//词频数组对应元素加一 			L=L->Next; 		} 	} 	 	//求特定的词频，使得大于等于该词频的单词总和超过给定的比例？？？？  }   //main函数,文件中单词词频统计 //统计文件中所有单词出现的频率，并输出词频最大的前10%的单词 //及其词频 int main() { 	FILE *fp; 	int TableSize = 10000;//散列表的估计大小 	char document[30]= "HarryPotter.txt"; //要统计词频的文件名 	HashTable H; 	int length=0; 	int Wordcount=0; 	ElementType word;  	//1.初始化一张散列表 	H = CreateTable(TableSize); 	//2.打开文件 	if( (fp=fopen(document,"r"))==NULL) printf("无法打开文件\n");  	//3.对文件进行处理 	while(!feof(fp)) 	{ 		length = GetAWord(fp,word);//从文件读一个单词 		if(length > 3) 		{  //只考虑长度大于3的单词 			Wordcount++;//统计文件中单词总数 			InsertAndCount(H,word);//在哈希表中寻找此word单词,如果在哈希表中则词频加1，不在则插入word} 	    } 	}  	//4.文件读取完毕 	fclose(fp); 	printf("该文档共出现%d个有效单词",word); 	//5.显示词频前10%的所有单词 	Show(H,10.0/100);  	//6、销毁散列表 	DestoryTable(H);  	return 0 ; }    引用 2 楼 棉猴 的回复:HashTable CreateTable(int TableSize) { 	HashTable H; 	int i;  	//先分配内存，内存大小为sizeof(struct HashTable) 	H = (HashTable)new HashTable();// --------------分配内存空间---------------- 	//保证散列表的最大长度是素数 	H->TableSize = nextPrime(TableSize); 	//分配链表头结点数组 	H->Heads = (List)malloc(H->TableSize * sizeof(struct LNode)); 	//初始化表头节点 	//for (i = 0; i<H->TableSize; i++) 	//{ 		memset(H->Heads->Data, 0 , KEYLENTH + 1);//------------为Data数组赋初值---------------- 		H->Heads->Next = NULL; 	//} 		return H; }谢谢回复。请问这个和加循环有什么区别？

user: user-2
content: HashTable CreateTable(int TableSize) { 	HashTable H; 	int i;  	//先分配内存，内存大小为sizeof(struct HashTable) 	H = (HashTable)new HashTable();// --------------分配内存空间---------------- 	//保证散列表的最大长度是素数 	H->TableSize = nextPrime(TableSize); 	//分配链表头结点数组 	H->Heads = (List)malloc(H->TableSize * sizeof(struct LNode)); 	//初始化表头节点 	//for (i = 0; i<H->TableSize; i++) 	//{ 		memset(H->Heads->Data, 0 , KEYLENTH + 1);//------------为Data数组赋初值---------------- 		H->Heads->Next = NULL; 	//} 		return H; }

user: user-2
content: 1在CreateTable()函数中，既然是初始化表头，就没必要使用for循环了 	//初始化表头节点 	//for (i = 0; i<H->TableSize; i++) 	//{ 		strncpy(H->Heads->Data, 0 , KEYLENTH + 1); 		H->Heads->Next = NULL; 	//} 2 把 int  HashAdd(const char *key) 改为 void  HashAdd(const char *key)  VS2015 C++环境，调试能通过