1. 程式人生 > >白盒測試(基本路徑法)程式碼

白盒測試(基本路徑法)程式碼

白盒測試的一種常用方法是基本路徑法,根據原始碼構造程式流程圖,轉換為控制流圖,得到基本路徑,進而為每條基本路徑設計測試用例。

基本路徑法的一個關鍵步驟是識別出所有的基本路徑。本次作業要求你寫一個C++程式:

  • 輸入:待測程式的控制流圖
  • 輸出:圈複雜度、基本路徑集合

基本要求

輸入:待測程式的控制流圖

包含多行資料。第1行表示控制流圖中的入口節點的編號,表示程式由此開始執行。後續每行代表控制流圖中的一條邊,表示為“1->2, T/F/N”,意即有一條邊從編號為1的節點指向編號為2的節點;T表示節點1為邏輯判斷節點且它為真的時候指向2;F表示節點1的條件為假的時候指向2;N表示節點1是基本語句,而不是邏輯判斷節點。最後一行為“END”,表示輸入結束。

例如,左側給出的控制流圖,相應的輸入資料如右側所示。

輸出:圈複雜度和基本路徑

輸出多行資料。第一行為“CC=n”,n為一個整數,表示計算得到的圈複雜度。後續各行,每一行代表一條基本路徑,格式為“1,2,3,5”的形式,逗號分隔開的是控制流圖中的節點編號。

下圖給出了一個示例。

注意:

  1. 在查詢基本路徑時,採用深度優先搜尋策略;若遇到判定節點,需遵循“先遍歷false分支,再遍歷true分支”的原則。
  2. 若某一條路徑出現迴圈,即:該路徑的後續部分已經在本路徑之前出現過,則在進入迴圈的第一個節點處停止,後續部分不需要再包含在該路徑中(例如1,2,3,9,10,2,3這樣的路徑,需簡化為1,2,3,9,10,2即可)。
  3. 需根據“基本路徑”的定義對每一條路徑進行檢查,看其中是否包含了之前其他路徑中不曾出現過的邊。若否,則將其去除;
  4. 若程式需要輸出多條基本路徑,按照路徑長度由小到大排序輸出;若兩個路徑的長度相等,則按相對應位置的數字大小由低到高排列(例如1,3,6,5和1,3,4,5兩條路徑,後者應該先輸出;1,10,8,3,4和1,9,10,3,4兩條路徑,後者應該先輸出)。

擴充套件要求

作業輸入中已經消除了“控制流圖中的所有判斷節點中包含複合條件表示式”的情形,即不存在通過and/or等邏輯運算子將多個單一條件表示式連線在一起的情況,例如 if (A and B)。

擴充套件:輸入資料中除了邊資訊之外,後續增加若干新行(與原有各行之間通過一行“EXT”分隔),每一行表示控制流圖中的判斷節點資訊,例如:

1, AND
3, OR

分別表示節點1是 if (A && B) 的形式、節點3是if (A || B)的形式。

只考慮and/or兩種邏輯運算子,且只考慮包含兩個單一條件表示式(A, B)的複合的情況。

為應對上述情況,你的程式應對原有控制流圖進行修改,使之變為標準的控制流圖的形式,再生成圈複雜度和基本路徑作為輸出。修改控制流圖後若需要引入新的節點,其編號可採用11、12、31、32來表示。(注:原有控制流圖中不會出同時出現1和11、12這樣的節點,因此在對其進行修改之後,不會出現編號衝突的情況。)

以下給出了一個例子,前一個是輸入,後一個為輸出。

程式語言: C++ (本地執行)
編譯器: g++ -m32 -D_MOODLE_ONLINE_JUDGE_ -Wall -static -o %DEST% %SOURCES% -lm
記憶體最多可用: 4MB
CPU使用時間上限: 5 秒

程式碼測試:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string>
#include<cstring>
using namespace std;
int result =0;
char sign1 = 'N';
int arcTail[100];
int arcHead[100];
int vexArr[100];

char biaodian[100]={'\0'};
int path[100]; 
string order_out = "";

typedef struct  POINT{
        int tail,head;  
        struct POINT *hlink, *tlink;    
        char biaodian; 
}POINT;

typedef struct POINT2{
        int data;
        bool visited;   
        POINT *fin, *fout;         

}POINT2;

typedef struct{
        POINT2 list[100]; 
        int vnum, anum;       
}Graph;

bool end1(string str){
     if(str == "END" || str == "end" || str == "EXT" || str == "ext")
            return true;
     return false;
}

int length(int num[]){
    int sum=0;
    for(int i=0; i<100; i++){
          if(num[i] != 0)
                sum++; 
          else
              break;
    }
    return sum;   
}

bool is_inArr(int ch[],int in){
     for(int i=0; i<length(ch); i++)
             if(in == ch[i])
                   return true;
     return false;
}



void insert(string str){
     int pos = length(vexArr);
     int i = length(arcTail);
     string _tail = str.substr(0,str.find('-'));
     string _head = str.substr(str.find('>')+1,str.find(',')-str.find('>')-1);
     char _biaodian = str[str.size()-1];
     if(!is_inArr(vexArr, atoi(_tail.c_str())))
          vexArr[pos++] = atoi(_tail.c_str());
     if(!is_inArr(vexArr, atoi(_head.c_str())))
          vexArr[pos++] = atoi(_head.c_str());
     arcTail[i] = atoi(_tail.c_str());
     arcHead[i] = atoi(_head.c_str());  
     biaodian[i] = _biaodian;         
}

int LocateVex(Graph *G, int vertex){
    int j=0,k;
    for(k=0; k<length(vexArr); k++)
             if(G->list[k].data == vertex){
                   j = k;
                   break;                   
             }    
    return j;
}

void CreateGraph(Graph *G){
     int _tail, _head;
     POINT *arcTemp;
     G->vnum = G->anum =0;
     for(int i=0; i<length(vexArr); i++){
             (*G).list[i].data = vexArr[i];
             G->list[i].fin = NULL;
             G->list[i].fout = NULL;  
             G->vnum++;  
             G->list[i].visited = false;
     }     

     //初始化弧並構建十字連結串列
     for(int i=0; i<length(arcTail); i++){
             if(biaodian[i] == 'T')
                     result ++;
             _tail = LocateVex(G,arcTail[i]);
             _head = LocateVex(G,arcHead[i]);
             arcTemp = (POINT*)malloc(sizeof(POINT));
             arcTemp->tail = _tail;
             arcTemp->head = _head;
             arcTemp->tlink = (*G).list[_tail].fout;
             (*G).list[_tail].fout = arcTemp;
             arcTemp->hlink = (*G).list[_head].fin;
             (*G).list[_head].fin = arcTemp;
             arcTemp->biaodian = biaodian[i]; 
             G->anum++;                       
     } 
}





void display(Graph *G,int arr[]){
     char ch[10];
     int temp =0;
     char is_no = 'N';
     for(int i=0; i<length(arr)-1; i++){
             string Arc = "";
             temp = arr[i];
             snprintf(ch,sizeof(ch),"%d",temp);
             Arc += ch;
             Arc += ",";
             temp = arr[i+1];
             snprintf(ch,sizeof(ch),"%d",temp);
             Arc += ch;
             if(order_out.find(Arc) != order_out.npos) 
                      continue;
             else{
                 is_no = 'Y';
                 break;
             } 
             i += 1;     
     }
     if(is_no == 'Y'){
              memset(ch,0,10);

     for(int i=0; i<length(arr)-1; i++){
             temp = arr[i];
             snprintf(ch,sizeof(ch),"%d",temp);
             order_out += ch;
             order_out += ",";
     }
     memset(ch,0,10);
     snprintf(ch,sizeof(ch),"%d",arr[length(arr)-1]);
     order_out += ch;
     order_out += "|"; 
     }
}

int my_memset(int arr[],int _data){
     int pos = 0;
     int _length = length(arr);
     for(int i=0; i<_length; i++)
           if(_data == arr[i]){
                     pos = i;
                     break;
           }
     for(int i=pos+1; i<_length; i++)
             arr[i] = 0;  
     //display(arr); 
     return pos;  
}
void changeVisited(Graph *G,int arr[], int num){
     char is_find_ = 'N';
     int pos =0;
     for(int i=0; i<length(arr); i++){
             if(arr[i] == num){
                       is_find_ = 'Y';
                       i++;          
             }    
             if(arr[i] != 0)
                       if(is_find_ == 'Y'){    
                                pos = LocateVex(G,arr[i]);
                                G->list[pos].visited = false;
                       }
     }     
}

//有向圖的深度非遞迴遍歷 
void DFSTraverse(Graph G, int pos){
     POINT *p;
     POINT *Queue[100*100];
     int Vex[100]={0};
     int _len_=0;
     int queue = -1;
     int pointer = -1;
     p = G.list[pos].fout;
     path[++pointer] = G.list[pos].data;
     if(!p){
           display(&G,path);
           return;
     }
     while(p){ 
           if(!is_inArr(path,G.list[p->tail].data))
                  path[++pointer] = G.list[p->tail].data;
           if(p->biaodian != 'N'){ 
                       //若遇到先前遍歷過的結點則直接走F就行,T不予考慮 
                  if(is_inArr(Vex,G.list[p->tail].data) && (!G.list[p->tail].visited)){
                            if(p->biaodian == 'T')
                                        p = p->tlink;
                  }
                  else{
                       if((p->biaodian == 'T') && (!G.list[p->tail].visited)){
                             Queue[++queue] = p;
                             p = p->tlink;
                       }
                       else if(p->biaodian == 'F')
                            Queue[++queue] = p->tlink; 
                       G.list[p->tail].visited = true;
                       if(!is_inArr(Vex,G.list[p->tail].data))
                            Vex[_len_++] = G.list[p->tail].data; 
                  }
           }
           if(is_inArr(path,G.list[p->head].data)){
                  path[++pointer] = G.list[p->head].data;  
                  if(queue >= 0){ 
                                display(&G,path);         
                                p = Queue[queue];
                                queue --; 
                                pointer = my_memset(path,G.list[p->tail].data);     
                                changeVisited(&G,Vex,G.list[p->tail].data);
                  }
                  //不加else會導致死迴圈,因為到最後一層的時候陣列為空。直接把頭結點加入到迴圈佇列中 
                  else{  
                         display(&G,path); 
                         break;
                  }
                  continue;                                            
           }
           path[++pointer] = G.list[p->head].data;
           pos = LocateVex(&G,G.list[p->head].data);
           p = G.list[pos].fout;
           if(!p){
                if(queue >= 0){     
                      display(&G,path); 
                      p = Queue[queue];
                      queue --;  
                      pointer = my_memset(path,G.list[p->tail].data);
                      changeVisited(&G,Vex,G.list[p->tail].data);
                }
                else{
                     display(&G,path);
                     break;     
                }
           }
     }
}

int returnNum(string str,char ch){
    int sum =0;
    while(str.size()){
          int pos = str.find(ch);
          if(pos != str.npos){
               str = str.substr(pos+1);
               sum++; 
          }
          else 
               break;          
    }
    return sum+1;   
}

void remove_(string str){
     int pos = order_out.find(str);
     order_out.replace(pos,str.size()+1,"");     
}

bool my_compare(string str1,string str2){
     str1 += ",";
     str2 += ",";
     string temp1 = "";
     string temp2 = "";
     int pos1 = str1.find(',');
     int pos2 = str2.find(',');
     while(str1.size()){
              temp1 = str1.substr(0,pos1);
              temp2 = str2.substr(0,pos2);
              if(atoi(temp1.c_str()) > atoi(temp2.c_str()))
				  return true;  
              else if(atoi(temp1.c_str()) < atoi(temp2.c_str()))
                  return false;
              str1 = str1.substr(pos1+1);
              pos1 = str1.find(',');
              str2 = str2.substr(pos2+1);  
              pos2 = str2.find(',');                
     }     
}

void orderDisplay(string str){
     string ordered = "";
     string _str = str;
     string small = str;
     int small_num = 100;
     string temp = "";
     char end1 = 'N';
     int pos = str.find('|');
     while(str.size()){
     for(int i=0; i<_str.size(); i++){
           temp = _str.substr(0,pos);
           if(returnNum(temp,',') < small_num){
                        small = temp;
                        small_num = returnNum(temp,',');
           }
           else if(returnNum(temp,',') == small_num)
                 if(my_compare(small,temp)){
                              small = temp; 
                              small_num = returnNum(temp,',');
                 }
           if(end1 == 'N'){
                _str = _str.substr(pos+1);  
                pos = _str.find('|');
                if(pos != _str.npos)
                     continue;
                else{
                     pos = _str.size();
                     end1 = 'Y';     
                }
           } 
           else
               break;   
     }
     ordered += small;
     ordered += "|";
     int _pos = str.find(small);
     str.replace(_pos,small.size()+1,"");
     _str = small = str;
     small_num =100;
     pos = str.find('|');
     end1 = 'N';
     }     
     order_out = ordered;  
}

void coutResult(string str){
     int pos = str.find('|');
     string temp;
     while(str.size()){
              temp = str.substr(0,pos);
              cout << temp << endl;
              str = str.substr(pos+1);
              pos = str.find('|');                  
     }
}

void changeVexArr(int num){
     for(int i=0; i<length(vexArr); i++)
             if(vexArr[i] == num){
                   vexArr[i] = num*10 + 1;
                   vexArr[length(vexArr)] = num*10 + 2;
                   break;             
             }             
}

void CreatePath(string str){
     string _vertex = str.substr(0,str.find(','));
     string _condition = str.substr(str.find(',')+1);
     int _num = atoi(_vertex.c_str());
     int _T = 0,_F = 0,_in[100]={0};
     int l = length(arcTail);
     int l_l =0;
     changeVexArr(_num);  
     for(int i=0; i<l; i++)
                   if(arcHead[i] == _num)
                          _in[l_l++] = i;                    
     for(int j=0; j<l; j++){
                   if((biaodian[j] == 'F') && (arcTail[j] == _num))
                        _F = j;
                   else if((biaodian[j] == 'T') && (arcTail[j] == _num)) 
                        _T = j;                            
     }
     for(int i=0; i<l_l; i++)
                   arcHead[_in[i]] = _num*10+1;
     if(_condition == "AND"){   
           int _into = length(arcTail);
           arcTail[_F] = _num*10+1;   
           arcTail[_into] = _num*10+1;   
           arcHead[_into] = _num*10+2;
           biaodian[_into] = 'T';
           _into ++;
           arcTail[_T] = _num*10+2;
           arcTail[_into] = _num*10+2;
           arcHead[_into] = arcHead[_F];
           biaodian[_into] = 'F';
     }

     else if(_condition == "OR"){

           int _into = length(arcTail);
           arcTail[_T] = _num*10+1;
           arcTail[_into] = _num*10+1;
           arcHead[_into] = _num*10+2;
           biaodian[_into] = 'F';
           _into++;
           arcTail[_F] = _num*10+2;
           arcTail[_into] = _num*10+2;
           arcHead[_into] = arcHead[_T];
           biaodian[_into] = 'T';
     }
}
/*
void xianshi(){
    for(int i=0; i<length(vexArr); i++)
            cout << vexArr[i] << endl;
    for(int i=0; i<length(arcTail); i++)
            cout << arcTail[i] << "->" << arcHead[i] << "," << biaodian[i] << endl;     
}
*/
int main(){
    Graph G;
    int i=0;
    string temp ="";
	memset(arcTail,0,sizeof(arcTail));
	memset(arcTail,0,sizeof(arcHead));
	
	memset(arcTail,0,sizeof(vexArr));
    int _header = 0;
    getline(cin,temp);

    if(temp == "END")
            return 0;
    vexArr[i++] = atoi(temp.c_str());
    while(1){
             getline(cin,temp);
             if(temp == "EXT" || temp == "ext")
                   sign1 = 'Y';
             if(end1(temp)) 
                   break;
             insert(temp);        
    }
    if(sign1 == 'Y')
             while(1){
                      getline(cin,temp);
                      if(end1(temp))
                            break;
                      CreatePath(temp); 
             }
    CreateGraph(&G);
    DFSTraverse(G,LocateVex(&G,vexArr[0]));
    cout << "CC=" << returnNum(order_out,'|')-1 << endl;
    for(int i=0;i<10;i++)
    orderDisplay(order_out);
    coutResult(order_out);
	//while(1)
		//getchar();
    return 0;   
}