月度归档:2014年10月

二叉树C语言递归算法演示

二叉树的定义

在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常根的子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在出度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

二叉树节点定义

struct BTNode {                    //定义二叉树节点名称, B表示二, T表示树, Node表示节点
char data;                    //定义二叉树数据域
struct BTNode * pLchild;    //定义二叉树左指针
struct BTNode * pRchild;    //定义二叉树右指针
};

继续阅读

汉诺塔C语言算法演示

汉诺塔简介:

有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:

  1. 每次只能移动一个圆盘;
  2. 大盘不能叠在小盘上面。

提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。

汉诺塔移动分析:

定义汉诺塔移动函数:

void hanoi(int n, char from, char buffer, char to);

1) 参数 n 表示要移动的盘子数

2) 参数 from 表示盘子所在的柱子

3) 参数 buffer 表示盘子移动过程中借助的柱子

4) 产生 to表示盘子最终要移到的柱子

初始状态:

将A柱子的N个圆盘移至C柱子上, 其中可以借助B柱子

汉诺塔移动初始状态

汉诺塔移动初始状态
移动n-1个盘子

汉诺塔的3个中间状态:

以下内容需要理解函数调用, 栈的知识

栈的知识: 先进后出, 后进先出

1): 汉诺塔移动n-1个盘子从A借助C移到B

hanoi-1

汉诺塔移动n-1个盘子从A借助C到B

移动代码: hanoi(n-1, from, to, buffer);

为何可以移动n-1个盘子, 这是初学者最难理解的部分. 要想理解, 必须理解栈的知识, 递归是一种反向思维.

2): 汉诺塔移动盘子n从A到C

汉诺塔移动盘子n从A到C

汉诺塔移动盘子n从A到C

移动代码: printf(“%d A->C\n”, n);

3): 汉诺塔移动n-1个盘子从B借助A移到B

汉诺塔移动n-1个盘子从B借助A移至C

汉诺塔移动n-1个盘子从B借助A移至C

移动代码: hanoi(n-1, buffer, from, to);

这是移动n-1个盘子的情况, 这和初始状态时一样的, 区别在于位于不同的柱子.

移动n-2个盘子并重复1-3步骤

接下来是移动n-2个盘子的情况. 因为 盘子n和n-1已经不要移动了(从递归的思想来看)

直到剩下一个盘子

这是就需要移动最后一个盘子到C, 实际的运算过程中程序会不断压栈(从n, n-1, 直到1), 然后执行此步操作, 注意之后的每一步都是每次移动一个盘子(之前只是压栈操作, 不要移动操作), 然后释放内存, 执行盘子2的操作, 直到最后移动盘子n-1, n的操作
继续阅读

栈的算法演示(C语言)

栈的算法演示

/*
	Name:		栈的算法演示
	Author:		lnesuper
	Date:		2014-10-11 00:05:17 
	Version:	V0.1 
	Discretion:	使用单向链表演示栈的操作 
*/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdbool.h>

//链表数据类型 
typedef struct Node {			
	int data;
	struct Node * pNext;
} NODE, *PNODE;

//链表栈数据类型 
typedef struct Stack {		
	PNODE pTop;
	PNODE pBottom;
} STACK, *PSTACK; 

//函数原型 
void init(PSTACK pS);				//栈的初始化 
void push(PSTACK pS, int val);		//压栈 
void traverse(PSTACK pS);			//遍历 
bool pop(PSTACK pS, int * pVal);	//出栈	
bool empty(PSTACK pS);				//判断栈是否为空	
void clear(PSTACK pS);				//清空栈 

int main(void)
{
	STACK S;
	init(&S);
	push(&S, 1);
	push(&S, 2);
	push(&S, 3);
	push(&S, 4);
	push(&S, 5);
	push(&S, 6);
	traverse(&S);

	int val;
	if (pop(&S, &val))
	{
		printf("出栈成功, 出栈的元素是%d\n", val); 
	}
	else
	{
		printf("出栈失败\n");
	}

	traverse(&S);
	clear(&S);
	traverse(&S);
	
	return 0;
}

void init(PSTACK pS)
{
	PNODE pHead = (PNODE)malloc(sizeof(NODE));
	if (NULL == pHead)
	{
		printf("分配内存失败. \n");
		exit(-1); 
	}
	else
	{
		pS->pTop = pHead;
		pS->pBottom = pHead;
		pHead->pNext = NULL; 
	}
	
	return;
}

void push(PSTACK pS, int val)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if(NULL == pNew)
	{
		printf("压栈失败. \n");
		exit(-1);
	}
	else
	{
		pNew->data = val;
		pNew->pNext = pS->pTop;
		pS->pTop = pNew;
	}
	
	return; 
}

void traverse(PSTACK pS)
{
	PNODE p = pS->pTop, q = NULL;
	
	if (empty(pS))
		printf("空栈, 无法遍历\n");
	else
	{
		while(pS->pBottom != q)
		{
			printf("%d ", p->data);
			q = p->pNext;
			p = q;
		}
		printf("\n");
	}

	return;
}

bool pop(PSTACK pS, int * pVal)
{
	bool ret = false;
	if(empty(pS))
	{
		ret = false;
	}
	else
	{
		PNODE r = pS->pTop;
		*pVal = r->data;
		pS->pTop = r->pNext;
		free(r);
		r = NULL; 
		
		ret = true;	
	}
	
	return ret;
}

bool empty(PSTACK pS)
{
	if (pS->pBottom == pS->pTop)
		return true;
	else
		return false;	
}

void clear(PSTACK pS)
{
	if (!empty(pS))
	{
		PNODE p = pS->pTop;
		PNODE q = NULL;
		while (pS->pBottom != p)
		{
			q = p->pNext;
			free(p);
			p = q;
		}
		pS->pTop = pS->pBottom; 
	}
	pS->pTop = pS->pBottom;
	
	return;
}

/*	
	Result(Dev-C++ 5.7.1):
	=========================
	6 5 4 3 2 1
	出栈成功, 出栈的元素是6
	5 4 3 2 1
	空栈, 无法遍历
	=========================
*/

源代码:

http://pan.baidu.com/s/1bn91dk7

测试用例设计

测试用例设计

测试用例就是一个文档,描述输入、操作和预期结果,其目的是为了验证待测特性是否符合设计需求。

测试用例基本要素

测试用例编号

命名规则

项目名称+测试阶段类型(系统测试阶段)+编号
比如

系统测试用例的编号这样定义规则: PROJECT1-ST-001

测试用例编号的作用

便于查找测试用例,便于测试用例的跟踪。

测试标题

对测试用例的描述,测试用例标题应该清楚表达测试用例的用途。
比如

测试用户登录时输入错误密码时,软件的响应情况。

重要级别

定义测试用例执行的优先级别,可以笼统的分为四个不同的等级

测试输入

提供测试执行中的各种输入条件。

根据需求中的输入条件,确定测试用例的输入。测试用例的输入对软件需求当中的输入有很大的依赖性,如果软件需求中没有很好的定义需求的输入,那么测试用例设计中会遇到很大的障碍。

继续阅读

ASCII码对照表

ASCII控制字符

二进制 十进制 十六进制 缩写 可以显示的表示法 名称/意义
0000 0000 0 00 NUL 空字符(Null)
0000 0001 1 01 SOH 标题开始
0000 0010 2 02 STX 本文开始
0000 0011 3 03 ETX 本文结束
0000 0100 4 04 EOT 传输结束
0000 0101 5 05 ENQ 请求
0000 0110 6 06 ACK 确认回应
0000 0111 7 07 BEL 响铃
0000 1000 8 08 BS 退格
0000 1001 9 09 HT 水平定位符号
0000 1010 10 0A LF 换行键
0000 1011 11 0B VT 垂直定位符号
0000 1100 12 0C FF 换页键
0000 1101 13 0D CR 归位键
0000 1110 14 0E SO 取消变换(Shift out)
0000 1111 15 0F SI 启用变换(Shift in)
0001 0000 16 10 DLE 跳出数据通讯
0001 0001 17 11 DC1 设备控制一(XON 启用软件速度控制)
0001 0010 18 12 DC2 设备控制二
0001 0011 19 13 DC3 设备控制三(XOFF 停用软件速度控制)
0001 0100 20 14 DC4 设备控制四
0001 0101 21 15 NAK 确认失败回应
0001 0110 22 16 SYN 同步用暂停
0001 0111 23 17 ETB 区块传输结束
0001 1000 24 18 CAN 取消
0001 1001 25 19 EM 连接介质中断
0001 1010 26 1A SUB 替换
0001 1011 27 1B ESC 跳出
0001 1100 28 1C FS 文件分割符
0001 1101 29 1D GS 组群分隔符
0001 1110 30 1E RS 记录分隔符
0001 1111 31 1F US 单元分隔符
0111 1111 127 7F DEL 删除

继续阅读

测试用例概述

测试用例:

测试用例(Test Case)是为了某个特殊目标而制定的一组测试输入、执行步骤以及预期结果,以便测试程序某个路径或着核实某个功能是否满足特定需求

测试用例的本质:

构成设计和测试过程的基础
测试用例是软件测试的核心
测试用例是测试工作的指导,
软件测试的必须遵守的准则
更是软件测试质量稳定的根本保障。

