统计热词

设计题目1 统计热词

 

【实验目的】

1.熟悉Linux(Ubuntu版本)的登录和退出、命令及使用格式和常用基本操作命令;

2.练习并熟练使用Linux提供的vi编辑器;

3.练习并熟练使用Linux操作系统下最常用的C语言编译器gcc;

4.练习掌握Linux操作系统下最常用的代码调试器gdb的使用和调试代码的基本方法;

5.学习使用make命令和Makefile文件。

 

【实验要求】

  统计某篇或某几篇文章中出现次数最多的单词。

 

【涉及的背景知识及采用的函数概述】

 

1、Lolcat命令

Lolcat 是一个针对 Linux,BSD 和 OSX 平台的工具,它类似于 cat 命令,并为 cat 的输出添加彩虹般的色彩。 Lolcat 主要用于在 Linux 终端中为文本添加彩虹般的色彩。

点击打开链接这个教程很好。

2、pthread介绍

包括一个pthread.h头文件和一个线程创建

编译方法

gcc  -o  **    **.c   –lpthread

g++  -o   **  **.cpp -lpthread

3、Makefile

Makefile 中由#开始的行都是注释行。Makefile 中最重要的是描述文件的依赖关系的说明。一般的格式是:

target: components

TAB rule

第一行表示的是依赖关系。第二行是规则.

比如说我们上面的那个Makefile 文件的第二行

main:main.o mytool1.o mytool2.o

表示我们的目标(target)main 的依赖对象(components) 是main.o mytool1.o mytool2.o 当依赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令,就象我们的上面那个Makefile 第三行所说的一样要执行

gcc -o main main.o mytool1.o mytool2.o

注意规则一行中的TAB 表示那里是一个TAB 键

 

【题目设计思路】

(1)给定几篇文章的目录,调用多个线程统计出出现次数最多的前10个单词分别时什么.关于这个问题首先比较难的是如何找到给定的目录和如何保存统计出的字符串,这里我用到很多C++ STL中封装好的库,比如 map<>,string ,vector pair,等等.这样很方便存储和读取字符串了,我们将所有统计的字符串从map中取出放入vector,然后排序输入即可.

(2)将统计结果存入answer.txt中,然后通过lolcat命令以彩虹般的颜色输出来。

 

【调试过程问题分析】

    统计用的文章是从网上随机下载的,包含各种文字字符。

(1)在生成makefile文件时,由于使用很多STL,在每个.cpp文件中加入前面定义过的变量会出现重定义的情况,可能c++特殊,在c语言中一般不会出现这种情况.

解决方法: 将已经定义过的变量声明为extern就可以解决了,表示沿用上一个的.这样便不用再次开辟空间。

(2)安装lolcat时,虚拟机不能连外网,安装出现权限问题等问题,均通过百度解决。

https://jingyan.baidu.com/album/6c67b1d68facbb2786bb1e7b.html?picindex=2

3)Execl传参出现问题,第一个参数必需包含路径,可通过whereis lolcat来查看lolcat安装路径。

4)写入文件用的freopen用法及注意问题。

freopen:

1)头文件:stdio.h

2)功 能: 替换一个流,或者说重新分配文件指针,实现重定向

3)用 法: FILE *freopen(char *filename, char *type, FILE *stream);

filename是文件的名字,若无此文件则自行创建;

type是权限   “w”写,“r”读;

stream是流,stdout是输出流,stdin是输入流;

char str1[]="rank:    word    quantity";
freopen("answer.txt","w",stdout);//把输出到屏幕的文本输出到一个文本文件中
cout<<str1<<endl;//直接使用cout写入文件
int cnt=0;
for(vtt = vt.begin();vtt != vt.end();vtt++)
{
if(cnt==10)
break;
cout<<"\t"<<vtt->first<<"\t";
cout<<vtt->second<<endl;
cnt++;
}
       freopen("/dev/tty","w",stdout);//注意一定要加这句话,将重定向解除,否则最后输不出(不能在终端显示出来)。
       execl("/usr/games/lolcat","lolcat","answer.txt",NULL);

execl第一个参数如果不在根目录里则必需包含路径,使用whereis lolcat可以知道lolcat的安装目录。

