Linux 状态机计算单词数量与统计单词出现频率


     状态机用于统计状态间切换次数,比较经典的应用在统计单词出现的次数等。在单词数量统计中,定义状态机为 IN OUT两个状态,分别表示当前位置在单词内与单词外,类似于光标在单词内与外的移动。初始化状态与光标移动到非字母处为out状态,检测到字母进入in状态,如图所示。

#define OUT       0
#define IN        1

#define INIT    OUT
int status = INIT;
int word = 0;

FILE *fp = fopen(filename, "r");
if (fp == NULL) return -1;
char c;
while ((c = fgetc(fp)) != EOF) {

if (' ' == c) || ('\n' == c) || ('\t' == c) ||
   ('\"' == c) || ('\'' == c) || ('+' == c) ||
   (',' == c) || ';' == c || '.' == c) { //
            status = OUT;
    } else if (OUT == status) {
            status = IN;
            word ++;
    }

} 

       打开一个文件,读取一个字符循环检测是否到达文章末尾,如未到达则检测当前字符是否为分隔符等非单词字符,否则当前字符为组成单词的字母。当检测到费单词部分时,进入out状态,检测到字母并且此时为out状态时才能进入IN状态,并记录进入IN状态次数,即为所得到的的单词个数。

        以此为基础,统计各个单词出现的频率,此时需要一个单词结构体,记录单词的字母组成,长度长度与出现次数。定义长度用于判断单词是否重复时,可以更快的排除不同的单词,避免每次都从头进行循环比较。

typedef  struct word {
    char word[30]; //假设没有多于三十个字符的单词
    int count;
    int length;
}word;
word w[20000];

        在判断单词部分与上文代码构造上基本相同,但输入的字符暂存在一个数组中,用于在输入时判断是否有相同单词,如果有则将元单词技术加一并不再存储重复的新单词,在存储单词数组中不创建重复单词的位置。

        当有第二个单词到来时,并且要记录单字母单词,到来时,判断已经存储的单词中是否有长度相同的单词,如果有再次判断是否与长度相同单词字母相同,如果是,相应的单词频率加一,break出当前与所存储单词的比较循环中。如未发现相应的单词,则新创建一个单词位置存储,在下次比较循环中,加入循环。当然可以选择用链表进行操作,每个单词存储时,在原链表后面加入一项,在遍历查找时,循环向后一个节点直到为空。

#include <stdio.h>
#include <string.h>

#define  OUT  0
#define  IN   1
#define  INIT OUT

typedef  struct word {
    char word[30];
    int count;
    int length;
}word;
word w[20000];


int  count_word(char* filename) {

    int status = INIT;
    char c[50];
    int word = -1;
    int letter = 0;
    int record = 0;
    FILE* fp = fopen(filename, "r");
    if (fp == NULL) return -1;
    while ((c[letter] = fgetc(fp)) != EOF) {

        if ((' ' == c[letter]) || ('\n' == c[letter]) || ('\t' == c[letter]) || ('\"' == c[letter]) || ('\'' == c[letter]) || ('+' == c[letter]) || (',' == c[letter]) || (';' == c[letter]) || ('-' == c[letter]) || ('\r' == c[letter])) 
        {
            if ((word > 1) && (letter>=1))
            {
                for (int i = 0; i < word; i++)
                {
                    if (w[i].length == letter)
                    {
                        int sum = 0;

                        for (int j = 0; j < letter; j++) {
                            if (w[i].word[j] != c[j])
                            {
                                sum++;           //判断长度相同的不同单词  当时因为因为什么 
                                                 //写成这样我也忘了
                            }
                        }

                        if (0 == sum) {
                            w[i].count++;
                            record = 1;        //表示次单词已经有记录在案了  不用重新建档

                            break;
                        }
                        sum = 0;

                    }

                }
            }
        if(record==0)  // 检查完毕  建档保存
        {
            for (int k = 0; k < letter; k++)
            w[word].word[k] = c[k];
            w[word].length = letter;
            w[word].count = 1;
            
        }
            
            status = OUT;
            letter = -1;
        }
        else if( OUT == status ){
            status = IN;
            if (record != 1)
            {
                word++;
            }
            if (record == 1)   //进入新单词中,取消之前的已经存在标志位
            {
                record = 0;
            }

        }   
        letter++;
        

    }

    return word;

}

int main(int argc, char* argv[]) {


    if (argc < 2) return -1;
    printf("word : %d \r\n",count_word(argv[1]));
    for (int i = 0; i < count_word(argv[1]); i++)
    {
        
            printf("letter %d : %s  :%d \r\n", i, w[i].word, w[i].count);
    }

}

        统计频率的代码没有区分大小写,见谅。后面也考虑过,或许可以使用单词字母的ASCII值来判断是否在内部,然后将其余一路置为out状态,可以试试。

        好像又出现了篇幅过短问题,此文章质量较低,这次的账号什么外链都没得,也没有图片全是代码,那估计是字太少了吧,凑点数。上一个账号就是因为GG违规被冻结GG了,这次学乖了,分享归分享,我也不挂连接也不同步社区了,如果有侵权的请联系我删除~~~确实想简单了,寻思参与个什么什么计划凑个奖,哪有那么简单呢,在人家的地盘发小广告,确实不对~~~ 消消停停发点帖子吧~~~~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux是一种开源操作系统,它有很多常用的单词和术语。以下是其中一些常见的词汇解释: 1. 内核(Kernel):Linux操作系统的核心部分,负责控制硬件和软件之间的交互。 2. 发行版(Distribution):基于Linux内核的操作系统的各种版本,如Ubuntu、Fedora和Debian等。 3. 终端(Terminal):用户与操作系统进行交互的窗口,可以通过命令行界面执行各种操作。 4. 命令(Command):在终端中输入的指令,用于执行特定的操作或运行程序。 5. 目录(Directory):用于组织和存储文件的文件夹,类似于Windows中的文件夹。 6. 文件(File):存储数据的基本单位,在Linux中可以是文本文件、可执行文件、目录等。 7. 权限(Permission):用于控制对文件和目录的访问权限,包括读取、写入和执行权限等。 8. 用户(User):使用Linux系统的个体,每个用户可以拥有自己的用户账户和配置文件。 9. 守护进程(Daemon):在Linux后台运行的程序,它们通常在系统启动时启动,并在整个系统运行过程中保持运行状态。 10. 管道(Pipeline):用于将一个命令的输出作为另一个命令的输入的特殊字符(|)。 11. 软件包(Package):一组相关的软件程序和文件的集合,可以通过包管理器来安装、更新和卸载。 12. Shell:一个命令行解释器或界面,用户可以通过它与操作系统进行交互。 13. HTTP(Hypertext Transfer Protocol):一种用于在计算机网络上传输超文本的协议,常用于Web浏览器和服务器之间的通信。 14. IP地址(Internet Protocol Address):用于在因特网上唯一标识设备的数字地址。 15. DNS(Domain Name System):将域名转换为对应IP地址的系统,使得用户可以通过易记的域名访问网站。 以上是一些常见的Linux单词和术语,它们涵盖了操作系统、文件系统、命令行操作和网络通信等方面。熟悉这些词汇对于理解和使用Linux系统非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值