设计测试用例的作用:

有了测试用例,无论是谁来测试,参照测试用例实施,都能保障测试的质量。可以把人为因素的影响减少到最小。即便最初的测试用例考虑不周全,随着测试的进行和软件版本更新,也将日趋完善。

影响软件测试的因素

软件本身的复杂程度
开发人员(包括分析、设计、编程和测试的人员)的素质
人员变动
测试方法
测试技术
测试的“深度”与测试用例的数量成比例,测试工作量与测试用例的数量也成比例。根据全面细化的测试用例,可以更准确地估算连续测试阶段各个周期的时间安排。
判断测试是否完全的标准:
是基于需求的覆盖,而这又是以确定、实施或执行的测试用例的数量为依据的。
类似下面这样的说明:“95 % 的关键测试用例已得以执行和验证”

编写测试用例核心内容:
验证程序做了它应该做的事情
验证程序没有做它不该做的事情

编写测试用例的最佳方案:

为每个测试需求至少编制两个测试用例

  • 一个测试用例用于证明该需求已经满足,通常称作正面测试用例
  • 另一个测试用例反映某个无法接受、反常或意外的条件或数据作为输入,用于论证条件不满足的情况下功能需求的实现,这个测试用例称作负面测试用例。

继续阅读

软件开发概念

软件开发概述:
根据用户要求建造出软件系统或者系统中软件部分的一个产品开发的过程。

软件开发步骤:
需求分析
软件架构
软件设计
软件编程
软件测试
软件部署
软件维护

需求分析的定义:
在系统工程及软件工程中,需求分析指的是在创建一个新的或改变一个现存的系统或产品时,确定新系统的目的、范围、定义和功能时所要做的所有工作。

需求分析是关键过程:
在这个过程中,系统分析员和软件工程师确定顾客的需求。只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。

需求分析的主要困难:
随着工程师对需求分析的越来越重视,今天我们对需求分析的主要困难也理解得比较清楚:

需求分析需要由有充分的经验、技术知识和语言技巧的专家来完成;
顾客一开始所提出的需要,往往不完全、太乐观以及过分受老的系统或过程的影响;
使用复杂的工具和不同的技术来进行需求分析往往会打消获得一个完整的和细致的结果的希望。

怎样看待顾客需求:

顾客不明白他自己需要什么
顾客不愿将他们的需要固定在一系列写在纸上的条例中
在价格和时间确定后,顾客坚持要求新的需要
分析者与顾客的通讯太缓慢
顾客不参加回顾或无法参加回顾
顾客缺乏技术上的知识
顾客缺乏对软件开发的知识

需求解决方法:
制作原型
统一建模语言(UML)
用例(Use case)
敏捷软件开发

软件开发模式:
敏捷开发 | 无尘室 | 迭代式开发 | RAD | 统一过程 | 螺旋模型 | 瀑布模型 | 极限编程 | Scrum

软件开发辅助领域:
配置管理 | 文档编写 | 质量管理 | 项目管理 | 使用者经验设计

C语言运算符优先级详细列表

C语言运算符优先级详细列表

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

()

圆括号

(表达式)/函数名(形参表)

.

成员选择(对象)

对象.成员名

->

成员选择(指针)

对象指针->成员名

2

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式

++

自增运算符

++变量名/变量名++

单目运算符

自减运算符

–变量名/变量名–

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

表达式+表达式

左到右

双目运算符

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1? 表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

/=

除后赋值

变量/=表达式

*=

乘后赋值

变量*=表达式

%=

取模后赋值

变量%=表达式

+=

加后赋值

变量+=表达式

-=

减后赋值

变量-=表达式

<<=

左移后赋值

变量<<=表达式

>>=

右移后赋值

变量>>=表达式

&=

按位与后赋值

变量&=表达式

^=

按位异或后赋值

变量^=表达式

|=

按位或后赋值

变量|=表达式

15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

C++编程语言中的所有运算符的优先级和结合性列表

C++运算符优先级和结核性列表

优先级 运算符 叙述 示例 重载性 结合性
1 :: 作用域解析(C++专有) Class::age = 2; 由左至右
2 ++ 后缀递增 i++
后缀递减 i–
{} 组合 {i++;a*=i;}
() 函数调用或变量初始化 c_tor(int x, int y) : _x(x), _y(y * 10) {}
[] 数组访问 array[4] = 2;
. 以对象方式访问成员 obj.age = 34;
-> 以指针方式访问成员 ptr->age = 34;
dynamic_cast 运行时检查类型转换(C++专有) Y& y = dynamic_cast<Y&>(x);
static_cast 未经检查的类型转换(C++专有) Y& y = static_cast<Y&>(x);
reinterpret_cast 重定义类型转换(C++专有) int const* p = reinterpret_cast<int const*>(0x1234);
const_cast 更改非常量属性(C++专有) int* q = const_cast<int*>(p);
typeid 获取类型信息(C++专有) std::type_info const& t = typeid(x);
3 ++ 前缀递增 ++i 由右至左
前缀递减 –i
+ 一元正号 int i = +1;
一元负号 int i = -1;
!
not
逻辑非
!的备用拼写
if (!done) …
~
compl
按位取反
~的备用拼写
flag1 = ~flag2;
(type) 强制类型转换 int i = (int)floatNum;
* 取指针指向的值 int data = *intPtr;
& 取变量的地址 int *intPtr = &data;
sizeof 某某的大小 size_t s = sizeof(int);
new 动态内存分配(C++专有) long* pVar = new long;
new[] 动态数组内存分配(C++专有) long* array = new long[20];
delete 动态内存释放(C++专有) delete pVar;
delete[] 动态数组内存释放(C++专有) delete [] array;
4 .* 成员对象选择(C++专有) obj.*var = 24; 由左至右
->* 成员指针选择(C++专有) ptr->*var = 24;
5 * 乘法 int i = 2 * 4;
/ 除法 float f = 10.0 / 3.0;
% 模数(取余) int rem = 4 % 3;
6 + 加法 int i = 2 + 3;
减法 int i = 5 – 1;
7 << 比特左移 int flags = 33 << 1;
>> 比特右移 int flags = 33 >> 1;
8 < 小于关系 if (i < 42) …
<= 小于等于关系 if (i <= 42) …
> 大于关系 if (i > 42) …
>= 大于等于关系 if (i >= 42) …
9 ==
eq
等于关系
==的备用拼写
if (i == 42) …
!=
not_eq
不等于关系
!=的备用拼写
if (i != 42) …
10 &
bitand
比特 AND
&的备用拼写
flag1 = flag2 & 42;
11 ^
xor
比特 XOR(独占or)
^的备用拼写
flag1 = flag2 ^ 42;
12 |
bitor
比特 OR(包含or)
|的备用拼写
flag1 = flag2 | 42;
13 &&
and
逻辑 AND
&&的备用拼写
if (conditionA && conditionB) …
14 ||
or
逻辑 OR
||的备用拼写
if (conditionA || conditionB) …
15 c?t:f 三元条件运算 int i = a > b ? a : b; 由右至左
16 = 直接赋值 int a = b;
+= 以和赋值 a += 3;
-= 以差赋值 b -= 4;
*= 以乘赋值 a *= 5;
/= 以除赋值 a /= 2;
%= 以取余数赋值 a %= 3;
<<= 以比特左移赋值 flags <<= 2;
>>= 以比特右移赋值 flags >>= 2;
&=
and_eq
以比特AND赋值
&=的备用拼写
flags &= new_flags;
^=
xor_eq
以比特XOR赋值
^=的备用拼写
flags ^= new_flags;
|=
or_eq
以比特OR赋值
|=的备用拼写
flags |= new_flags;
17 throw 抛出异常 throw EClass(“Message”);
18 , 逗号运算符 for (i = 0, j = 0; i < 10; i++, j++) … 由左至右

软件测试理论

什么是软件测试:

  软件测试(英语software testing),描述一种用来促进鉴定软件正确性完整性安全性质量的过程。
软件测试理论

软件质量:

软件质量,是指软件系统或系统中的软件部分的质量,即满足用户需求,包括功能需求性能需求的程度。

软件质量包括:

  • 正确性
  • 高效性
  • 可靠性
  • 安全性
  • 可升级性
  • 可维护性
  • 其他质量特性

软件测试的经典定义:

在规定的条件下,对程序进行操作,以发现程序错误,衡量软件质量,并对其是否满足设计要求进行评估的过程。

软件测试本质:

实际输出与预期结果之间的审核或者比较过程。

软件测试内容:

    软件测试针对被测软件,制定测试计划配置测试环境按照各种测试方法编写测试用例,并严格按照测试设计步骤执行测试用例,对执行结果进行分析,并得出测试报告,这是软件质量保证的关键步骤。

软件测试公共特性:

    公认特性是共通的:可靠性稳定性、轻便性、易于维护、以及实用性。

怎样看待软件测试:

    软件测试一度被认为是编程能力偏低的员工的工作,直到今天,仍然有许多公司把优秀的人才放在编码上,也有更多公司让优秀的人才进行设计,可是很少公司让优秀的人才进行测试工作。实际的软件工程实践证明,让对软件思想有深刻理解的工程师进行软件测试的,可以大幅度的提高软件质量。

继续阅读