当前位置:网站首页>【个人学习总结】CRC校验原理及实现
【个人学习总结】CRC校验原理及实现
2022-08-09 09:21:00 【明如正午】
【个人学习总结】CRC校验原理及实现
下文是自己在学习CRC校验过程中收集的一些资料,供日后需要时查阅。
查阅资料中,发现很多博文对CRC实际代码的讲解比较少,即使讲了理论,但没有很好匹配的代码来理解。【我最终还是没能彻底理解,像CRC16、CRC32等的代码实现,不过“二、CRC实际应用”应该也够我工作中用了,尤其是 “3.查表法算法原理” 】
重点:
CRC原理理解:模2除法;异或XOR;CRC算法模型参数;
查表法的原理+代码实现:CRC8、CRC16、CRC32
一、CRC校验原理【理论篇】


参考文章:
1.硬核视频讲解【重点看,非常非常好!!!】
2.基础文章【略看】
3.深入文章!!!【代码、查表法有点看不懂,跨越有点大】
- 重点看 算法原理 与 查表法
理解重要截图:

下图需要结合上图中红框圈中部分进行理解:
4.必备知识【了解】
1)模2除法与普通除法不同:
https://blog.csdn.net/weixin_39450145/article/details/83987836
2)输出数据反转(REFOUT)的理解:


二、CRC实际应用【代码篇-理解常规用法】
参考文章:
CRC算法 个人学习笔记 直接法、查表法注意点【写的很好,很实用!】
1.简单实例
计算单字节0x81的CRC8的值(生成多项式:0x07,初始值00,输入输出不反转)
将经0x81与初始值0x00进行异或
CRC8 = 0x81 XOR 0x00 = 0x81;从判断数据的最高位,选择对应的计算方法
1:数据左移一位,然后与多项式0x07进行异或,CRC8 = (CRC8 << 1) ^ 0x07
0:数据左移一位,然后不动作,CRC8 =(CRC8 << 1)8位数据是否都移动完:
未移动完:返回第2步继续计算
移动完 :最后的结果则为最终的8位校验值对应的C代码
uint8_t Get_CRC8( uint8_t dat , uint8_t init_value)
{
uint8_t CRC8 = dat ^ init_value;
for(uint8_t i = 0 ; i < 8 ; i++)
{
if(CRC8 & 0x80)
CRC8 = (CRC8 << 1) ^ 0x07;
else
CRC8 <<= 1;
}
return CRC8;
}
- 以上是8位检验值的直接计算方法,16位/32位也是同样的。
2.CRC16、CRC32等多字节的校验值的计算有几点需要清楚(只针对一次一个字节的算法)
初始值不为0的情况下,该如何计算【重点!!!】:
输入数据需要反转:先将要计算的数据与初始值的最低字节进行异或,再与反转后的多项式进行计算。
输入数据不需要反转:先将要计算的数据左移到与初始值对齐的位置(如CRC16算法,则左移8位,低位填充0;如CRC32算法,则左移24位,低位填充0)与初始值进行异或,再与正常的多项式进行计算。结果异或值不为0的情况:第一步算得到的CRC值再与结果异或值进行异或操作得到最终的校验值:
输出数据反转:如果输入数据是反转的模式,则结果也是反转的
输出数据不反转:如果输入数据是不反转的模式,则结果也是不反转的初始值的选择是可自己定义,很多不同的厂家使用的初始值是不一样,不一样的初始值得到的结果也是不一样的,要起到定制的效果,像上面提到的国际、行业使用的标准算法,初始值是固定的。
3.查表法 算法原理【实际写代码时需要!!!】
1)CRC8的查表法:
要计算的单字节数据与初始值进行异或得到单字节数据,以此结果为表的序号从表中取得的值即为该字节的校验值;如果是多字节,则以前一字节的检验值作为初始值进行同样的操作,算法如下:
//结果不异或其他值
uint8_t Get_CRC8_With_Table(uint8_t *datptr , uint8_t len , uint8_t init_value)
{
uint8_t CRC8 = init_value;
while(len--)
{
CRC8 = CRC8_TABLE[(*datptr++) ^ CRC8];
}
return CRC8;
}
2)CRC16的查表法:
要计算的单字节数据与初始值的高字节异或,然后以此单字节数据作为表的序号从表中取得的值再与初始值的低字节左移8位后的值进行异或得到最终的检验值:
//输入、输出不反转,结果不异或其他值
uint16_t Get_CRC16_With_Table(uint8_t *datptr , uint8_t len , uint16_t init_value)
{
uint16_t CRC16 = init_value;
while(len--)
{
CRC16 = CRC16_TABLE[(*datptr++) ^ ((CRC16 >> 8) & 0xFF)] ^ ((CRC16 << 8) & 0xFF00);
}
return CRC16;
}
3)CRC32的查表法:
要计算的单字节数据与初始值的最高字节异或,然后以此单字节数据作为表的序号从表中取得的值再与初始值的低字节左移8位后的值进行异或得到最终的检验值:
//输入、输出不反转的查表算法,结果不异或任何值
uint32_t Get_CRC32_With_Table(uint8_t *datptr , uint8_t len , uint32_t init_value)
{
uint32_t CRC32 = init_value;
while(len--)
{
CRC32 = CRC32_TABLE[(*datptr++) ^ ((CRC32 >> 24) & 0xFF)] ^ ((CRC32 << 8) & 0xFFFFFF00);
}
return CRC32;
}
//反转输入、输出的查表算法,结果异或0xFFFFFFFF
uint32_t Get_CRC32_With_Table_Inv(uint8_t *datptr , uint8_t len , uint32_t init_value)
{
uint32_t CRC32 = init_value;
while(len--)
{
CRC32 = CRC32_TABLE_INV[((*datptr++) ^ CRC32) & 0xFF] ^ ((CRC32 >> 8) & 0x00FFFFFF);
}
return CRC32 ^ 0xFFFFFFFF;
}
4)生成表 的C代码
//生成输入、输出不反转的表
void CRC32_Table_Init(void)
{
uint32_t i , j;
uint32_t CRC = 0;
for(i = 0 ; i < 256 ; i++)
{
CRC = (i << 24);
for(j = 0 ; j < 8 ; j++)
{
if(CRC & 0x80000000)
{
CRC = (CRC << 1) ^ 0x04C11DB7;
}
else
{
CRC <<= 1;
}
}
CRC32_TABLE[i] = CRC;
}
}
//生成输入、输出反转的表
void CRC32_Table_Init_Inv(void)
{
uint32_t i , j;
uint32_t CRC = 0;
for(i = 0 ; i < 256 ; i++)
{
CRC = i;
for(j = 0 ; j < 8 ; j++)
{
if(CRC & 0x00000001)
{
CRC = (CRC >> 1) ^ 0xEDB88320;
}
else
{
CRC >>= 1;
}
}
CRC32_TABLE_INV[i] = CRC;
}
}
5)使用查表法需要注意的问题:
关于表的生成,是以0~255这256个数分别计算得到的CRC检验值,需要注意的是,此表的生成需要配合所使用的CRC算法的配置,如输入数据是否要反转,输入数据反转和不反转对应的表是不一样的。还有很重要的一点,表的生成是以初始值为0时生成的检验值,否则会出错,以下我是生成的表数据:
C#生成表的代码:
using System;
using System.Text;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
CRC32_Table_Init();
StringBuilder st = new StringBuilder();
for (int i = 0; i < 256; i++)
{
st.Append(Convert.ToString(CRC32_TABLE[i], 16).PadLeft(8,'0').ToUpper() + "\r\n");
}
Console.WriteLine(st);
Console.ReadLine();
}
public static UInt32[] CRC32_TABLE = new UInt32[256];
public static void CRC32_Table_Init()
{
UInt32 i, j;
UInt32 CRC = 0;
for (i = 0; i < 256; i++)
{
CRC = (i << 24);
for (j = 0; j < 8; j++)
{
if ((CRC & 0x80000000)>0)
{
CRC = (CRC << 1) ^ 0x04C11DB7;
}
else
{
CRC <<= 1;
}
}
CRC32_TABLE[i] = CRC;
}
}
}
}
输入、输出数据不反转使用查表法时的表数据【上边用C#做了验证】:
//输入、输出数据不反转使用查表法时的表数据
uint32_t CRC32_TABLE[256] = {
0x00000000 , 0x04C11DB7 , 0x09823B6E , 0x0D4326D9 , 0x130476DC , 0x17C56B6B , 0x1A864DB2 , 0x1E475005 ,
0x2608EDB8 , 0x22C9F00F , 0x2F8AD6D6 , 0x2B4BCB61 , 0x350C9B64 , 0x31CD86D3 , 0x3C8EA00A , 0x384FBDBD ,
0x4C11DB70 , 0x48D0C6C7 , 0x4593E01E , 0x4152FDA9 , 0x5F15ADAC , 0x5BD4B01B , 0x569796C2 , 0x52568B75 ,
0x6A1936C8 , 0x6ED82B7F , 0x639B0DA6 , 0x675A1011 , 0x791D4014 , 0x7DDC5DA3 , 0x709F7B7A , 0x745E66CD ,
0x9823B6E0 , 0x9CE2AB57 , 0x91A18D8E , 0x95609039 , 0x8B27C03C , 0x8FE6DD8B , 0x82A5FB52 , 0x8664E6E5 ,
0xBE2B5B58 , 0xBAEA46EF , 0xB7A96036 , 0xB3687D81 , 0xAD2F2D84 , 0xA9EE3033 , 0xA4AD16EA , 0xA06C0B5D ,
0xD4326D90 , 0xD0F37027 , 0xDDB056FE , 0xD9714B49 , 0xC7361B4C , 0xC3F706FB , 0xCEB42022 , 0xCA753D95 ,
0xF23A8028 , 0xF6FB9D9F , 0xFBB8BB46 , 0xFF79A6F1 , 0xE13EF6F4 , 0xE5FFEB43 , 0xE8BCCD9A , 0xEC7DD02D ,
0x34867077 , 0x30476DC0 , 0x3D044B19 , 0x39C556AE , 0x278206AB , 0x23431B1C , 0x2E003DC5 , 0x2AC12072 ,
0x128E9DCF , 0x164F8078 , 0x1B0CA6A1 , 0x1FCDBB16 , 0x018AEB13 , 0x054BF6A4 , 0x0808D07D , 0x0CC9CDCA ,
0x7897AB07 , 0x7C56B6B0 , 0x71159069 , 0x75D48DDE , 0x6B93DDDB , 0x6F52C06C , 0x6211E6B5 , 0x66D0FB02 ,
0x5E9F46BF , 0x5A5E5B08 , 0x571D7DD1 , 0x53DC6066 , 0x4D9B3063 , 0x495A2DD4 , 0x44190B0D , 0x40D816BA ,
0xACA5C697 , 0xA864DB20 , 0xA527FDF9 , 0xA1E6E04E , 0xBFA1B04B , 0xBB60ADFC , 0xB6238B25 , 0xB2E29692 ,
0x8AAD2B2F , 0x8E6C3698 , 0x832F1041 , 0x87EE0DF6 , 0x99A95DF3 , 0x9D684044 , 0x902B669D , 0x94EA7B2A ,
0xE0B41DE7 , 0xE4750050 , 0xE9362689 , 0xEDF73B3E , 0xF3B06B3B , 0xF771768C , 0xFA325055 , 0xFEF34DE2 ,
0xC6BCF05F , 0xC27DEDE8 , 0xCF3ECB31 , 0xCBFFD686 , 0xD5B88683 , 0xD1799B34 , 0xDC3ABDED , 0xD8FBA05A ,
0x690CE0EE , 0x6DCDFD59 , 0x608EDB80 , 0x644FC637 , 0x7A089632 , 0x7EC98B85 , 0x738AAD5C , 0x774BB0EB ,
0x4F040D56 , 0x4BC510E1 , 0x46863638 , 0x42472B8F , 0x5C007B8A , 0x58C1663D , 0x558240E4 , 0x51435D53 ,
0x251D3B9E , 0x21DC2629 , 0x2C9F00F0 , 0x285E1D47 , 0x36194D42 , 0x32D850F5 , 0x3F9B762C , 0x3B5A6B9B ,
0x0315D626 , 0x07D4CB91 , 0x0A97ED48 , 0x0E56F0FF , 0x1011A0FA , 0x14D0BD4D , 0x19939B94 , 0x1D528623 ,
0xF12F560E , 0xF5EE4BB9 , 0xF8AD6D60 , 0xFC6C70D7 , 0xE22B20D2 , 0xE6EA3D65 , 0xEBA91BBC , 0xEF68060B ,
0xD727BBB6 , 0xD3E6A601 , 0xDEA580D8 , 0xDA649D6F , 0xC423CD6A , 0xC0E2D0DD , 0xCDA1F604 , 0xC960EBB3 ,
0xBD3E8D7E , 0xB9FF90C9 , 0xB4BCB610 , 0xB07DABA7 , 0xAE3AFBA2 , 0xAAFBE615 , 0xA7B8C0CC , 0xA379DD7B ,
0x9B3660C6 , 0x9FF77D71 , 0x92B45BA8 , 0x9675461F , 0x8832161A , 0x8CF30BAD , 0x81B02D74 , 0x857130C3 ,
0x5D8A9099 , 0x594B8D2E , 0x5408ABF7 , 0x50C9B640 , 0x4E8EE645 , 0x4A4FFBF2 , 0x470CDD2B , 0x43CDC09C ,
0x7B827D21 , 0x7F436096 , 0x7200464F , 0x76C15BF8 , 0x68860BFD , 0x6C47164A , 0x61043093 , 0x65C52D24 ,
0x119B4BE9 , 0x155A565E , 0x18197087 , 0x1CD86D30 , 0x029F3D35 , 0x065E2082 , 0x0B1D065B , 0x0FDC1BEC ,
0x3793A651 , 0x3352BBE6 , 0x3E119D3F , 0x3AD08088 , 0x2497D08D , 0x2056CD3A , 0x2D15EBE3 , 0x29D4F654 ,
0xC5A92679 , 0xC1683BCE , 0xCC2B1D17 , 0xC8EA00A0 , 0xD6AD50A5 , 0xD26C4D12 , 0xDF2F6BCB , 0xDBEE767C ,
0xE3A1CBC1 , 0xE760D676 , 0xEA23F0AF , 0xEEE2ED18 , 0xF0A5BD1D , 0xF464A0AA , 0xF9278673 , 0xFDE69BC4 ,
0x89B8FD09 , 0x8D79E0BE , 0x803AC667 , 0x84FBDBD0 , 0x9ABC8BD5 , 0x9E7D9662 , 0x933EB0BB , 0x97FFAD0C ,
0xAFB010B1 , 0xAB710D06 , 0xA6322BDF , 0xA2F33668 , 0xBCB4666D , 0xB8757BDA , 0xB5365D03 , 0xB1F740B4 ,
};
输入、输出数据反转使用查表法时的表数据:
//输入、输出数据反转使用查表法时的表数据
uint32_t CRC32_TABLE_INV[256] = {
0x00000000 , 0x77073096 , 0xEE0E612C , 0x990951BA , 0x076DC419 , 0x706AF48F , 0xE963A535 , 0x9E6495A3 ,
0x0EDB8832 , 0x79DCB8A4 , 0xE0D5E91E , 0x97D2D988 , 0x09B64C2B , 0x7EB17CBD , 0xE7B82D07 , 0x90BF1D91 ,
0x1DB71064 , 0x6AB020F2 , 0xF3B97148 , 0x84BE41DE , 0x1ADAD47D , 0x6DDDE4EB , 0xF4D4B551 , 0x83D385C7 ,
0x136C9856 , 0x646BA8C0 , 0xFD62F97A , 0x8A65C9EC , 0x14015C4F , 0x63066CD9 , 0xFA0F3D63 , 0x8D080DF5 ,
0x3B6E20C8 , 0x4C69105E , 0xD56041E4 , 0xA2677172 , 0x3C03E4D1 , 0x4B04D447 , 0xD20D85FD , 0xA50AB56B ,
0x35B5A8FA , 0x42B2986C , 0xDBBBC9D6 , 0xACBCF940 , 0x32D86CE3 , 0x45DF5C75 , 0xDCD60DCF , 0xABD13D59 ,
0x26D930AC , 0x51DE003A , 0xC8D75180 , 0xBFD06116 , 0x21B4F4B5 , 0x56B3C423 , 0xCFBA9599 , 0xB8BDA50F ,
0x2802B89E , 0x5F058808 , 0xC60CD9B2 , 0xB10BE924 , 0x2F6F7C87 , 0x58684C11 , 0xC1611DAB , 0xB6662D3D ,
0x76DC4190 , 0x01DB7106 , 0x98D220BC , 0xEFD5102A , 0x71B18589 , 0x06B6B51F , 0x9FBFE4A5 , 0xE8B8D433 ,
0x7807C9A2 , 0x0F00F934 , 0x9609A88E , 0xE10E9818 , 0x7F6A0DBB , 0x086D3D2D , 0x91646C97 , 0xE6635C01 ,
0x6B6B51F4 , 0x1C6C6162 , 0x856530D8 , 0xF262004E , 0x6C0695ED , 0x1B01A57B , 0x8208F4C1 , 0xF50FC457 ,
0x65B0D9C6 , 0x12B7E950 , 0x8BBEB8EA , 0xFCB9887C , 0x62DD1DDF , 0x15DA2D49 , 0x8CD37CF3 , 0xFBD44C65 ,
0x4DB26158 , 0x3AB551CE , 0xA3BC0074 , 0xD4BB30E2 , 0x4ADFA541 , 0x3DD895D7 , 0xA4D1C46D , 0xD3D6F4FB ,
0x4369E96A , 0x346ED9FC , 0xAD678846 , 0xDA60B8D0 , 0x44042D73 , 0x33031DE5 , 0xAA0A4C5F , 0xDD0D7CC9 ,
0x5005713C , 0x270241AA , 0xBE0B1010 , 0xC90C2086 , 0x5768B525 , 0x206F85B3 , 0xB966D409 , 0xCE61E49F ,
0x5EDEF90E , 0x29D9C998 , 0xB0D09822 , 0xC7D7A8B4 , 0x59B33D17 , 0x2EB40D81 , 0xB7BD5C3B , 0xC0BA6CAD ,
0xEDB88320 , 0x9ABFB3B6 , 0x03B6E20C , 0x74B1D29A , 0xEAD54739 , 0x9DD277AF , 0x04DB2615 , 0x73DC1683 ,
0xE3630B12 , 0x94643B84 , 0x0D6D6A3E , 0x7A6A5AA8 , 0xE40ECF0B , 0x9309FF9D , 0x0A00AE27 , 0x7D079EB1 ,
0xF00F9344 , 0x8708A3D2 , 0x1E01F268 , 0x6906C2FE , 0xF762575D , 0x806567CB , 0x196C3671 , 0x6E6B06E7 ,
0xFED41B76 , 0x89D32BE0 , 0x10DA7A5A , 0x67DD4ACC , 0xF9B9DF6F , 0x8EBEEFF9 , 0x17B7BE43 , 0x60B08ED5 ,
0xD6D6A3E8 , 0xA1D1937E , 0x38D8C2C4 , 0x4FDFF252 , 0xD1BB67F1 , 0xA6BC5767 , 0x3FB506DD , 0x48B2364B ,
0xD80D2BDA , 0xAF0A1B4C , 0x36034AF6 , 0x41047A60 , 0xDF60EFC3 , 0xA867DF55 , 0x316E8EEF , 0x4669BE79 ,
0xCB61B38C , 0xBC66831A , 0x256FD2A0 , 0x5268E236 , 0xCC0C7795 , 0xBB0B4703 , 0x220216B9 , 0x5505262F ,
0xC5BA3BBE , 0xB2BD0B28 , 0x2BB45A92 , 0x5CB36A04 , 0xC2D7FFA7 , 0xB5D0CF31 , 0x2CD99E8B , 0x5BDEAE1D ,
0x9B64C2B0 , 0xEC63F226 , 0x756AA39C , 0x026D930A , 0x9C0906A9 , 0xEB0E363F , 0x72076785 , 0x05005713 ,
0x95BF4A82 , 0xE2B87A14 , 0x7BB12BAE , 0x0CB61B38 , 0x92D28E9B , 0xE5D5BE0D , 0x7CDCEFB7 , 0x0BDBDF21 ,
0x86D3D2D4 , 0xF1D4E242 , 0x68DDB3F8 , 0x1FDA836E , 0x81BE16CD , 0xF6B9265B , 0x6FB077E1 , 0x18B74777 ,
0x88085AE6 , 0xFF0F6A70 , 0x66063BCA , 0x11010B5C , 0x8F659EFF , 0xF862AE69 , 0x616BFFD3 , 0x166CCF45 ,
0xA00AE278 , 0xD70DD2EE , 0x4E048354 , 0x3903B3C2 , 0xA7672661 , 0xD06016F7 , 0x4969474D , 0x3E6E77DB ,
0xAED16A4A , 0xD9D65ADC , 0x40DF0B66 , 0x37D83BF0 , 0xA9BCAE53 , 0xDEBB9EC5 , 0x47B2CF7F , 0x30B5FFE9 ,
0xBDBDF21C , 0xCABAC28A , 0x53B39330 , 0x24B4A3A6 , 0xBAD03605 , 0xCDD70693 , 0x54DE5729 , 0x23D967BF ,
0xB3667A2E , 0xC4614AB8 , 0x5D681B02 , 0x2A6F2B94 , 0xB40BBE37 , 0xC30C8EA1 , 0x5A05DF1B , 0x2D02EF8D ,
};
三、CRC计算工具
1.CRC(循环冗余校验)在线计算:http://www.ip33.com/crc.html
2.离线计算工具:CRC_Calc v0.1.exe或者GCRC.exe
链接:https://pan.baidu.com/s/1zATvZX4So8-C6bgWkW8z2Q
提取码:9u5n


四、用C#实现的几种常用数据校验方法整理(CRC校验;LRC校验;BCC校验;累加和校验)
https://www.cnblogs.com/ayxj/p/11481969.html
第一个算法的代码示例【其余算法的应用模仿即可】:
using System;
using System.Text;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
byte[] bt1 = new byte[] {
0x11, 0x22 };
byte[] result = Crc1(bt1, 0, 2);
Console.WriteLine(Convert.ToString(result[0], 16).PadLeft(2,'0').ToUpper());
Console.ReadLine();
}
/// **********************************************************************
/// Name: CRC-4/ITU x4+x+1
/// Poly: 0x03
/// Init: 0x00
/// Refin: true
/// Refout: true
/// Xorout: 0x00
///*************************************************************************
public static byte[] Crc1(byte[] buffer, int start = 0, int len = 0)
{
if (buffer == null || buffer.Length == 0) return null;
if (start < 0) return null;
if (len == 0) len = buffer.Length - start;
int length = start + len;
if (length > buffer.Length) return null;
byte crc = 0;// Initial value
for (int i = start; i < length; i++)
{
crc ^= buffer[i];
for (int j = 0; j < 8; j++)
{
if ((crc & 1) > 0)
crc = (byte)((crc >> 1) ^ 0x0C);//0x0C = (reverse 0x03)>>(8-4)
else
crc = (byte)(crc >> 1);
}
}
return new byte[] {
crc };
}
}
}


边栏推荐
猜你喜欢

年薪40W测试工程师成长之路,你在哪个阶段?

Django实现对数据库数据增删改查(一)
黑盒测试常见错误类型说明及解决方法有哪些?

MySQL lock

使用图新地球无法加载谷歌地球的完美解决方法(附软件下载)

MySQL锁
通用的测试用例编写大全(登录测试/web测试等)

Global 19 Google Satellite Map Free View Download

Read file by byte and character_load configuration file

Do you know the basic process and use case design method of interface testing?
随机推荐
HD Satellite Map Browser
本体开发日记04-努力理解protege的某个方面
可以写进简历的软件测试项目实战经验(包含电商、银行、app等)
白盒测试的概念、目的是什么?及主要方法有哪些?
软件测试流程包括哪些内容?测试方法有哪些?
测试计划包括哪些内容?目的和意义是什么?
接口性能测试方案设计方法有哪些?要怎么去写?
Jfinal loading configuration file principle
初窥门径代码起手,Go lang1.18入门精炼教程,由白丁入鸿儒,首次运行golang程序EP01
WAVE SUMMIT 2022深度学习开发者峰会
学习栈的心得和总结(数组实现)
MySQL查漏补缺(五)不熟悉的知识点
Rights management model, ACL, RBAC and ABAC (steps)
Venture DAO Industry Research Report: Macro and Classic Case Analysis, Model Summary, Future Suggestions
软件测试的流程规范有哪些?具体要怎么做?
软件测试个人求职简历该怎么写,模板在这里
web测试之功能测试常用的方法有哪几种?有什么要点要注意?
Web请求原理
Consolidation of Questionnaire Questions and Answers
Lecture 4 SVN