5)也是被freopen坑了,虽然写入文件简单,可是输出被重定向到文件里了,导致最后的结果老是输不到终端,在execl前加上freopen(“/dev/tty”,”w”,stdout);再将输出重定向到控制台。

 

【源代码】

1、main.cpp

#include<cstdio>

#include<iostream>

 

using namespace std;

 

void solve_choice1();

void welcome()

{

printf("请选择功能\n");

printf("1. 输入几篇文章,输出在这几篇文章中出现次数最多的10个单词\n");

return ;

}

 

int main()

{

   int choice ;

welcome();

cin>>choice;

if(choice == 1)

{

solve_choice1();

}

 

return  0;

}

2、count_word.cpp

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

#include<map>

#include<pthread.h>

#include<set>

#include<algorithm>

 

using namespace std;

 

const int max_char = 150;

extern const int max_file = 100;

pthread_mutex_t p_mutex = PTHREAD_MUTEX_INITIALIZER;

extern map<string,int>mp;

extern string  str_file[max_file];

extern  int tot_num;

 

string copy(char *s)

{

string str = "";

int len = strlen(s);

for(int i = 0;i < len;i++)

{

if((s[i] >= 'a'&&s[i] <= 'z') || (s[i] >= 'A' &&s[i] <= 'Z'))

str += s[i];

else

return "1";

}

return str;

}

 

 

void* count_word(void* args)

{

mp.clear();

int tmp = *((int*) args);

FILE *fp;

char ch[20];

int i;

for(i = 0;i < str_file[tmp].size();i++)

ch[i] = str_file[tmp][i];

ch[i] = '\0';

if((fp = fopen(ch,"r")) == NULL)

{

printf("fopen file error\n");

exit(0);

}

char str[max_char];

while(fscanf(fp,"%s",str) != EOF)

{

 

pthread_mutex_lock(&p_mutex);

string  s = copy(str);

if(s != "1")

{

//puts("debug1");

mp[s]++;

tot_num++;

}

pthread_mutex_unlock(&p_mutex);

}

pthread_exit(0);

}

3、solve_choice1.cpp

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

#include<map>

#include<pthread.h>

#include<set>

#include<algorithm>

#include<unistd.h>

using namespace std;

 

const int mp_num = 100;

const int max_file = 100;

 

 

string str_file[max_file];

map<string,int>mp;

map<string,int>::iterator it;

vector< pair <string,int> >vt;

vector< pair <string,int> >::iterator vtt;

int file_num,tot_num;

int num[mp_num];

 

 

 

void* count_word(void* args);

 

bool cmp(pair <string,int > a,pair <string,int> b)

{

return a.second > b.second;

}

 

void solve_choice1()

{

tot_num = 0;

printf("请输入文章的数量\n");

cin>>file_num;

while(file_num > max_file)

{

printf("文章数量过大,请重新输入\n");

cin>>file_num;

}

printf("请输入你要统计的文章\n");

for(int i = 0;i < file_num;i++)

cin >> str_file[i];

 

pthread_t id[mp_num];

for(int i = 0;i < file_num;i++)

{

num[i] = i;

while(pthread_create(&id[i],NULL,count_word,(void *) &(num[i])) != 0 );

}

 

for(int i = 0;i < file_num;i++)

{

while(pthread_join( id[i],NULL) != 0);

}

 

vt.clear();

for(it = mp.begin();it != mp.end();it++)

{

string cp = it -> first;

    int w = it -> second;

// cout<<it -> first <<' '<<it -> second<<endl;

vt.push_back(make_pair(cp,w));

}

sort(vt.begin(),vt.end(),cmp);

char str1[]="rank:    word    quantity";

freopen("answer.txt","w",stdout);

cout<<str1<<endl;

int cnt=0;

for(vtt = vt.begin();vtt != vt.end();vtt++)

{

if(cnt==10)

break;

cout<<"\t"<<vtt->first<<"\t";

cout<<vtt->second<<endl;

cnt++;

}

       freopen("/dev/tty","w",stdout);

       execl("/usr/games/lolcat","lolcat","answer.txt",NULL);

return ;

}

4、makefile

main: main.o count_word.o solve_choice1.o

g++ -o $@ $^ -lpthread //注意一定要加-lpthread

http://www.linuxidc.com/Linux/2015-07/119839.htm

..c.o:

g++ -c $<


运行过程

makefile

./main

stdio.h
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值