說明:給出git地址是由於碼雲不支持TOC標籤,我直接寫錨定代碼他也不支持,可是github卻能夠,因此加上一個github地址linux
git不支持TOC標籤生成目錄(當場翻白眼)(gitee和github都不支持)git
可是好的是,github仍是能夠實現錨定功能的,可是gitee殊不知道爲何不行,因此我也給了一個github的地址。github
. ├── bin │ ├── linux_amd64 │ │ ├── input │ │ ├── my.ini │ │ ├── result.log │ │ ├── result.txt │ │ └── wc │ └── windows │ ├── wc32.exe │ └── wc64.exe ├── image │ └── whole_flow_chart.png ├── readme.md └── src ├── function.c ├── wc.c └── wc.h
wc接收一個文本文件,並統計這個文本文件中的信息(行數、字數等)算法
wc.exe -c file.c //返回文件 file.c 的字符數shell
wc.exe -w file.c //返回文件 file.c 的單詞總數windows
wc.exe -l file.c //返回文件 file.c 的總行數markdown
wc.exe -o outputFile.txt file.c //將結果輸出到指定文件outputFile.txtapp
我在原來的基本上加了一個幫助選項,由於以爲這樣更適用:
wc.exe -h //顯示幫助信息
注意:
參數的形式有兩種:長選項、短選項,選項間能夠組合,長選項用空格隔開各個參數
例: wc.exe --word --charater file.c
短選項能夠多個直接疊加或者,也像長選項同樣分開寫
例: wc.exe -wc file.c
wc.exe -w -c file.c
對於一個命令行程序,它能夠接受來自命令行的參數。
c語言的main函數中有兩個參數:int main (int argc, char
,這兩個參數就是用於這個參數的輸入。
*argv[])
argc 一個整數,表明有多少個命令行參數,在此注意兩個點
一、 參數間是用空格格開的;
二、程序名是第一個參數。
argv[i]是一個指針,指向第i個參數的首地址
理解了以上的兩個參數就簡單了,只須要作一些基本的字符串處理就能夠了。
這個參數單獨說是由於這個參數不能和別的參數混用,因此我在程序裏面是單獨寫的,一開始就判斷是否用戶須要的是help幫助,若是是的話,那麼徹底沒必要要再運行程序(打開文件),直接exit停止進程
。
這三個參數都是一個路數:
一、打開文件;
二、判斷要作的操做;
三、執行操做。
它們間只有步驟3是不一樣的,因此有理由把3寫成不一樣的函數,再由2判斷執行哪一個。
有一些細節問題是能夠考慮的。
好比,由於單複數的關係,有一行/個 單詞/字母,應該是不一樣的表達(是否有s)
額外就是判斷一個單詞的算法也是值得考慮的問題,個人想法是,若是一個字符,它本身是一個字母,它前面是一個非字母,那麼這就是一個單詞的標緻。
這個參數比較特殊,由於它後面跟了一個文件,要作的事情是把輸出的內容存到的文件換成用戶自定義的名字。
總的來講是兩件事情
void lines_searching(FILE *fp, bool out_to_files){ int line = 0; int ch = 0; while(!feof(fp)){ ch = fgetc(fp); //putchar(ch); if(ch == '\n') line++; else continue; }//of while loop //printf("line is %d\n",line); output_to_sdo(line, "line", out_to_files); }//of character_searching function
void words_searching(FILE *fp, bool out_to_files){ int letter =0; int word = 0; bool is_word = FALSE; while(!feof(fp)){ letter = fgetc(fp); if((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z' ) || (letter == '\'')){ if(!is_word) //if if_word is false, it means this is a brand new word is_word = TRUE; }//of if else{ if(is_word){ word ++; is_word = FALSE; }//of if else continue; }//of else }//of while loop output_to_sdo(word, "word", out_to_files); }//of words_searching function
這個裏面有一些問題要考慮:
letter != '\n' || letter != '\t' || letter != ' '
void output_to_sdo(int number, char* name, bool out_to_files){ char result_fp_name[50];//the name of the result files char result[50]; //printf("%s\n",specific_file); if(number == 0) sprintf(result, "No %s in the file\n", name); else if(number == 1) sprintf(result, "1 %s in the file\n", name); else sprintf(result, "%d %ss in the file\n",number,name); printf("%s", result); if(out_to_files){ strcpy(result_fp_name, specific_file); }//of if else{ strcpy(result_fp_name, "result.txt"); }//of else FILE *result_fp = fopen(result_fp_name,"w"); fputs(result, result_fp); fclose(result_fp); }//of function output_to_fdo
主要是作簡單的系統測試,等價類和邊界值
從輸入的數據入用進行分析,本程序的輸入信息就是從命令行接受的一些數據,這些個數據能夠分爲兩人類
選項:控制程序運行的方式和輸出的方式,這類選項能夠分爲三類
1.1 -h
:這個選項不能和別人一用,並且這個選項不帶參數,它也不容許程序再帶參數;
1.1 -o
:這個選項須要和別人組合在一塊兒用,並且不能單用,在這個選項後面須要帶一個參數,並且也須要程序帶一個參數;
1.2
-w/-c/-l:它們都是是執行特色的查找任務的,這幾個選項不帶參數,可是須要程序帶一個參數。
參數:在本程序中也就是須要查找的文件,分紅這文件存在、不存在。
輸入條件 | 有效等價類 | 無效等價類 |
---|---|---|
選項 | -h (1)/ -w(2) / -l(3) / -c(4) / -o out(5) / -w -c(6) | -a(7) / -p(8) / -h -w(9) |
參數 | 文件(10) | 沒有文件(11) |
I loved you. But you didn't love me. I felt sad. But you seemed to feel happy. So I begun to hate you.
seven@mylab:~/wordcount/bin/linux_amd64$ cat result.in Usage: wc.exe [OPTIONS]... [FILE] --character -c calculate the numbers of characters in the file --word -w calculate the numbers of words in the file --line -l calculate the numbers of lines in the file --outtofile=x -o x transfer the result to the specific file
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -h input Wrong Parameter!
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w input 23 words in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -w input 23 input
與linux下自帶的wordcount(wc)的結果對比了下
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w nothing Fail to Open the File! seven@mylab:~/wordcount/bin/linux_amd64$ wc -w nothing wc: nothing: No such file or directory
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -l input 5 lines in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -l input 5 input
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -l nothing Fail to Open the File! seven@mylab:~/wordcount/bin/linux_amd64$ wc -l nothing wc: nothing: No such file or directory
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -c input 104 characters in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -c input 103 input
出現了不一樣
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -c nothing Fail to Open the File! seven@mylab:~/wordcount/bin/linux_amd64$ wc -c nothing wc: nothing: No such file or directory
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w -o result.log input 23 words in the file seven@mylab:~/wordcount/bin/linux_amd64$ cat result.log 23 words in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -w input > result.log seven@mylab:~/wordcount/bin/linux_amd64$ cat result.log 23 input
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w -h Fail to Open the File! seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w -h nohting Fail to Open the File! seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w -h input Wrong Parameter! 23 words in the file
這個用例沒有經過
for(int i = 1; i < argc-1; i++){ if(argv[i][0] == '-'){ switch(argv[i][1]){ case 'c': print_characters = TRUE; break; case 'l': print_lines = TRUE; break; case 'w': print_words = TRUE; break; case 'o': out_to_files = TRUE; strcpy(specific_file,argv[i+1]); //printf("%s\n",specific_file); break; case 'h'://add a case to detect -h printf("-h parameter should work alone!\n"); exit(0); default: printf("Wrong Parameter!\n"); }//of switch }//of if }//of for loop
seven@mylab:~/wordcount/src$ ./a.out -h input -h parameter should work alone!
經過測試!
檢查用例7
seven@mylab:~/wordcount/bin/linux_amd64$ printf "I hate you\nYou hate me\n" I hate you You hate me seven@mylab:~/wordcount/bin/linux_amd64$ printf "I hate you\nYou hate me\n" > my.ini seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -c my.ini 24 characters in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -c my.ini 23 my.ini
seven@mylab:~/wordcount/bin/linux_amd64$ echo "I really made a mistake??" > my.ini seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -c my.ini 27 characters in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -c my.ini 26 my.ini
while(!feof(fp)){ fgetc(fp); character ++; }//of while loop
這樣把最後一個結尾字符也記上了,因此應該把結果減去1.
seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w my.ini 5 words in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -w my.ini 5 my.ini seven@mylab:~/wordcount/bin/linux_amd64$ ./wc -w input 23 words in the file seven@mylab:~/wordcount/bin/linux_amd64$ wc -w input 23 input
seven@mylab:~/wordcount/src$ ./a.out -c input input, character number:23
#!/bin/sh #Author: seven #date: 2018/09/27 #aim: an automatic script to test the program #a function to print test result #function will receive 2 parameters, #first is the type of the test, #second is whether the test tested as expected test_result_print(){ if [ $2 -eq 1 ] then echo `date "+%Y-%m-%d %H:%M:%S"` " $1 test succeeded!" | tee -a test_log.txt else echo `date "+%Y-%m-%d %H:%M:%S"` " $1 test met with failure!" | tee -a test_log.txt fi } compare_result_with_standard(){ if [ "$1" = "$2" ] then if_test_success=1 else if_test_success=0 fi } test_file_name="input" #Here is the test for ./wc -h #the ideal result is the usage of the program standard_result="Usage: wc.exe [OPTIONS]... [FILE] --character -c calculate the numbers of characters in the file --word -w calculate the numbers of words in the file --line -l calculate the numbers of lines in the file --outtofile=x -o x transfer the result to the specific file" result=`./wc -h` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -h" $if_test_success #Here is the test for ./wc -h input #the ideal result is to print "-h parameter should work alone!" standard_result="-h parameter should work alone!" result=`./wc -h input` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -h print" $if_test_success #Here is the test for wc -w input standard_result=`wc -w $test_file_name | sed 's/[^0-9]//g'` result=`./wc -w $test_file_name | sed 's/[^0-9]//g'` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -w input" $if_test_success #Here is the test for wc -w nothing standard_result="Fail to Open the File!" result=`./wc -w nothing` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -w nothing" $if_test_success #Here is the test for wc -l nothing standard_result="Fail to Open the File!" result=`./wc -l nothing` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -l nothing" $if_test_success #Here is the test for wc -c input standard_result=`wc -c $test_file_name | sed 's/[^0-9]//g'` result=`./wc -c $test_file_name | sed 's/[^0-9]//g'` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -c input" $if_test_success #Here is the test for wc -c nothing standard_result="Fail to Open the File!" result=`./wc -c nothing` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -c nothing" $if_test_success #Here is the test for wc -w -o result.log input standard_result=`wc -w $test_file_name | sed 's/[^0-9]//g'` result=`./wc -w -o result.log $test_file_name | sed 's/[^0-9]//g'` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -w -o result.log input in std output" $if_test_success result=`cat result.log | sed 's/[^0-9]//g'` compare_result_with_standard "$result" "$standard_result" test_result_print "wc -w -o result.log input in outputfile" $if_test_success
測試結果:
seven@mylab:~/wordcount/bin/linux_amd64$ ./test.sh 2018-09-27 16:11:58 wc -h test succeeded! 2018-09-27 16:11:58 wc -h print test succeeded! 2018-09-27 16:11:58 wc -w input test succeeded! 2018-09-27 16:11:58 wc -w nothing test succeeded! 2018-09-27 16:11:58 wc -l nothing test succeeded! 2018-09-27 16:11:58 wc -c input test succeeded! 2018-09-27 16:11:58 wc -c nothing test succeeded! 2018-09-27 16:11:58 wc -w -o result.log input in std output test succeeded! 2018-09-27 16:11:58 wc -w -o result.log input in outputfile test succeeded!
完成一個還算比較難的程序(由於我總想着GNU寫過了的wc)對一個學生而言並不是易事,參考了不少(其實也很少),見下: