圖解安裝CLion編寫程序並進行單元測試


我對JetBrains公司的IDE情有獨鍾,於是這里使用的IDE是CLion,CLion是以IntelliJ為基礎,專為開發C及C++所設計的跨平台IDE,可以在Windows、Linux及MacOS使用。

本文介紹了在Linux系統(以Ubuntu16.04為例)下如何安裝CLion-2016.2.2(及其破解)和它的簡單使用。

一、安裝CLion

1、從CLion官網下載最新版CLion安裝包,其Linux版是.tar.gz的壓縮包。

netcon@conwlt:~$ wget https://download.jetbrains.8686c.com/cpp/CLion-2016.2.2.tar.gz

2、下載完成后,解壓壓縮包。

netcon@conwlt:~$ tar -zxvf CLion-2016.2.2.tar.gz

 3、進入到安裝目錄下的bin目錄下,運行clion.sh即可。

netcon@conwlt:~$ cd clion-2016.2.2/bin/
netcon@conwlt:~/clion-2016.2.2/bin$ ./clion.sh

4、首次打開會設置workspace,之前沒安裝過直接點OK即可。

5、然后就是每次安裝都有但每次都沒人讀的使用協議了,Accpect即可。

 

6、然后是激活操作,由於CLion是收費的,可以選擇試用30天。如果有經濟能力的話使用正版軟件自然是更好,但是現在我還沒那個能力,所以只能另辟蹊徑,搭建了一個破解的服務器,地址是:http://bash.pub:1017,如今網上其他的破解方案基本不能用了。這個Server也可以激活JetBrains的同類其他產品,大家如果有需要,請低調使用。選擇License server,正確輸入后,點擊Activate即可。

7、選擇自己喜歡的主題。

8、配置CMake及debugger,默認即可。

9、默認插件,無須改變,繼續即可。

10、特色插件,按需安裝,這里只是演示我沒有安裝,也可以以后安裝。

11、最后一步,創建桌面菜單圖標。

至此,CLion已經被我們成功安裝!

二、創建工程及編寫代碼

1、安裝成功后我們可以在應用程序列表中找到CLion,打開后進入創建工程頁面。

2、創建完成后就可以看到CLion的主界面了,左側是工程目錄,MaxSubArraySum就是我們剛剛創建的工程,展開它並打開main.cpp,我們的代碼講在這里編寫(如果覺得字體不合適請自行百度如何修改,這里不再介紹)。

3、點擊Run -> Run 'Build All',即可運行程序。(首次運行可能要求編輯配置文件,只需要將Target設置為MaxSubArraySum即可)。

運行成功!在下方的控制台可以看到結果!

三、使用Coding.net存放代碼

我們已經完成了編寫代碼的任務,接下來把代碼push到遠程git倉庫吧!

CLion當然支持版本控制工具,建立好Git倉庫后,右鍵項目名稱,依次選擇Git -> Repositories -> push即可。

我們可以在CLion中方便的使用Git的各種功能而不用輸入Git命令,但是個人還是喜歡Shell操作。

項目地址:https://coding.net/u/netcon/p/MaxSubArraySum/git

關於最大連續子數列和問題的解法可以參考這篇文章:

經典算法問題 - 最大連續子數列和

關於Coding.net和Git的使用可以參考這兩篇文章:

1、Coding.net簡單使用指南

2、Git簡易使用指南

四、測試代碼

1、單元測試

由於代碼使用C++語言編寫, CLion沒有官方的CUnit單元測試插件(貌似這方面就VS做得好,可惜不能跨平台),如果使用的話可以把測試框架的源碼拷貝到工程中,與其多此一舉,不如直接在Shell中測試,我這里采用了Google的GTest測試框架,並進行了簡單配置,以下時配置后的GTest目錄結構:

netcon@conwlt:~/gtest$ tree -L 2
.
├── codes
│   ├── main.cpp │   ├── Makefile │   └── test.cpp ├── include │   └── gtest └── src ├── gtest-all.cc ├── gtest.cc ├── gtest-death-test.cc ├── gtest-filepath.cc ├── gtest-internal-inl.h ├── gtest_main.cc ├── gtest-port.cc ├── gtest-printers.cc ├── gtest-test-part.cc └── gtest-typed-test.cc 4 directories, 13 files netcon@conwlt:~/gtest$ 

下面是其Makefile。

GTEST_DIR = ..
USER_DIR = .
CPPFLAGS += -isystem $(GTEST_DIR)/include
CXXFLAGS += -g -Wall -Wextra -pthread
TESTS = run_test
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
                $(GTEST_DIR)/include/gtest/internal/*.h
FILES = $(foreach d, $(USER_DIR), $(wildcard $(d)/*.cpp))
OBJS = $(patsubst %.cpp, %.o, $(FILES))


all : $(TESTS)

clean :
    rm -f $(TESTS) gtest_main.a *.o

GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

gtest-all.o : $(GTEST_SRCS_)
    $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
            $(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
    $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
            $(GTEST_DIR)/src/gtest_main.cc

gtest_main.a : gtest-all.o gtest_main.o
    $(AR) $(ARFLAGS) $@ $^

%.o : %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

$(TESTS) : $(OBJS) gtest_main.a
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@

我們用其測試以下MaxSubArraySum項目中nlogn分支下的代碼,這份代碼是采用分治法解決這個問題的,源碼及測試代碼如下:

/**
 * File name: main.cpp
 *
 * 最大連續子數列問題的O(NlogN)解法,分治法
 *
 * Author: netcon
 * Email: netcon@live.com
 * Blog: http://conw.net
 *
 */

//N是數組長度,num是待計算的數組
int solve(int N, int *num, int left, int right)
{
    //數列長度為1時
    if(left == right)
        return num[left];
    
    //划分為兩個規模更小的問題
    int mid = (left + right) >> 1;
    int lans = solve(N, num, left, mid);
    int rans = solve(N, num, mid + 1, right);
    
    //橫跨分割點的情況
    int sum = 0, lmax = num[mid], rmax = num[mid + 1];
    for(int i = mid; i >= left; i--) {
        sum += num[i];
        if(sum > lmax) lmax = sum;
    }
    sum = 0;
    for(int i = mid + 1; i <= right; i++) {
        sum += num[i];
        if(sum > rmax) rmax = sum;
    }

    //答案是三種情況的最大值
    int ans = lmax + rmax;
    if(lans > ans) ans = lans;
    if(rans > ans) ans = rans;

    return ans;
}
/**
 * File name: test.cpp
 */

#include "gtest/gtest.h"

int solve(int, int *, int, int);

int N[3] = {5, 5, 8};
int num[3][8] = {
    {1, 2, 3, 4, 5},
    {-1, -2, -3, -4, -5},
    {}
};
int ans[3] = {15, -1, 14};

TEST(MaxSubArraySum, Positive) {
    EXPECT_EQ(ans[0], solve(N[0], num[0], 0, N[0] - 1));
}

TEST(MaxSubArraySum, Negative) {
    EXPECT_EQ(ans[1], solve(N[1], num[1], 0, N[1] - 1));
}

TEST(MaxSubArraySum, Random) {
    EXPECT_EQ(ans[2], solve(N[2], num[2], 0, N[2] - 1));
}

 

 測試結果:

netcon@conwlt:~/gtest/codes$ ls
main.cpp  Makefile  test.cpp
netcon@conwlt:~/gtest/codes$ make
g++ -isystem ../include -g -Wall -Wextra -pthread -c main.cpp -o main.o
g++ -isystem ../include -g -Wall -Wextra -pthread -c test.cpp -o test.o
g++ -isystem ../include -I.. -g -Wall -Wextra -pthread -c \
            ../src/gtest-all.cc
g++ -isystem ../include -I.. -g -Wall -Wextra -pthread -c \
            ../src/gtest_main.cc
ar rv gtest_main.a gtest-all.o gtest_main.o
ar: creating gtest_main.a
a - gtest-all.o
a - gtest_main.o
g++ -isystem ../include -g -Wall -Wextra -pthread -lpthread main.o test.o gtest_main.a -o run_test
netcon@conwlt:~/gtest/codes$ ./run_test 
Running main() from gtest_main.cc
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from MaxSubArraySum
[ RUN      ] MaxSubArraySum.Positive
[       OK ] MaxSubArraySum.Positive (0 ms)
[ RUN      ] MaxSubArraySum.Negative
[       OK ] MaxSubArraySum.Negative (0 ms)
[ RUN      ] MaxSubArraySum.Random
[       OK ] MaxSubArraySum.Random (0 ms)
[----------] 3 tests from MaxSubArraySum (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 3 tests.
netcon@conwlt:~/gtest/codes$ make clean
rm -f run_test gtest_main.a *.o
netcon@conwlt:~/gtest/codes$ 

 

2、大規模數據測試 

大量的數據測試是最能體現代碼正確性的,這里我寫了一個生成數據的腳本自動生成數據。

# generate the test data
import random
# N is the length of the sequence
N = 10000000
# MAX_ABS is the max absolute value of the numbers in the sequence
MAX_ABS = 1024
def rand(n):
    return int((random.random() - 0.5) * 2 * n)
out = str(rand(MAX_ABS))
for i in range(1, N):
    out += ' ' + str(rand(MAX_ABS))
print(N)
print(out)

 上述Python腳本會生成一千萬規模的數據!那么如何測試呢,我們使用一個O(N)的算法與一個O(NlogN)的程序比較結果是否相同。

先看一下各文件的內容:

/**
 * File name: nlogn.cpp
 *
 * 最大連續子數列問題的O(NlogN)解法,分治法
 *
 * Author: netcon
 * Email: netcon@live.com
 * Blog: http://conw.net
 *
 */

#include <stdio.h>

//N是數組長度,num是待計算的數組,放在全局區是因為可以開很大的數組
int N, num[16777216];

int solve(int left, int right)
{
    //數列長度為1時
    if(left == right)
        return num[left];
    
    //划分為兩個規模更小的問題
    int mid = (left + right) >> 1;
    int lans = solve(left, mid);
    int rans = solve(mid + 1, right);
    
    //橫跨分割點的情況
    int sum = 0, lmax = num[mid], rmax = num[mid + 1];
    for(int i = mid; i >= left; i--) {
        sum += num[i];
        if(sum > lmax) lmax = sum;
    }
    sum = 0;
    for(int i = mid + 1; i <= right; i++) {
        sum += num[i];
        if(sum > rmax) rmax = sum;
    }

    //答案是三種情況的最大值
    int ans = lmax + rmax;
    if(lans > ans) ans = lans;
    if(rans > ans) ans = rans;

    return ans;
}

int nlogn()
{
    freopen("in.txt", "r", stdin);
    //輸入數據
    scanf("%d", &N);
    for(int i = 1; i <= N; i++)
        scanf("%d", &num[i]);

    int ans = solve(1, N);

    return ans;
}
/**
 * File name: on.cpp
 *
 * 最大連續子數列問題的O(N)解法,空間復雜度O(1)
 *
 * Author: netcon
 * Email: netcon@live.com
 * Blog: http://conw.net
 *
 */

#include <stdio.h>

int on()
{
    int N, n, s, ans, m = 0;
    
    freopen("in.txt", "r", stdin);
    scanf("%d%d", &N, &n); //讀取數組長度和數列中的第一個數
    ans = s = n; //把ans初始化為數列中的的第一個數
    for(int i = 1; i < N; i++) {
        if(s < m) m = s;
        scanf("%d", &n);
        s += n;
        if(s - m > ans)
            ans = s - m;
    }

    return ans;
}

測試文件很簡單:

/**
* File name: test.cpp
*/
#include "gtest/gtest.h" int on(); int nlogn(); TEST(MaxSubArraySum, Positive) { EXPECT_EQ(on(), nlogn()); }

測試結果:

netcon@conwlt:~/gtest/codes$ ls
in.txt  Makefile  nlogn.cpp  on.cpp  test.cpp  test.py
netcon@conwlt:~/gtest/codes$ python test.py > in.txt
netcon@conwlt:~/gtest/codes$ make
g++ -isystem ../include -g -Wall -Wextra -pthread -c on.cpp -o on.o
g++ -isystem ../include -g -Wall -Wextra -pthread -c test.cpp -o test.o
g++ -isystem ../include -g -Wall -Wextra -pthread -c nlogn.cpp -o nlogn.o
g++ -isystem ../include -I.. -g -Wall -Wextra -pthread -c \
            ../src/gtest-all.cc
g++ -isystem ../include -I.. -g -Wall -Wextra -pthread -c \
            ../src/gtest_main.cc
ar rv gtest_main.a gtest-all.o gtest_main.o
ar: creating gtest_main.a
a - gtest-all.o
a - gtest_main.o
g++ -isystem ../include -g -Wall -Wextra -pthread -lpthread on.o test.o nlogn.o gtest_main.a -o run_test
netcon@conwlt:~/gtest/codes$ ./run_test 
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MaxSubArraySum
[ RUN      ] MaxSubArraySum.Positive
[       OK ] MaxSubArraySum.Positive (2790 ms)
[----------] 1 test from MaxSubArraySum (2790 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (2790 ms total)
[  PASSED  ] 1 test.
netcon@conwlt:~/gtest/codes$ make clean 
rm -f run_test gtest_main.a *.o
netcon@conwlt:~/gtest/codes$ 

測試通過!而且速度很快!一千萬的數據不到三秒的時間兩個程序都跑完了,我覺得,這還是IO占了很大一部分時間,而且O(NlogN)也確實會比O(N)慢很多。

用例編號 用例描述 輸入數據 預期輸出數據 實際輸出數據 通過/不通過 評價
 0  全是正數的測試樣例 1 2 3 4 5  15  15  通過

輸入數據全是正數,

結果必然時數列的和

 1  全是負數的測試樣例  -1 -2 -3 -4 -5  -1  -1  通過  

輸入數據全是負數,結

果必然時數列中最小值

 2  正數負數混合的隨機數列 -2 6 -1 5 4 -7 2 3  14  14  通過

輸入數據正負數混合,則

需要考慮多種情況。

 3  一千萬規模的數據  不能展示  不同版本程序輸出相同  不同版本程序輸出相同  通過

用很大規模的數據測試

程序,可以覆蓋程序盡可

能多的情況,並且考察程

序的執行效率。雖無法知道

數據的正確結果,但多個版

本的算法都得到相同答案,

可基本證明程序沒問題。

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM