# EE308 LAB2

The Link of Requirement of This Assignmenthttps://bbs.csdn.net/topics/600798588
The Aim of This AssignmentCode individually & learn how to use git and submit codes & learn how to use unit test and performance test & extract keywords of different levels from the C or C++ code files that are read in.
MU STU ID and FZU STU ID19104553 and 831902205

You can visit my github website: My github website

Directory

PSP Form

Preparation

Problem-solving Ideas

Design and Implementation Process

Code Description

Unit Test

Coverage Optimization and Performance Testing

Summary

# PSP Form

Personal Software Process StagesEstimated Time/minutesCompleted Time/minutes
Planning3030
Estimate1515
Development--
Analysis120210
Design Spec6060
Design Review3030
Coding Standard1010
Design100200
Coding600900
Code ReviewPlanning6045
Test120150
Reporting--
Test Report--
Size Measurement1010
Postmortem&Process Improvement120150
total12751810

# Preparation

I have learned the basic grammar of Java, C++ and Python. According to this lab

's requirements, I decide to use Python.

According to other blogs, I learned how to use github and git to submit my files to the repository on Github for the first time. I submitted my first file to Github by using remote clone repositories.

Since I have no idea what coding styles I can use, I revise my coding styles depending on the content of this website: PEP8 and the code specification is Code Specification

Because I have been learning Python for less than one months, I need to search for the corresponding functions of Python on the Internet which takes me a lot of time. For instance, I don't know how to achieve the implement of stack in Python, so I browsed the Internet for a long time, just like the image below:

What a hard work it was!

# Problem-solving Ideas

According to the requirements of this lab, I seperate the code into two steps.

1. Process the data
2. Achieve the requirements of this lab step by step

So the main purpose of the first step is to eliminate the effect of the comment. I decide to use the regular expression to solve the problem. The regular expression can match not only the complete English word, but also the unnecessary comments and words.

The needed regular expressiong is shown below:

1. Comment: r"(\/\*([^\*^\/]*|[\*^\/*]*|[^\**\/]*)*\*\/|\/\/.*|'.*'|\"([^\"]*)\")"
2. English Word: r'\b[a-zA-Z]+\b'
3. else if: r"\be.*?f\b"

Based on these expressions, I can identify the comments and the English words. After reading and processing the data, I can proceed the second step.

And the second step can be divided into three little steps according to the requirements. Before every little steps, the data must be processed again using regular expressions.

1. Use regular expressions to identify the words from other symbols, count the number of every words and add the number together, then get the final result.
2. Just like the first little step, the English words are identified. So how to count the number of keyword "switch" ? I think the "switch" can only be counted after the next "switch" appears. And the cases of one "switch" can be counted between two "switch" by using a flag to indicate whether the process is between two "switch".
3. So how to count the number of if, else and if-elseif-else? The first thing is to eliminate the space of "else if" between "else" and "if". And then we continue to do the real operations. I think the stack can be used. Once a "if" has been identified, this "if" will be pushed into "stack". And the size of stack will be checked. If the size is bigger than one, the program will go the next judge. If we encounter a "elseif" and the last value of the stack is "if", this "elseif" will be pushed into this stack too. If we encounter a "else", then we will check the last value of stack. If the last value is "if", then we can conclude that it is a "if-else" structure. Otherwise, we will pop the stack and calculate the number of "if-else-if".

# Code Description

• Stack. Since I decide to use stack in the function "countIfElseIf", I write a stack class by hand by referencing other's blogs.
class Stack(object):
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
def value(self,num):
return self.items[num]
• Read the file. Because I am not very familiar with the way of reading in a file, I search on the Internet and I found the function "open" and it can detect whether this file is c or c++.
result = []
if file_name.endswith('.cpp') or file_name.endswith('.c'):
fr = open(file_name, 'r')
for line in fr:
result.append(line)
fr.close()
text = "".join(result)

And then the comment should be replaced with ' '.

