天花板編程手把手計(jì)劃-第1期-第6天-打卡

題目

原問(wèn)題鏈接
編程統(tǒng)計(jì)出input.txt文件保存的文章中,每個(gè)單詞出現(xiàn)的次數(shù)劲蜻。文章內(nèi)容如下:

In this chapter we will be looking at files and directories and how to manipulate them. We will learn how to create files, open them, read, write and close them. We'll also learn how programs can manipulate directories, to create, scan and delete them, for example. After the last chapter's diversion into shells, we now start programming in C.
Before proceeding to the way UNIX handles file I/O, we'll review the concepts associated with files, directories and devices. To manipulate files and directories, we need to make system calls (the UNIX parallel of the Windows API), but there also exists a whole range of library functions, the standard I/O library (stdio), to make file handling more efficient.

這段文字來(lái)自網(wǎng)絡(luò)恋昼。為了統(tǒng)計(jì)更有意義御蒲,加入兩個(gè)條件:

統(tǒng)計(jì)過(guò)程中不考慮空格和標(biāo)點(diǎn)符號(hào)
不區(qū)分大小寫(xiě)(可以把所有字母轉(zhuǎn)成小寫(xiě)后參與統(tǒng)計(jì))

解題思路

做一個(gè)詞頻統(tǒng)計(jì)工具
觀察文本發(fā)現(xiàn)洁奈,兩個(gè)單詞之間都有空格隔開(kāi)稍味。這就比較好處理了井濒,因?yàn)槲覀兛梢院茌p松的實(shí)現(xiàn)一次讀取一個(gè)單詞灶似。

如果實(shí)際要處理的文本有標(biāo)點(diǎn)之后沒(méi)空格的情況,如

I love you.My program.

那我們還要加一個(gè)deliver函數(shù)把you和My分開(kāi)

如何存儲(chǔ)出現(xiàn)過(guò)的單詞
1.二維數(shù)組搭配一個(gè)一維數(shù)組實(shí)現(xiàn)
2.利用結(jié)構(gòu)體做一個(gè)鏈表實(shí)現(xiàn)
我選擇了第二種瑞你,因?yàn)槲矣X(jué)得結(jié)構(gòu)體是通往抽象編程的路酪惭,而且使用結(jié)構(gòu)體可讀性更好。

具體思路
1.一次從文本讀取一個(gè)字符串word
2.把字符串word的大寫(xiě)字母轉(zhuǎn)化為小寫(xiě)
3.把字符串word里的 ,.() 四種標(biāo)點(diǎn)消除(想做成一個(gè)好用的詞頻統(tǒng)計(jì)工具的話者甲,根據(jù)實(shí)際需要增添要消除的標(biāo)點(diǎn)符號(hào))
4.檢查word是否出現(xiàn)過(guò)
沒(méi)有出現(xiàn)過(guò): 把他存入結(jié)構(gòu)體
出現(xiàn)過(guò):找到存儲(chǔ)這個(gè)word的結(jié)構(gòu)體春感,并把里面的計(jì)數(shù)變量加一
5.打印所有存儲(chǔ)了單詞的結(jié)構(gòu)體

源碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILE_PATH "..\\要統(tǒng)計(jì)的文本.txt" //宏存儲(chǔ)文本相對(duì)路徑
#define WORD_LENGTH 60
#define LENGTH sizeof(WORD)

struct WORD
{
    char word[WORD_LENGTH];     //存放單詞
    int wordCount;        //本單詞出現(xiàn)次數(shù)
    struct WORD *pNext;            //next指針
};
struct WORD pHeader;      //鏈表的頭結(jié)點(diǎn)

WORD *countWord(char *word, WORD *pLastWord);
void changeToLower(char *word);
void checkPunct(char *word);
int checkCountWord(char *word);
void addcount(char * word);
WORD * addNewWord(char *word, WORD *pLastWord);
void printResult();
void freeAll();

void main()
{
    WORD *pLastWord = &pHeader;//指向最后一個(gè)結(jié)點(diǎn)的指針
    char tempWord[WORD_LENGTH];//儲(chǔ)存本次讀取的字符串
    pHeader.pNext = NULL;//把頭節(jié)點(diǎn)的指向初始化為空
    FILE *fp;
    if ((fp = fopen(FILE_PATH, "r")) == NULL)//如果打開(kāi)文本為空
    {
        printf("System can`t find this file!\n");
        exit(0);
    }
    while ((fscanf(fp, "%s", tempWord)) != EOF)//如果文件還沒(méi)讀取完
    {
        pLastWord = countWord(tempWord, pLastWord);//統(tǒng)計(jì)詞頻
    }
    fclose(fp);//關(guān)閉文件
    printResult();//打印統(tǒng)計(jì)結(jié)果
    freeAll();//釋放所有動(dòng)態(tài)申請(qǐng)的內(nèi)存
    system("PAUSE");
}

