画出1模块功能及调用关系 2对每个模块需要画出程序系统主要函数程序流程图

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include

#define SIZE 50 //设置单词最长长度

//链表结构体,储存单词,数量,以及构成链表的指针
typedef struct
{
char str[SIZE]; //单词最长100个?
int count;
struct Words* next;
}Words;

//初始化链表
Words* InitWord()
{
Words* headWord = (Words*)malloc(sizeof(Words));
strcpy(headWord->str, " ")
headWord->count = 0;
headWord->next = NULL;
return headWord;
}

//头插入的方式插入新数据
void AddWord(Words* headWord, const char* str)//头插入
{
Words* pos = headWord->next; //储存当前第一个结构体的指针
Words* newWord = (Words*)malloc(sizeof(Words));
strcpy(newWord->str, str);
headWord->next = newWord;
if (pos == NULL) newWord->next = NULL;//第一个单词,储存在链表尾部,next指向空
else newWord->next = pos;
newWord->count = 1;
}

int CheckStr(Words* headWord, const char* str)//检查单词是否出现过,若出现单词数量加一,返回1,没出现返回0
{
Words* p = headWord->next;
if (headWord->next == NULL)
{
//AddWord(headWord, str);如果链表为空,这里不需加入链表的操作,返回 0 即可。
return 0; //return 1;
}
while (strcmp(p->str, str) != 0)//p指向了结构体变量里的char新元素str
{
p = p->next;//修改p的位置p向下一个结点
if (p == NULL) break;
}
if (p == NULL) return 0;//没有该单词,返回0标记
else
{
++(p->count); //已有单词,数量加一
return 1;
}
return -1; //异常出错
}

//读单词操作——过滤标点与空格
int ReadWord(FILE* fp, int* plen, char* str)
{
fseek(fp, *plen, SEEK_SET);//设置文件位置为从给定的偏移plen,plen意味着从给定的seek set位置查找字节数
unsigned char ch;//定义无符号类型
int flg_eof = 0; //标记 判断是否文件结束,如果再没有读入的内容了,即文件结束
int i = 0;
while (fread(&ch, sizeof(char), 1, fp) != 0) //注:isalpha(unsigned(ch)),需要强制转换,
//发fread读取字节,计算数据类型长度,sizeof计算数据类型长度

{
    if (!isalpha(unsigned(ch)) && i == 0) continue;//排除单词是个字母无法读取问题
    if (isalpha(unsigned(ch)) || ch == '\'')//类似I'm中的 ' 符号,有且只能有一个
        //判断字符是否为英文字母
    {
        flg_eof = 1;
        str[i++] = ch;
    }
    else
    {
        break;
    }
}
if (flg_eof == 0) return 0; //没有读文件,文件结尾了
str[i] = '\0';
*plen = ftell(fp);
return *plen;

}

//读文件操作
void ReadFile(Words* headWord, char* name)//文件操作,从文件中读取单词
{
FILE* fp;
int len = 0; //标记文件指针在文件中的位置
if ((fp = fopen(name, "r")) == NULL)
{
fp = fopen(name, "w+"); // 如果创建失败,新建一个文件 w + :可读写
//文件存在则文件长度清为零,文件不存在时创建一个
}

char str[SIZE];
while (ReadWord(fp, &len, str) != 0)//fscanf(fp,"%s",str) != EOF
{
    if (CheckStr(headWord, str) == 0)    //没有该单词,新增一个
    {
        AddWord(headWord, str);
    }

}
fclose(fp);

}

//交换数据——单词/出现次数
void SwapWord(Words* posWord, Words* posNext)
{
char tmpWord[SIZE] = "";
strcpy(tmpWord, posWord->str);
strcpy(posWord->str, posNext->str);
strcpy(posNext->str, tmpWord);

int tmpCount;
tmpCount = posWord->count;
posWord->count = posNext->count;
posNext->count = tmpCount;

}

//单词排序
void WordsSort(Words* headWord)
{
if (headWord->next == NULL) return;
Words* pos = headWord->next;
Words* pos_next = pos->next;
int flag;
while (pos_next != NULL)
{
flag = 0;

    //-- _pos 表示内循环的遍历 -- / ps:本来想通过这种方式优化,然后写的有点复杂了,已优化,链接见文章首行
    Words* _pos = pos;
    Words* _pos_next = pos_next;

    while (_pos_next != NULL)
    {
        Words* tmp = _pos_next->next;
        if (_pos->count < _pos_next->count)
        {
            SwapWord(_pos, _pos_next);
            flag = 1;
        }
        _pos = _pos->next;
        _pos_next = _pos_next->next;
    }
    if (flag == 0)    break;
}

}

void PrintWords(Words* headWord, const char* name)
{
Words* pMove = headWord->next;
if (headWord->next == NULL) return;
int count = 0;
printf("<<%s>>中出现的最高频率的单词:\n", name);
printf("单词:出现次数:\n");
while (pMove != NULL && count < 200)
{
printf("%-50s%d\n", pMove->str, pMove->count);
pMove = pMove->next;
count++;
}
printf("\n");
}

//释放链表
void free_Word(Words* headNode)
{
Words* point = NULL;
while (headNode != NULL)
{
point = headNode;//指向所释放的空间
headNode = headNode->next;//指针后移
free(point);
}
}

int main()
{
Words* headWord = InitWord(); //初始化链表,创建表头
char bookName[] = "输入文件地址及文件名";
ReadFile(headWord, bookName); //文件操作
WordsSort(headWord);
PrintWords(headWord, bookName);
free_Word(headWord);
return 0;
大概就是从指定文件位置读取一个文本文件,然后读入单词,当遇到标点和空格时就用CheckStr函数将这个单词和链表中已经存在的单词比较,如果读入的单词已经存在,就将该结构体的数据域的count++,如果不存在则用头查法插入链表,此处调用InitWord,AddWord函数(这里我不太理解为什么要头插法,因为你这个是降序排序,新出现的插在最后又方便排序又方便打印),之后WordsSort调用SwapWord方法对链表进行一次类似冒泡排序的排序(其实这里的存储结构不用链表,用数组会好点,因为代码上限只能容纳200个不同单词,200的数组长度不吓人,用链表会频繁动态分配空间,时间上可能要差一点,当然如果单词数量多了还是用链表会好一点),最后就是调用PrintWords打印,其中如果文件没有读入单词就会立刻结束函数,提高了效率,然后就是正常的打印链表数据域了,最后用free_Word函数释放内存,这点属于链表的常规操作

6个问题0采纳,告辞告辞

代码都有了,自己照着画图呗

嗯......不太清楚

0%采纳率,再见再见

大概就是从指定文件位置读取一个文本文件,然后读入单词,当遇到标点和空格时就用CheckStr函数将这个单词和链表中已经存在的单词比较,如果读入的单词已经存在,就将该结构体的数据域的count++,如果不存在则用头查法插入链表,此处调用InitWord,AddWord函数(因为你这个是降序排序,新出现的插在最后又方便排序又方便打印),之后WordsSort调用SwapWord方法对链表进行一次类似冒泡排序的排序(其实这里的存储结构不用链表,用数组会好点,因为代码上限只能容纳200个不同单词,200的数组长度不吓人,用链表会频繁动态分配空间,时间上可能要差一点,当然如果单词数量多了还是用链表会好一点),最后就是调用PrintWords打印,其中如果文件没有读入单词就会立刻结束函数,提高了效率,然后就是正常的打印链表数据域了,最后用free_Word函数释放内存,这点属于链表的常规操作