单一责任原则
在遵循开闭原则的过程中,我期望能够写出一个类或者方法,在以后我回过头读它的时候,会很舒服地看到它能完成它的工作并且我也不需要再修改它。你永远也达不到真正的开闭天堂,但是通过严格地遵循与之相关的单一责任原则:一个类应该有并且只有一个更改的理由,你可以非常靠近地接近它。
在遵循开闭原则的过程中,我期望能够写出一个类或者方法,在以后我回过头读它的时候,会很舒服地看到它能完成它的工作并且我也不需要再修改它。你永远也达不到真正的开闭天堂,但是通过严格地遵循与之相关的单一责任原则:一个类应该有并且只有一个更改的理由,你可以非常靠近地接近它。
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
hash table(哈希表) 哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。然而在当前可利用内存越来越多的情况下,用空间换时间的做法是值得的。另外,编码比较容易也是它的特点之一。
近来遇到了一些常见的概念,尤其是网络编程方面的概念,如:阻塞、非阻塞、异步I/O等等,对于这些概念自己也没有太清晰的认识,只是很模糊的概念,说了解吧也了解,但是要让自己准确的描述概念方面的具体细节,却说的不那么准确,这也是自己在这几个方面也没有细细考究过的原因吧。经过看了些这几个概念的资料,发现同步、异步、阻塞、非阻塞的概念其实也并不难以理解,在此写下此文,欢迎拍砖,希望多多交流。
关于操作系统的定义,我没有找到一个权威的解释,基本上可以说,它是一个程序,一个介于计算机硬件和计算机用户/开发者之间的程序,用户通过它来操作计算机,开发者用它提供的接口来编写程序。操作系统大概可算是最重要(也可算是最复杂)的程序,基本上,它决定了我们能用电脑干什么和怎样用电脑,软件当然是千变万化,不断发展,但无论是在那一种操作系统下跑的软件,必然受限于操作系统所提供的功能,换句话说,它只能在操作系统划下的圈子里翻筋斗。
作者:Joel Spolsky
译者:阮一峰
原文网址:http://www.joelonsoftware.com/items/2007/06/12.html
苹果公司和微软公司,对于如何在电脑屏幕上显示字体,总是有不同看法。目前,这两家公司都使用次像素渲染(subpixel rendering)技术,使得字体在低分辨率的屏幕上,也能显得很清晰。这两家公司的根本不同之处在于指导思想。
这个题其实以前我去面华为的时候被考过…前几天在网上无意间看到,勾起了回忆…
用C++描述,题目大致是这样的:
已知下面Stack类及其3个方法Push、Pop和 Count,请用2个Stack实现Queue类的入队(Enqueue)出队(Dequeue)方法。
之前一直在搞数据相关滴事情…然后碰到这么个问题,要向Access数据库的数据字段写入空值…
要是字符型字段还好说一点咯,写个空字符串就好了…
这个数字型,想想的话怎么着也要给个数字啊…
void CDataControl::GetFieldNameCn(const CString& sTableName,CADORecordset* pAdoAccess,const CString& sNameEn, CString& sNameCn)
{
SAFEARRAY FAR* psa = NULL;
SAFEARRAYBOUND rgsabound;
_variant_t var;
_variant_t Array;
rgsabound.lLbound = 0;
rgsabound.cElements = 4;
psa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
var.vt = VT_EMPTY;
long ix;
ix = 0;
SafeArrayPutElement(psa, &ix, &var);
ix= 1;
SafeArrayPutElement(psa, &ix, &var);
ix = 2;
var.vt = VT_BSTR;
var.bstrVal =sTableName.AllocSysString(); //表名 sTableName
SafeArrayPutElement(psa, &ix, &var);
var.vt = VT_BSTR;
ix = 3;
var.bstrVal =sNameEn.AllocSysString();//字段名
SafeArrayPutElement(psa, &ix, &var);
Array.vt = VT_ARRAY|VT_VARIANT;
Array.parray = psa;
pAdoAccess->m_pRecordset = pAdoAccess->GetActiveConnection()->OpenSchema(adSchemaColumns,&Array);
Field *fd = pAdoAccess->m_pRecordset->Fields->GetItem("DESCRIPTION");
if (fd->GetValue().vt != VT_NULL)
{
_bstr_t column_discription = fd->Value;
CString sNote;
sNote.Format(_T("%s"), (LPCTSTR)column_discription);
sNameCn = (LPCTSTR)column_discription;
}
else
{
sNameCn = sNameEn;
}
}
BOOL CDataControl::GetFileNULL(const CString& sTableName,const CString& sFileNameEN,CString& sFileNameCN,CADORecordset* pAdoAccess,BOOL& ISNullSet, int& OrdinalPostion)
{
SAFEARRAY FAR* psa = NULL;
SAFEARRAYBOUND rgsabound;
_variant_t var;
_variant_t Array;
rgsabound.lLbound = 0;
rgsabound.cElements = 4;
psa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
var.vt = VT_EMPTY;
long ix;
ix = 0;
SafeArrayPutElement(psa, &ix, &var);
ix= 1;
SafeArrayPutElement(psa, &ix, &var);
ix = 2;
var.vt = VT_BSTR;
var.bstrVal =sTableName.AllocSysString(); //表名 sTableName
SafeArrayPutElement(psa, &ix, &var);
var.vt = VT_BSTR;
ix = 3;
var.bstrVal =sFileNameEN.AllocSysString();//字段名
SafeArrayPutElement(psa, &ix, &var);
Array.vt = VT_ARRAY|VT_VARIANT;
Array.parray = psa;
pAdoAccess->m_pRecordset = pAdoAccess->GetActiveConnection()->OpenSchema(adSchemaColumns,&Array);
//IS_NULL = 1 表示字段可以为空 0 表示必填
ISNullSet = (pAdoAccess->m_pRecordset->Fields->GetItem("IS_NULLABLE")->Value.boolVal == -1)?TRUE:FALSE;//是否允许为空
_bstr_t column_name = pAdoAccess->m_pRecordset->Fields->GetItem("COLUMN_NAME")->Value;//字段名
OrdinalPostion = pAdoAccess->m_pRecordset->Fields->GetItem("ORDINAL_POSITION")->Value;//字段序号
Field *fd = pAdoAccess->m_pRecordset->Fields->GetItem("DESCRIPTION");
if (fd->GetValue().vt != VT_NULL)
{
_bstr_t column_discription = fd->Value;
CString sNote;
sNote.Format(_T("%s"), (LPCTSTR)column_discription);
sFileNameCN = (LPCTSTR)column_discription;
}
else
{
sFileNameCN = sFileNameEN;
}
//int NUMERIC_PRECISION = m_pRecordset->Fields->GetItem("NUMERIC_PRECISION")->Value;
//int NUMERIC_SCALE = m_pRecordset->Fields->GetItem("NUMERIC_SCALE")->Value;
return TRUE;
}
BOOL CDataControl::GetFilePkName(const CString& sTableName,std::vector<CString>& sPkName,CADORecordset* pAdoAccess)
{
SAFEARRAY FAR* psa = NULL;
SAFEARRAYBOUND rgsabound;
_variant_t var;
_variant_t Array;
rgsabound.lLbound = 0;
rgsabound.cElements = 3;
psa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
var.vt = VT_EMPTY;
long ix;
ix = 0;
SafeArrayPutElement(psa, &ix, &var);
ix= 1;
SafeArrayPutElement(psa, &ix, &var);
ix = 2;
var.vt = VT_BSTR;
var.bstrVal =sTableName.AllocSysString(); //表名 sTableName
SafeArrayPutElement(psa, &ix, &var);
Array.vt = VT_ARRAY|VT_VARIANT;
Array.parray = psa;
pAdoAccess->m_pRecordset = pAdoAccess->GetActiveConnection()-> OpenSchema(adSchemaPrimaryKeys,&Array); //adSchemaColumns
while(!pAdoAccess->IsEOF())
{
_bstr_t column_name = pAdoAccess->m_pRecordset->Fields->GetItem("COLUMN_NAME")->Value;
_bstr_t column_PK= pAdoAccess->m_pRecordset-> Fields-> GetItem( "PK_NAME")-> Value;
sPkName.push_back((LPCTSTR)column_name);
pAdoAccess->MoveNext();
}
return TRUE;
}
用了一个map来记录所有的层级关系,然后从root找起,依次找出所有的节点…
// 用的是tinyXML读取
BOOL CXmlRead::ReadGroupInfo( std::map<CString, std::vector<std::pair<CString, BOOL>>> &mapGroup )
{
// 载入文件
TiXmlDocument *doc = new TiXmlDocument(PATH);
if (!doc->LoadFile())
{
delete doc;
return FALSE;
}
// 获取根节点
TiXmlElement *pRoot = doc->FirstChildElement(_T("TableGroup"));
ASSERT(pRoot);
if (pRoot == NULL)
{
delete doc;
return FALSE;
}
mapGroup.clear();
std::vector<std::pair<CString, BOOL>> vecTable;
TiXmlElement *pNode = dynamic_cast<TiXmlElement *>(pRoot->FirstChildElement());
while (pNode != NULL)
{
// 节点属性
CString strSubName = pNode->Attribute(_T("Name"));
vecTable.push_back(std::make_pair(strSubName, TRUE));
ASSERT(_T("Group") == (CString)(pNode->Value()));
if(!ReadNode(pNode, mapGroup))
{
return FALSE;
}
// 下一关键字节点
pNode = dynamic_cast<TiXmlElement *>(pNode->NextSiblingElement());
}
mapGroup[_T("ROOT")] = vecTable;
delete doc;
return TRUE;
}
BOOL CXmlRead::ReadNode(TiXmlElement *pNode, std::map<CString, std::vector<std::pair<CString, BOOL>>> &mapGroup)
{
// 每次添加的新节点应该是之前没有出现过的,否则会死循环
CString strNodeName = pNode->Attribute(_T("Name"));
if(mapGroup.end() != mapGroup.find(strNodeName)) return FALSE;
std::vector<std::pair<CString, BOOL>> vecTable;
TiXmlElement *pSubNode = dynamic_cast<TiXmlElement *>(pNode->FirstChildElement());
while (pSubNode != NULL)
{
// 节点名
CString strSub = pSubNode->Value();
// 节点属性
CString strSubName = pSubNode->Attribute(_T("Name"));
if(_T("Group") == strSub)
{
vecTable.push_back(std::make_pair(strSubName, TRUE));
if(!ReadNode(pSubNode, mapGroup))
{
return FALSE;
}
}
else if(_T("Table") == strSub)
{
vecTable.push_back(std::make_pair(strSubName, FALSE));
}
// 下一关键字节点
pSubNode = dynamic_cast<TiXmlElement *>(pSubNode->NextSiblingElement());
}
mapGroup[strNodeName] = vecTable;
return TRUE;
}
其实vector里面的bool是可以不要的,最初加这个只是为了区分树节点和叶节点…