WORD *countWord(char *word,WORD *pLastWord)
{
    
    changeToLower(word);//把Word全部轉(zhuǎn)換為小寫(xiě)字母
    checkPunct(word);//去除word中的 (),. 如果文本含有其他特殊標(biāo)點(diǎn),這里需要再增加一點(diǎn)代碼
    if (checkCountWord(word))//如果本單詞在前文出現(xiàn)過(guò)
    {
        addcount(word);//把這個(gè)單詞的計(jì)數(shù)加一
    }
    else
    {
        pLastWord = addNewWord(word, pLastWord);//建立一個(gè)新的單詞結(jié)點(diǎn)
    }
    return pLastWord;
}

void changeToLower(char *word)//把字符串全部轉(zhuǎn)化為小寫(xiě)字母
{
    int i;
    for (i = 0; word[i] != '\0'; i++)
    {
        if (word[i] >= 65 && word[i] <= 90)
        {
            word[i] += 32;
        }
    }
}

void checkPunct(char *word)//去除標(biāo)點(diǎn)符號(hào)
{
    int i, k;
    for (i = 0; word[i] != '\0'; i++)//遍歷字符串
    {
        if (word[i] == '(' || word[i] == ')' || word[i] == ',' || word[i] == '.')//如果含有標(biāo)點(diǎn)
        {
            for (k = i; word[k] != '\0'; k++)
            {
                word[k] = word[k + 1];
            }
            i--;//防止"sdio)."這種連續(xù)多個(gè)特殊字符出現(xiàn)的情況虏缸,再次檢查當(dāng)前index下的字符
        }
    }
}

int checkCountWord(char *word)//不在已存儲(chǔ)單詞中返回0.  在就返回1
{
    WORD *p;
    p = &pHeader;
    if (pHeader.pNext == NULL)//如果檢查的是第一個(gè)單詞
    {
        return 0;
    }
    do
    {
        p = p->pNext;
        if (strcmp(word, p->word) == 0)
        {
            return 1;
        }
    } while (p->pNext != NULL);
    return 0;
}

void addcount(char * word)//把出現(xiàn)過(guò)的單詞計(jì)數(shù)加一
{
    WORD *p;
    p = &pHeader;
    do
    {
        p = p->pNext;
        if (strcmp(word, p->word) == 0)//遍歷到重復(fù)的結(jié)點(diǎn)鲫懒,并把計(jì)數(shù) +1 
        {
            p->wordCount++;
            return;
        }
    } while (p->pNext != NULL);
}

WORD * addNewWord(char *word, WORD *pLastWord)//加一個(gè)新單詞結(jié)點(diǎn)
{
    WORD *pTemp;
    if (pHeader.pNext == NULL)//如果添加的是第一個(gè)結(jié)點(diǎn)
    {
        pHeader.pNext = (WORD *)malloc(LENGTH);
        strcpy(pHeader.pNext->word, word);
        pHeader.pNext->wordCount = 1;
        pHeader.pNext->pNext = NULL;
        pLastWord = pHeader.pNext;
    }
    else
    {
        pTemp = pLastWord;
        pLastWord = (WORD *)malloc(LENGTH);
        strcpy(pLastWord->word, word);
        pLastWord->wordCount = 1;
        pLastWord->pNext = NULL;
        pTemp->pNext = pLastWord;
    }
    return  pLastWord;
}

void printResult()//打印存儲(chǔ)的所有單詞結(jié)點(diǎn)
{
    WORD *p;
    int sign = 0;
    p = &pHeader;
    do
    {
        p = p->pNext;
        printf("%-12s%d\t\t", p->word, p->wordCount);
        sign++;
        if (sign % 3 == 0)
        {
            printf("\n");
        }
    } while (p->pNext != NULL);
}

void freeAll()
{
    WORD *p ,*piror;
    p = pHeader.pNext;//頭節(jié)點(diǎn)不是動(dòng)態(tài)申請(qǐng)的不能釋放
    do
    {
        piror = p;
        p = p->pNext;
        free(piror);
    } while (p->pNext != NULL);
    free(p);
}

執(zhí)行結(jié)果

統(tǒng)計(jì)結(jié)果