reg = r"(\/\*([^\*^\/]*|[\*^\/*]*|[^\**\/]*)*\*\/|\/\/.*|'.*'|\"([^\"]*)\")" #Replace the comment
com = re.finditer(reg,text)
for key in com:
text = text.replace(key.group(),' ')
•  Count the number of keywords.AS mentioned above, the English words can be identified using regular expression.
reg = r'\b[a-zA-Z]+\b'
line = re.findall(reg, text)
res = {}
for word in kwList:
num = line.count(word)
if num != 0:
res[word] = num
items = list(res.items())
sum = 0
for i in range(len(items)):
kw, num = items[i]
# print(kw, 'num : ', num)
sum += num

•  Count the number of "switch" and corresponding cases. The first idea is to use default, which ends the match. On second thought, not every switch has a default. So I think the "switch" can only be counted after the next "switch" appears. And the nested "switch" should not be considered according to TA.
def countSwitch(text):
reg = r'\b[a-zA-Z]+\b'
line = re.findall(reg, text)
switch_num = 0
flag = 0
case_num = []
if line.count('switch') == 0:
print("There is no switch keyword in the keywords list")
return 0
for kw in line:
if kw == 'switch':
switch_num += 1
flag = 1
case_num.append(0)
if flag == 1 and kw == 'case':
case_num[switch_num-1] += 1
print("switch num: ", switch_num)
for i in range(len(case_num)):
print("Case num for No.{} switch: {}".format(i+1, case_num[i]))
•  Count the number of "if-else" and "if-elseif-else". Since there exists a space in "else if" between "else" and "if", I use a function to replace " " with '' based on the regular expression mentioned above.
def replaceElseIf(text, reg):
elseIf = re.finditer(reg, text)
for key in elseIf:
text = text.replace(key.group(), 'elseif')
return text

And then the number of two structures can be counted

def countIfElseIf(text, level):
reg = r"\be.*?f\b"
reg1 = r'\b[a-zA-Z]+\b'
newText = replaceElseIf(text, reg)
newkwList = re.findall(reg1, newText)
ifelse_num = 0
ifelifelse_num = 0
ifelifelse_flag = 0
stack = Stack()
for kw in newkwList:
if kw == 'if':
stack.push('if')
if stack.size() >= 1:
if kw == 'elseif':
if stack.value(-1) == 'if':
stack.push('elseif')
elif kw == 'else':
if stack.value(-1) == 'if':
ifelse_num += 1
else:
while (stack.value(-1) != 'if'):
ifelifelse_flag = 1
stack.pop()
stack.pop()
if ifelifelse_flag:
ifelifelse_num += 1
ifelifelse_flag = 0
if level == 3:
print("if-else num: {}".format(ifelse_num))
if level == 4:
print("if-elif-else num: {}".format(ifelifelse_num))
• The main function is shown below:
if __name__ == "__main__":
kwList = ["auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum",
"extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while"]
level = int(input("Please enter the level you want(1-4): "))
if level == 1:
countKeyWords(kwList, text)
elif level == 2:
countSwitch(text)
else:
countIfElseIf(text, level)

• More than 10 commits:

Source code: LAB2.py

# Unit Test

I haven't heard this word before this lab, so I searched on the Internet and obtained some results. I created a new file and added following codes:

import unittest
import 软件工程lab2

class test(unittest.TestCase):
path = "d:/test.c"

def test_countKeywords(self):
kwList = ["auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum",
"extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while"]
self.assertEqual(软件工程lab2.countKeyWords(kwList, text), 35)

def test_countSwitch(self):
self.assertEqual(软件工程lab2.countSwitch(text), 2)

def test_count_if_else(self):
self.assertEqual(软件工程lab2.countIfElseIf(text, 3), [2, 2])

if __name__ == '__main__':
unittest.main()

And after running this program,  I get the output:

It seems that everything is OK, my code has passed the unit test.

# Coverage Optimization and Performance Testing

I haven't heard these words before this lab, so I searched on the Internet and obtained some results.

By using the coverage tool in Python, I obtained the results:

According to the above images, I have my coverage optimization which is 96%. And the missing code is the warning when we don't have "switch" keyword and some codes in stack class. It can be concluded that most codes are covered.

After searching on the Internet, I use cProfile of Python and get the final result of performance testing. It seems that my code performs well.

         211 function calls in 0.003 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1    0.000    0.000    0.003    0.003 <frozen importlib._bootstrap>:1002(_find_and_load)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:112(release)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:152(__init__)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:156(__enter__)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:160(__exit__)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:166(_get_module_lock)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:185(cb)
2    0.000    0.000    0.002    0.001 <frozen importlib._bootstrap>:220(_call_with_frames_removed)
10    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:231(_verbose_message)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:351(__init__)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:385(cached)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:398(parent)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:406(has_location)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:486(_init_module_attrs)
1    0.000    0.000    0.002    0.002 <frozen importlib._bootstrap>:558(module_from_spec)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:58(__init__)
1    0.000    0.000    0.002    0.002 <frozen importlib._bootstrap>:659(_load_unlocked)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:736(find_spec)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:811(find_spec)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:87(acquire)
3    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:874(__enter__)
3    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:878(__exit__)
1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap>:901(_find_spec)
1    0.000    0.000    0.003    0.003 <frozen importlib._bootstrap>:967(_find_and_load_unlocked)
7    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:114(<listcomp>)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1155(__init__)
1    0.000    0.000    0.002    0.002 <frozen importlib._bootstrap_external>:1171(create_module)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1179(exec_module)
3    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1337(_path_importer_cache)
3    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:135(_path_stat)
1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap_external>:1374(_get_spec)
1    0.000    0.000    0.001    0.001 <frozen importlib._bootstrap_external>:1406(find_spec)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:145(_path_is_mode_type)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1500(_get_spec)
2    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1505(find_spec)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:154(_path_isfile)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:167(_path_isabs)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:491(_get_cached)
2    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:64(_relax_case)
1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:696(spec_from_file_location)
7    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:91(_path_join)
1    0.000    0.000    0.000    0.000 <string>:1(<module>)
5    0.000    0.000    0.000    0.000 {built-in method _imp.acquire_lock}
1    0.002    0.002    0.002    0.002 {built-in method _imp.create_dynamic}
1    0.000    0.000    0.000    0.000 {built-in method _imp.exec_dynamic}
1    0.000    0.000    0.000    0.000 {built-in method _imp.is_builtin}
1    0.000    0.000    0.000    0.000 {built-in method _imp.is_frozen}
5    0.000    0.000    0.000    0.000 {built-in method _imp.release_lock}
2    0.000    0.000    0.000    0.000 {built-in method _thread.allocate_lock}
2    0.000    0.000    0.000    0.000 {built-in method _thread.get_ident}
1    0.000    0.000    0.003    0.003 {built-in method builtins.exec}
6    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
4    0.000    0.000    0.000    0.000 {built-in method builtins.hasattr}
3    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
15    0.000    0.000    0.000    0.000 {built-in method builtins.len}
1    0.000    0.000    0.000    0.000 {built-in method nt._path_splitroot}
1    0.000    0.000    0.000    0.000 {built-in method nt.fspath}
3    0.001    0.000    0.001    0.000 {built-in method nt.stat}
2    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.lock' objects}
7    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
24    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
2    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
7    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
1    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
1    0.000    0.000    0.000    0.000 {method 'replace' of 'str' objects}
4    0.000    0.000    0.000    0.000 {method 'rpartition' of 'str' objects}
21    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
15    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}

# Summary

1. After four days' hard work, I have browsed hundreds of websites. It is really an unforgettable experience because I realized that writing code is only a small part of the assignment, sourcing and optimizing code takes up most of the time.
2. After this lab, I have a deeper understanding of Python. And I learned how to do unit test and performance test which improved my ability of finding information.
3. During the discussion with my classmates, I realized that I still had many things to consider, such as the removal of header files.

• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

03-27
10-09 465