后來(lái)改成了雙向鏈表并在打印前加了排序的函數(shù),下載了一本英文版的 <百年孤獨(dú)> 進(jìn)行了詞頻統(tǒng)計(jì)
很好用(亂碼是因?yàn)橄螺d的文本文件本身就有亂碼...)
就是運(yùn)行效率有些低

統(tǒng)計(jì)<百年孤獨(dú)>運(yùn)行時(shí)間記錄(800K的文本文件)

  • 打印結(jié)果占用2秒
  • 排序代碼占用1秒
  • 其他代碼占用3秒
  • 總計(jì)運(yùn)行時(shí)間6秒
百年孤獨(dú)的部分統(tǒng)計(jì)結(jié)果

總結(jié)

去年考英語(yǔ)六級(jí)時(shí)刽辙,我下載了一本英文電子版的<The Great Gatsby>窥岩,想統(tǒng)計(jì)出它的高頻單詞并背誦。我用了一個(gè)在線詞頻統(tǒng)計(jì)工具來(lái)統(tǒng)計(jì)宰缤,因?yàn)楦鞣N特殊字符的存在結(jié)果特別不理想颂翼。
現(xiàn)在學(xué)會(huì)了寫(xiě)自己的程序,我可以根據(jù)自己的實(shí)際需求來(lái)改寫(xiě)出合適的程序慨灭。It's really cool朦乏!
而且這個(gè)鏈表思維和我寫(xiě)的貪吃蛇實(shí)現(xiàn)蛇身體的思維很相似,我可以優(yōu)化我的貪吃蛇程序了氧骤!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末呻疹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子筹陵,更是在濱河造成了極大的恐慌刽锤,老刑警劉巖镊尺,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姑蓝,居然都是意外死亡鹅心,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)纺荧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)旭愧,“玉大人,你說(shuō)我怎么就攤上這事宙暇∈淇荩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵占贫,是天一觀的道長(zhǎng)桃熄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)型奥,這世上最難降的妖魔是什么瞳收? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮厢汹,結(jié)果婚禮上螟深,老公的妹妹穿的比我還像新娘。我一直安慰自己烫葬,他們只是感情好界弧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著搭综,像睡著了一般垢箕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兑巾,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天条获,我揣著相機(jī)與錄音,去河邊找鬼蒋歌。 笑死帅掘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奋姿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼素标,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼称诗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起头遭,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寓免,失蹤者是張志新(化名)和其女友劉穎癣诱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體袜香,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撕予,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蜈首。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片实抡。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖欢策,靈堂內(nèi)的尸體忽然破棺而出吆寨,到底是詐尸還是另有隱情,我是刑警寧澤踩寇,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布啄清,位于F島的核電站,受9級(jí)特大地震影響俺孙,放射性物質(zhì)發(fā)生泄漏辣卒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一睛榄、第九天 我趴在偏房一處隱蔽的房頂上張望荣茫。 院中可真熱鬧,春花似錦懈费、人聲如沸计露。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)票罐。三九已至,卻和暖如春泞边,著一層夾襖步出監(jiān)牢的瞬間该押,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工阵谚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚕礼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓梢什,卻偏偏與公主長(zhǎng)得像奠蹬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嗡午,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 從今天起囤躁,我們要開(kāi)始學(xué)習(xí)用工程化的思想去解決問(wèn)題。之前,我們總是把所有的代碼寫(xiě)在一個(gè)源文件中狸演,這樣看起來(lái)比較方便言蛇。...
    天花板閱讀 2,129評(píng)論 1 30
  • 這一期的內(nèi)容已經(jīng)過(guò)半,部分同學(xué)開(kāi)始覺(jué)得吃力宵距。如果這時(shí)候放棄腊尚,那前邊的努力就白費(fèi)了。今天我們來(lái)看看上一篇中的課后題满哪。...
    天花板閱讀 1,598評(píng)論 0 13
  • 初識(shí)瑜伽源于朋友的瘦身成功翩瓜,從朋友處聽(tīng)說(shuō)了瑜伽的好處瘦身受扳、減壓、排毒兔跌、完美體形勘高、預(yù)防慢性病、消除緊張和疲勞坟桅、保持青...
    愛(ài)思嘉閱讀 290評(píng)論 2 5
  • 一'我學(xué)到了什么 這一學(xué)期我們學(xué)習(xí)了第一單元 小數(shù)除法华望,第二單元 軸對(duì)稱和平移,第三單元 倍數(shù)和因數(shù)仅乓。下面我就把每...
    梁志敏LZM閱讀 1,517評(píng)論 0 1