关于作者

用户名:dragon77
笔名:狂龙天下
地区: 广东-广州
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



友情

有限元

小说

程序设计

百度搜索

baidu

互联网 狂龙天下

军事频道

记忆力训练

访问统计:
文章个数:119
评论个数:288
留言条数:14




Powered by BlogDriver 2.1

狂龙天下

 

无网格法研究。 本人现已毕业,硕士毕业论文《无单元伽辽金法程序设计及其应用》,论文主要研究内容:1.EFGM程序设计(VC++);2.基于VC的EFGM分析平台开发,含前、后处理;3.EFGM中各种支座的处理及程序实现;4.EFGM在边坡稳定中的应用实例。

文章

[原创]无网格计算程序界面开发实践  (作者置顶)

  学习无网格计算方法已经有一段时间了,现在开始写毕业论文。论文的内容计划是写地下结构的弹粘塑性分析,为了便于调试,我想还是编写一个界面比较节约时间。
  在这些方面我也是边学边做,如果大家有更好的办法,还请不吝指教!THX!

  一、主界面

  主界面划分为三个窗口,如图1所示,上面两个窗口为菜单区(受ansys的影响了^_^)和绘图区(以后可以考虑是否用一个属性页,可以绘图,也可以显示计算结果,看内存消耗情况吧),下面的一个窗口为输出窗口(显示的内容类似于日志形式吧,比如当前正在进行的步骤、花费的时间等)。

 主界面

 二、分割窗口 

划分窗口的代码如下:
在CMainFrame中声明如下两个变量,为什么在这里使用CMySplitterWnd而不是CSplitterWnd呢?主要是为了重载鼠标的动作,使得分割窗口的大小不可调整:
 CMySplitterWnd m_wndSplitter; //第一行的两个列
 CMySplitterWnd m_wndSplitter1; //两行

在OnCreateClient中添加以下分割窗口的代码:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
 CCreateContext* pContext)
{
 // create splitter window
 if (!m_wndSplitter1.CreateStatic(this, 2, 1))
  return FALSE;

 if (!m_wndSplitter1.CreateView(1, 0, RUNTIME_CLASS(CBottomView), CSize(0, 0), pContext))
 {
  m_wndSplitter1.DestroyWindow();
  return FALSE;
 }

    if(m_wndSplitter.CreateStatic(&m_wndSplitter1,1,2,WS_CHILD|WS_VISIBLE,
          m_wndSplitter1.IdFromRowCol(0, 0))==NULL)
               return FALSE; //将第0行0列再分开1行2列
 

 if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(140, 5000), pContext) ||
  !m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMeshlessView), CSize(0, 5000), pContext))
 {
  m_wndSplitter.DestroyWindow();
  return FALSE;
 }
 
 m_wndSplitter1.SetRowInfo(0,560,100);   //设置第一行窗口的高度

 return TRUE;
}

新建CSplitterWnd的派生类CMySplitterWnd,再重载以下函数,将默认的CSplitterWnd调用改为CWnd,使分割窗口失去调整大小的能力:
void CMySplitterWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 
    CWnd::OnLButtonUp(nFlags, point);
 //CSplitterWnd::OnLButtonUp(nFlags, point);
}

void CMySplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 //SplitterWnd::OnLButtonDown(nFlags, point);
 CWnd::OnLButtonDown(nFlags, point);
}

  三、创建左侧的树形控制菜单

  左侧的树形菜单为CLeftView,基类为CTree。创建各项目的代码如下:
void CLeftView::OnInitialUpdate()
{
 CTreeView::OnInitialUpdate();

 // TODO: You may populate your TreeView with items by directly accessing
 //  its tree control through a call to GetTreeCtrl().
 m_tree = &(this->GetTreeCtrl());
 HTREEITEM parent[10];
// CString text;
// text.Format("this is parent");

 parent[0] = m_tree->InsertItem("1 设置工程参数",0,1);
 parent[1] = m_tree->InsertItem("2 定义材料",0,1);
 parent[2] = m_tree->InsertItem("3 建模",0,1);
 parent[3] = m_tree->InsertItem("4 布点",0,1);
 parent[4] = m_tree->InsertItem("5 加载",0,1);

 parent[5] = m_tree->InsertItem("6 求解",0,1);

 HTREEITEM parent_sub1[10][5];
 parent_sub1[0][0] = m_tree->InsertItem("1.1 工作目录",0,1,parent[0]);
 parent_sub1[0][1] = m_tree->InsertItem("1.2 项目名称",0,1,parent[0]);

 parent_sub1[2][0] = m_tree->InsertItem("3.1 求解参数",0,1,parent[2]);
 parent_sub1[2][1] = m_tree->InsertItem("3.2 Solve",0,1,parent[2]);

 parent_sub1[5][0] = m_tree->InsertItem("6.1 求解参数",0,1,parent[5]);
 parent_sub1[5][1] = m_tree->InsertItem("6.2 开始求解",0,1,parent[5]);


}

  四、各窗口间的通信

  以各窗口与输出窗口CBottomView的通信为例,CBottomView的基类为CEditView:

CBottomView.h中定义变量:
 CEdit* m_ctrlEdit;
在构造函数中将编辑窗口与它关联:
CBottomView::CBottomView()
{
 m_ctrlEdit =& this->GetEditCtrl();
}
CBottomView中定义一个函数,用于在编辑窗口中输入文本内容:
void CBottomView::AppendText(LPCSTR pText)
{
// m_ctrlEdit->SetMargins(20,10);

 int nLen=m_ctrlEdit->GetWindowTextLength();
 m_ctrlEdit->SetFocus();
 m_ctrlEdit->SetSel(nLen,nLen);
 m_ctrlEdit->ReplaceSel(pText);
}
在需要的地方,通过以下代码可以调用CBottomView中的功能:
void CMeshlessView::AppendText(LPCSTR pText)
{
// CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent(); //这种方法会出错!
 CMainFrame* MainFrame=static_cast (AfxGetMainWnd()); //取得MainFrame,正确
    CBottomView* BottomView=static_cast(MainFrame->m_wndSplitter1.GetPane(1,0));
    BottomView->AppendText(pText);
}

  五、定义工作目录和项目名称

定义全局变量CString strWorkDir和CString strWorkName;方法详见我的博客里的文章“VC中怎么使用全局变量
处理CLeftView树形视图中的选择事件

void CLeftView::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default

 CTreeView::OnLButtonDown(nFlags, point);
 UINT m_uFlags;
 HTREEITEM hItem = m_tree->HitTest(point, &m_uFlags);
 CString sItemName;

 CSelectDir dlgSelectDir;
 if ( (m_uFlags&TVHT_ONITEMLABEL ))
 {
  sItemName = m_tree->GetItemText(hItem);
  if(sItemName.Find("工作目录")!=-1)    //选择工作目录
  {
   if(g_fSelectFolderDlg(&strWorkDir,strWorkDir,true))
   {
    UpdateData(false);

    //改变窗口标题栏名称
 char str2[255];
    strcpy(str2,strWorkDir);
    strcat(str2,strWorkName);
    strcat(str2,"  -  无网格计算");
    AfxGetMainWnd()->SetWindowText(str2); 
   }
  }
  if(sItemName.Find("项目名称")!=-1)     //定义项目名称
  {
   CWorkName workname;
   workname.DoModal();
   //改变窗口标题栏名称
   char str2[255];
   strcpy(str2,strWorkDir);
   strcat(str2,strWorkName);
   strcat(str2,"  -  无网格计算");
   AfxGetMainWnd()->SetWindowText(str2);
  }
 } 
}

选择文件夹的函数,单独定义一个selectdir.h中:另一篇文章:vc文件夹选择对话框
#ifndef GLOBAL_H
#define GLOBAL_H

#ifndef BIF_NEWDIALOGSTYLE
#define  BIF_NEWDIALOGSTYLE  0x0040
#endif

#ifndef BIF_USENEWUI
#define  BIF_USENEWUI   0x0050
#endif

#define REMOVE_HEIGHT 28

// 初始化文件夹设定用的回调函数
int CALLBACK _SHBrowseForFolderCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    static HWND hWndEdit = NULL;
     CString strDir;

     switch (uMsg)
     {
     case BFFM_INITIALIZED:
         {
             ::SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);

             CRect rect;  
             HWND  hChild = GetWindow(hwnd, GW_CHILD);
             while (hChild)
             {
                 TCHAR szClass[256];
                 GetClassName(hChild, szClass, 255);
               //  如果是中间的树目录控件,使可以随窗口移动大小
                 if (strcmp(szClass, "SHBrowseForFolder ShellNameSpace Control") == 0)
                 {
                     GetWindowRect(hChild, rect);
                     rect.top -= REMOVE_HEIGHT;

                     CPoint pt = rect.TopLeft();
                     ScreenToClient(hwnd, &pt);
                     MoveWindow(hChild, pt.x, pt.y, rect.Width(), rect.Height(), TRUE);
                 }

                 if (strcmp(szClass, "Edit") == 0)
                 {
                     hWndEdit = hChild;
      SetWindowText(hWndEdit, strWorkDir);
                 }

                 hChild = GetNextWindow(hChild, GW_HWNDNEXT);
             }

             SetWindowText(hwnd, "工作目录...");
         }
&nbs;       break;

    case BFFM_SELCHANGED: //处理选中的项目,使得编辑框中可以显示文件夹全名
         if(hWndEdit)
         {
             if(::SHGetPathFromIDList((LPITEMIDLIST)lParam, strDir.GetBufferSetLength(MAX_PATH)))
             {
                 SetWindowText(hWndEdit, strDir);
             }
             else
             {
                 SetWindowText(hWndEdit, NULL);
                 SendMessage(hwnd, BFFM_VALIDATEFAILED, 0, 0);
             }
           strDir.ReleaseBuffer();
        }
        break;

    default:
        break;

    }

    return 0;
}

//lpstrFolder返回的文件夹名称
//strIniFolder初始文件夹
//bAvailNewFolder是否允许新建文件夹
bool g_fSelectFolderDlg(CString* lpstrFolder,CString strIniFolder,bool bAvailNewFolder)
{
 bool   ret;
 char   lpszPath[MAX_PATH];
 LPMALLOC  lpMalloc;
 BROWSEINFO  sInfo;
 LPITEMIDLIST lpidlRoot;
 LPITEMIDLIST lpidlBrowse;
 
 if(lpstrFolder == NULL)
  return false;
 
 if(::SHGetMalloc(&lpMalloc) != NOERROR)
  return false;
 
 ret = false;
 
 if(strIniFolder != "")
 {
  if(strIniFolder.Right(1) == "\\")
   strIniFolder = strIniFolder.Left(strIniFolder.GetLength() - 1); //删除末尾的"\\"
  
 }
 
 ::SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &lpidlRoot); //取得选定的文件夹名
 
 
 ::ZeroMemory(&sInfo, sizeof(BROWSEINFO));
 sInfo.pidlRoot  = lpidlRoot;
 sInfo.pszDisplayName = lpszPath;
 sInfo.lpszTitle  = _T("选择工作目录:");
 sInfo.ulFlags  = BIF_RETURNONLYFSDIRS| BIF_NEWDIALOGSTYLE | BIF_USENEWUI;
// if(bAvailNewFolder == true)
//  sInfo.ulFlags |= BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_USENEWUI;
 sInfo.lpfn   = _SHBrowseForFolderCallbackProc;
 sInfo.lParam  = (LPARAM)strIniFolder.GetBuffer(0);
 
 lpidlBrowse = ::SHBrowseForFolder(&sInfo);   //显示文件夹选择对话框
 
 if(lpidlBrowse != NULL)
 {
  if(::SHGetPathFromIDList(lpidlBrowse,lpszPath)) //取得文件夹名  
  {
   *lpstrFolder = "";
   *lpstrFolder = lpszPath;
   
   if(*lpstrFolder != "")
   {
    if(lpstrFolder->Right(1) != "\\")
     *lpstrFolder += "\\";    //在末尾时附加"\\"
   }
  }
  
  ret = true;
 }
 
 if(lpidlBrowse != NULL)
  ::CoTaskMemFree(lpidlBrowse);
 if(lpidlRoot != NULL)
  ::CoTaskMemFree(lpidlRoot);
 
 lpMalloc->Release();
 
 return ret;
}

#endif
运行结果如图2:


图2 文件夹选择对话框

定义项目名称的程序很简单,只需在对话框的类向导中定义一个与编辑框关联的CString,再在程序中将这个变量删除,把全局变量strWorkName与编辑框关联就OK了。改变的内容如下:
void CWorkName::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CWorkName)
 DDX_Text(pDX, IDC_EDIT_NEW, strWorkName);
 //}}AFX_DATA_MAP
}
运行结果如图3:


图3 定义项目名称

- 作者: 狂龙天下 2005年12月5日, 星期一 23:33  回复(0) |  引用(0) 加入博采

[原创]QQ斗地主记牌器开发实践  (作者置顶)
摘要:开发实践:最终程序可以实现记牌的目的,如果手动点击按钮记牌,没有什么问题。如果使用OnTimer()来自动记牌,刚开始的时候还行,但记一段时间之后就不行了,需要重新激活才行。应该是激活的算法,或者是抓图的算法有些问题。 欢迎有兴趣的朋友一起研究。 查看全文

- 作者: dragon77 2005年06月9日, 星期四 17:48  回复(2) |  引用(0) 加入博采

孙盒淞珍藏两年的精品:图象记忆的基本公式

孙盒淞珍藏两年的精品:图象记忆的基本公式

图象记忆的基本公式


记忆=+
=感知+想象
感知:感官+情绪
感官=视觉++++
情绪:喜怒哀乐惊恐愁




+
(连接、心灵胶水):形象、抽象
         形象:良性、中性、恶性、功能性、中介
         抽象:转化成形象
               人言化、延伸、造句



想象:基础:日常、行业、社会体系
        前提:奇像(我活着的时候拿着球拍打世界杯)
        方法:联想
  =信息库+搜索
     信息库:自然科学 、社会科学


+
(提示):外界的引子
    搜索:

- 作者: 狂龙天下 2008年03月18日, 星期二 22:45  回复(0) |  引用(0) 加入博采

神奇记忆术揭秘(1-5)

神奇记忆术揭秘(1)
一 认识你自己

老子说:"知人者明,自知者智"。
古希腊著名的德尔菲神庙上刻着这样一句令千百年来的后世众生获益良多的谆谆教导:"认识你自己
!"
请问:"您认识自己吗?"我当然不是说您照过镜子没有之类的废话,而是指您是否了解--真正地了解--自己的记忆潜力。

您是否一直认为自己记忆力较差?如果是,您是否相信经过训练可以大大改观?如果不是,您是否认为您的记忆潜力已经发挥到了极致, 再无深挖的可能性了
?
先来看看现代心理学研究得出的结论吧。

人脑由140亿个左右的神经细胞构成,每个细胞有1000~10000万个突触,其记忆的容量可以收容一生之中接收到的所有信息。即便如此,在人生命将尽之时,大脑还有记忆其他信息的"空地"。正常人头脑的储藏量是美国国会图书馆全部藏书的50倍,而此馆藏书量是1000万册。

人的记忆力,即使是发挥最好的人也只用到了其潜力的3~10%。仅仅这样小的比例已足以创造出令世人叹为观止的"奇迹"来了。古罗马的哲学家塞涅卡可以重复2000个只听过一次的不连续的单词。贝多芬可以边散步边作曲,在作品尚未在头脑中完成之前,从不用纸和笔记录一个音符。俄罗斯世界象棋冠军阿廖欣1938年在美国芝加哥市同时下32盘盲棋,在2000个方格上调遣成千个棋子。拿破仑对于自己手下的士兵,只要见过一次,就可以在下次见到他时准确地认出他。

有人认为,"天才"的智力来源于特殊的大脑,比如超重的或者结构异于常人的大脑。然而,研究表明,成人男性的大脑平均为1350克~1400克,女性平均1200克~1250克。许多成就显赫的名人的大脑都在这一范围之内,有的还在平均值之下。诺贝尔文学奖得主法国作家阿纳托尔·法朗士的脑仅1017克,美国大诗人惠特曼的大脑仅1282克。世界上最重的大脑有2855克,这一庞然大脑的主人该是一位旷世奇才吧?可他竟然是个白痴!!爱因斯坦去世之后,他的大脑成为许多科学家争相研究的对象,经过许多年的折腾,却并未发现他的大脑在结构、功能、重量等方面存在任何异于常人之处。俄国有位记忆力不同寻常的人,他可以准确地回答出15年前某一天某一时刻发生过的事,因而被称为"完美的记忆家"。心理学家鲁利亚曾用数年时间研究他,发现他的大脑结构、功能并无不同常人之处。不同的只是他从小学会了熟记发生在身边的事情的方法而已。

马克·吐温讲过一个寓言:一位游客来到天堂,问圣徒彼得是否可以见见曾经在世的最伟大的一位将军。圣彼得指指身边的一位天使。游客说自己认识他,但他不是什么将军,而只是一个小小的鞋匠而已。圣彼得说:"不错。但如果他在世时当将军,他就会是最伟大的将军了。"他本有将军之才,由于未能充分发挥自己的潜力,终其一生,只是一个默默无闻的鞋匠。

人人都有如此巨大的记忆潜力,而我们却整天为误以为自己"先天不足"而长吁短叹、怨天尤人,或自以为早已脑尽其才、无力可以再使了,这样岂不是象这位抱着金碗挨饿的鞋匠一样可惜
?
也许你对这些仍旧将信将疑,如果真是这样,请你千万不要错过下面的这个实验。

请准备好钟表、纸、笔,然后使用你曾经用过的最好的方法(本书介绍的联想记忆法除外)记忆下面的一段数字(30位)和一串词语(要求按照原文顺序),直到能够完全记住为止。写下记忆过程中重复的次数,所花的时间等数据。4小时之后,再回忆默写一次(注意:在此之前不能进行任何形式的复习),然后填写统计数据。

数字:109912857246392465702591436807
词语:恐惧 马车 轮船 瀑布

熊掌 武术 监狱 日蚀

石油 泰山

学习所用的时间:________
重复的次数
:____________
默写出错率
:____________
此时的时间
:____________
4小时后默写出错率
:_____

现在再按同样的形式记忆下面的两组内容,统计出有关数据,但必须使用提示中的方法来学习、记忆。

数字
:187105341279326587663890278643
(提示:使用谐音的方法给每个数字确定一个代码字,串连成一个有意义、有形象、完整、连贯的故事。故事大意:你原来有胆小之病,服了一把治胆的神奇的药后,大病痊愈,从此胆大如斗,连杀鸡这样的"大事"也不怵头了,一刀砍下去,一只矮脚鸡应声而倒。为了庆祝病愈你和爸爸,还有你的一位朋友,来到酒吧。你的父亲饮了63瓶啤酒,大醉而归。走时带了两只西瓜回去,由于大醉,全都丢光了。现在,你正给你的这位朋友讲这件事,你说:"一把奇药(1871),令吾杀死一矮鸡(0534127),酒吧(98),尔来(26),吾爸吃了63啤酒(58766389),拎两西瓜(0278),流失散(643)。
")
词语:火车 黄河 岩石 鱼翅 体操 惊讶 煤炭 茅屋 流星 汽车

(提示:把10个词语用一个故事串连起来,请在读故事时一定要象看电视剧一样在脑中映出这个故事描述的画面来。故事如下:一列飞速行驶的"火车"在经过"黄河"大桥时撞在"岩石"上,脱轨落入河中,河里的"鱼"受惊之后展"翅"飞出水面,纷纷落在岸上,活蹦乱跳,象在做"体操"似的。人们目睹此景大为"惊讶",驻足围观。有几个聪明人拿来"煤炭",支起炉灶来煮鱼吃。煤不够了就从"茅屋"上扒下干草来烧。鱼刚煮好,不料,一颗"流星"从天而降砸在炉上。陨石有座小山那么大,上面有个洞,洞中开出一辆"汽车"来,也许是外星人的桑塔纳吧。)


学习所用的时间:________
重复的次数
:____________
默写出错率
:____________
此时的时间
:____________
4小时后默写出错率
:_____

通过比较两次学习的效果,可以看出:使用后面提示中的联想记忆法来记忆时,时间短,记忆准确,效果持久。

如果后者的效果优势不是很明显,很可能是由于刚刚接触新的方法, 不太适应,感到生疏,甚至有点别扭。不过,经过一段时间的练习之后,你会很快适应它,掌握它,离不开它。

实验可以告诉我们
:
①好的方法可以显著地提高学习、记忆的效率。

②改善记忆,你也做得到。

③学习、记忆完全可以是一件趣味盎然的赏心乐事。"学海无涯",不错,但何必非得"苦"作舟呢?

==================================================================================================
神奇记忆术揭秘(2)
二 你的起跑线

为了以更加直观的方法检验这种方法的效果,你可以用下面这份记忆题测一下自己现在的记忆水平,了解一下你学习的起点。在学完后,再做一份相同数量与难度的同类记忆题。通过前后对比,看一下通过学习有无明显进步。你也可以任选其中一种题型,自己多出几份,在学习过程之中,每过一段时间就自我测验一下,看看有无进步。这样可以经常看到自己的收益,从而增强学习的兴趣和信心。
不过请你千万记住一点:方法必须知而行之,勤学多练,才能得心应手,才能见效明显。指望天上掉饼,地下冒钱,读一遍书马上过目不忘,这是不可能的。至少本书无法提供这样的祖传秘方。

书中虽也提供了不少训练题目,但仅靠这些还不够,你还应该在学习、生活中多加应用,勤加训练才可以。"常用的钥匙最亮",方法的根有点苦,有些涩,但它的果实却是香香的,甜甜的。

另外还需说明的是,本书训练所选题目尽量避免出现中小学所学课本中出现的知识点,原因在于这样的内容会使已经掌握它的读者由于轻车熟路而不能通过测验反映自己使用"新"法的效果。

下面是第一份测试题,请用你以前掌握的最佳方法来记忆,然后记下有关数据。

一、记忆几位名人的脑重量,并做后面的第一题。

拜伦 2238克 巴甫洛夫 1653克 门捷列夫 1570克 屠格涅夫 2012克 高斯 1492克 法朗士 1017克
二、配对题:每组两词一一对应,请记住其对应关系。然后做后面的第二题。
狮子-暖瓶 榆树-枕头 总统-钱包西瓜-书籍 算盘-联网犯罪-蜘蛛哲学-宝塔 天鹅-理智扎啤-起义家庭-狗熊

三、请按顺序记住影响世界历史的100件大事中的前20件中每一序号对应的事件。
1.汉谟拉比法典
2.埃赫那吞改革

3.罗马建立

4.犹太教的创立

5.佛教的创立

6.儒学的创立

7.希波克拉底创立医学

8.希腊三哲的哲学研究

9.道教创立

10.马拉松战役

11.亚历山大远征

12.基督教创立

13.米兰敕令

14.查士丁尼法典

15.斯巴达克起义

16.伊斯兰教创立

17.查理大帝统一西罗马

18.十字军东征

19.自由宪章运动

20.成吉思汗的霸业


一、写出下列名人的脑重量,然后填写统计表。
高斯________ 拜伦__________ 巴甫洛夫______门捷列夫_____ 屠格涅夫____ 法朗士________
二、出下列词语的对应词,然后填写统计表。
暖瓶____ 榆树____ 狗熊____ 宝塔____ 起义____ 西瓜____ 联网____ 犯罪____ 天鹅____ 钱包____
三、填写下列序号对应的世界大事,然后填写统计表。
8_____________ 2_____________1_____________ 9_____________7_____________ 6_____________16____________ 3_____________11____________ 14_____________4_____________ 10_____________13____________ 17_____________15____________ 12_____________19____________ 5_____________18____________ 20_____________
测验结果统计表
┏━━━━┯━━┯━━┯━━┓

┃ 题号│ │ │ ┃

┃项目 │ 一 │ 二 │ 三 ┃

┠————┼——┼——┼——┨

┃学习重复│ │ │ ┃

┃的 次 数│ │ │ ┃

┠————┼——┼——┼——┨

┃所 用 的│ │ │ ┃

┃时 间│ │ │ ┃

┠————┼——┼——┼——┨

┃出 错 率│ │ │ ┃

┠————┼——┼——┼——┨

┃4 小时后│ │ │ ┃

┃回 忆│ │ │ ┃

┃出 错 率│ │ │ ┃

┗━━━━┷━━┷━━┷━━┛

测验时间:__年_月_日_时_分

_______________
注:4小时后回忆时可以使用前面的填空题,盖住测验时填上的答案,根据记忆再填一次;也可以测验之后,再抄一份题;也可以第一次测验时用铅笔写,然后擦掉;也可以测验时将答案写在纸上,而不是填在书上。总之,4小时后的回忆效果一定要真实地反映出来,不要受到答案的任何痕迹的暗示或提示。

===============================================================================================
神奇记忆术揭秘(3)
三 解剖一只麻雀--基本原理

有个故事也许你并不陌生。
古时候,风景如画的江南某地,子虚山上有座胤久寺,寺中主持法号土律,好作诗文,爱饮美酒。山下有座书院(也就是学校),唯一的先生名叫汲解,管着十五六个学生。汲先生和土律法师臭味相投,时常上山对饮,以文会友。一日,先生临上山前,给学生留下一道作业题:记忆圆周率到小数点后第22位,也就是3.1415926535897932384626。学生左记右记记不住,愁苦万状,抓耳挠腮。其中有个机灵点的,名叫连象,眼珠一转,计上心头,他把数字用谐音编成"打油词",一记就记住了,又快,又准,又有趣。他把此法传给其他同学,同样见效神速。夕阳西下,先生深一脚歪一脚地回来了。满以为可以借机好好教训教训这帮叫他烦心费神的小家伙。不料,一提问,个个对答如流,先生不禁狂喜。不过,一追问之所以如此多快好省的原因,却差点把他气得休克过去。原来,他们背的打油词是"山巅一寺一壶酒(3.14159),尔乐苦杀吾(26535),把酒吃(897),酒杀尔(932),杀不死(384)乐尔乐(626)。"是骂先生呢,汲先生岂能不急
!
你看,这样记法,比简单的重复重复再重复,是不是好多了?你自己也可以试一试,看是否也可以易如反掌地将它拿下。

如果你也觉得意犹未尽,还可以看下面的故事续集,把圆周率记到第50位小数,在原来22位的基础上再加上4338327950288419716979715058。打油词的故事背景是这样的:学生们见酒中投毒的办法未能成功,就在先生下山之时,施起法术,动员山上的鲜花一齐飞向先生。先生一惊,酒壶落地,踩在上面,一个趔趄,跌下悬崖,几乎上了西天。睁眼一看,原来掉进了冰窖中,里面有个老道正在炼丹。先生摔伤了,向道士讨药医治。浑身发冷,所以又要讨酒暖暖身子。词曰:"此山山花杀尔去(4338327),酒壶令尔白白死(9502884),要求吃药(1971),老朽吃酒吃一壶(6979715),冷(0),我怕
(58)"
我国著名科学家茅以升在83岁高龄这时仍能背出圆周率小数点以后100位的准确数值。日本索尼公司的职员寄英哲能记到15151位,为此他花了10个月的时间。人们曾对此惊叹不已。现在,你是否仍旧认为他们这样的成绩令我们普通人觉得可望而不可及呢?孟子说:"人皆可以为尧舜"。佛教有云:"一阐提亦可成佛",所言甚是。

当然记到22位也好,50位,100位,15151位也好,就其实用价值而言显然没有多大意义。但此事本身却可给予我们不少有益的启示。我们除了可以看到人的记忆力的开发具有比我们通常认为的那样广阔得多的前景之外,还可以从方法上学到许多可以在记忆其他知识时为我所用的原则和技巧。

麻雀虽小,五脏俱全。故事中的记忆过程之中包含了许多记忆的规律和方法。解剖这只麻雀可以帮助我们了解提高记忆效率的基本原理。

在故事中,那个连象实际上采用了一种千百年来一直为一些人使用并行之有效的记忆方法,我们可以称之为联想记忆法。尽管其中融合了许多其他的方法,但联想是其中的关键性因素。

这种方法为什么特别有效?一句话,因为它合乎心理活动的客观规律。

1.让蜘蛛趴在网上
蜘蛛如果只用一根丝吊起来,这根丝一断,它就会摔下来。聪明的蜘蛛把丝织成一张大网,自己趴在上面,用爪抓住许多丝,这根断了,还有另外许多根连着,支撑着。所以它可以在空中如履平地,行动自如。
知识如蜘蛛。如果学到的知识孤立地存在,很快会下沉到意识的深处,需要时提取困难。如果用几条线把它和其他知识连起来,知识就被挂住了,不容易下沉,即使印象模糊,还可以通过线索方便地把它提出来,迅速准确,有条不紊。联系越多,线索越多,记忆越牢固,回忆越方便。

在故事中,数字、老师、和尚、酒、花、道士之间本无任何关系,简直是风马牛不相及。但是,经过处理,它们在故事中形成了一个整体,织成了一张线索的蛛网。记住故事,就记住了数字。想到任何一个因素,就会联系到故事、打油词、数字。回忆数字时如果记不起来了,想想故事就可以方便地恢复记忆。

联想有利于记忆,这是心理学家普遍的共识。美国的詹姆士说:"一件在脑子里的事实,与其他多种事物发生联想,就容易作好记忆。所联想的其他事物,有如一个个的钓钩一样,能把记忆着的事实钩出来。当记忆从表面向下沉落的时候,这种钓钩便能把它钓上来。"讲的就是这个道理。
早在古罗马时期这一规律就已被一些演说家纯熟地应用于实践中。为了记住头绪纷繁的演讲思路,他们把要点和家中的器物相联系。比如今天要讲四个方面的问题:奴隶、税收、犯罪、战争。家中经常用于记忆的东西依次有:门前石狮子、门上的锁、门内大树、树上的鸟窝等等。也许他会这样想:石狮子张开血盆大口要吃掉他,幸亏"奴隶"及时赶到,一剑刺在它的肚子上,狮子大吼一声,落荒而逃;门上铁将军把门,是因为院中堆满了黄金白银,这都是收"税"收上来的,怕人见了会起歹意;大树上有一根旁逸斜出的粗枝,上面吊了一个人,遍体鳞伤,他因"重罪"而受鞭笞,而所谓"重罪"也许只是在见到贵族的时候没有行礼而已;鸟巢遭到老鹰的袭击,摇摇欲坠,老雀为了保家卫穴,奋起抵抗,双方燃起了麻鹰百年"战争"的烽火狼烟。这样在上台演讲时,他的脑子里就会始终有一条线,依次串着要点,思路清晰,繁而不乱。有时候,要点也许不只4个,而是10个、20个。那也没问题,既然他是贵族,器物自然不会仅此而已,还可以扩展到餐桌、酒杯、夜壶什么的。即使穷,也没有关系,反正一想即可,不必真的付钱买来放在家中才可以想。这种方法有人称之为"罗马居室法"。后面我们还会把它应用到我们这个时代的记忆中去。

2.无中生有
这里有两组字母,请分别记忆一下,然后默写,看一下哪一组记得快,哪 一组记得准。
第一组
:Bi zi zhang zai zui de shang mian hu zi zhang zai bi zi de xia mian.
第二组
:Ed ke kswlj iek jei kd skeiw jdsi ls jw diedj lss ke ik dd efs iefst.
两组字母数目相同,但前者显然记得又快又准,而后者又慢又费劲,还不容易记准,忘得也快。因为前者字母组成汉语拼音,整体上是两句有意义的话;而后者,各个字母孤立地存在,前后之间毫无联系,整体上没有任何意义。

大脑的脾气就是这样,有意义的东西一见倾心,记得快、准、久,无意义的则拒之千里,记起来慢、难,转眼就忘。
即使是有意义的知识有的人在记忆时也不注意通过领会意义来加深记忆,而象背百家姓似的机械重复。这样不靠理解、不抓知识的联系的机械重复强行记忆,就叫机械识记。

相反,有的人,即使是记忆本身并无任何意义的材料,也会人为赋予意义,无中生有地创造含义,建立联系,而对有意义的材料,则会更加深入地挖掘、利用它的意义,或也通过赋予意义加强记忆,这种方法,就叫意义识记。

德国心理学家艾宾浩斯通过实验证明:记忆12个无意义的音节,平均要复习16.5次,记忆36个无意义音节,则要54次,而记忆480个音节的六节诗,只需复习大约8次即可成诵了。有人统计,记80个无意义、不连贯的单词比背80个字组成的诗 要多费10倍的精力。

有的人,甚至有的心理学专家,尽管知道应该尽量避免机械识记,但在涉及到那些不易理解的或无意义的知识(如人名、地名、数字等)时,却又认为"只能采取这种方法",似乎无意义的学习内容和抽象、"深奥"的内容成了机械记忆的"最后避难所"。联想记忆法则把这种费力不讨好的方法从最后避难所里驱逐出来。有意义的要,无意义的更要意义识记;理解的要,不理解的也要意义识记。这也是联想记忆法的成功因素之一。

有人问过茅以升,这么大年纪还能熟记圆周率到100位小数的秘诀何在,茅先生说了七个字:"重复,重复,再重复。"寄英哲记到15151位,也是靠的重复,所以用了10个月之久。可是前面的介绍足以说明,任何人使用联想记忆法,都可以很轻松地记到50位。一般人,即使加上自己编码多花一点时间的因素,1小时记住50位,也是相当保守的估计。假设记到15151位,也不过用到303个小时而已。即使再花上同样多时间来复习,也不过区区606小时。况且经过训练,编码速度会大提高,而且使用科学的复习方法,复习的时间远远少于学习所用的时间,所以606小时的估计仍是相当保守的。即便如此,以每天记忆4小时计也仅仅用5个月就可以完工了。而达到茅以升的记忆标准,总共需要的时间,顶多不过4小时而已。


数字的记忆往往令许多以记忆力超群的人也望而却步,因而通常被作为记忆力的试金石。数字记忆尚且如此简单,何况其他。
比如人名,尤其是洋人名,似乎难记,所以有人说遇到此类知识只好机械一下。其实人名不仅本身往往大有讲究,寓意深广,参透含义之后记忆十分方便,而且即使人为地曲解,赋予含义,也是一件相当容易而有趣的事,记忆起来并不费力。于得水,就是鱼儿入水,吉祥如意。牛得草,自是丰衣足食,温饱不愁。有个人叫朱大年,叫了半辈子,忽然要改。猪到了大年,不是该杀么?干脆改个朱初一,离死期还早着呢,再说天天初一,也许就永远不杀了。高尔基,令人由"高耳鸡"联想到"矮脚鸡",两个一耳一脚,一上一下,一长一短,相映成趣。拉札诺夫(保加利亚心理学家,超级学习法的倡导者)令人想到他是个恐电症患者,一拉闸就哆嗦,才叫"拉闸懦夫"。车尔尼雪夫斯基令人想到一辆车陷入泥中,天又下起大雪,"斯基"多着急啊。史密斯到了门第观念音容宛在的中国,不必趾高气昂,你祖上不就是一个打铁的吗?Smith就是铁匠,而且还是Blacksmith黑铁匠。

其他难解的名词、概念,也都可以用这种方法拆得面目全非,编得趣味盎然,在欢声笑语之中将硬骨头啃下,绊脚石踢开。这种记忆的方法虽然可以称之为意义识记,但稍稍不同于一般意义上的意义识记,因为它采用的意义多数情况下不是学习对象内在的,而是人为附加的,吃柳条子出簸箕--肚里编的。

3.神游字外
同样一件事,听说过,读到过,与目睹过、亲历过相比,后两种更能留下深刻得多的记忆痕迹。"百闻不如一见,百见不如一干。"
学习过程中,大部分时间,我们都在接受间接的经验。前人积累,我们继承;前人实践,我们来听,来读。根本不可能每个事实都去目睹,都去亲历,都去实践一番。

但是幸好人的大脑天生就有"神游"的本领,眼不能看的,可以用脑去看;耳不能听的,可以用脑去听;身不能历的,可以在脑中去经历。上下五千年,瞬息可以穿越;纵横千万里,历历如在眼前。文字不过是把活生生的世界用一种平面化的符号的形式蕴含在里面了,善读者看到的不仅仅是文字的铁画银钩,而且有它们背后的立体、动态、鲜活的多彩世界。一段文字就是一幅画,一部电影。即使是本来极其抽象的知识,也可以设法用形象来表示,加以处理,使枯燥的生动起来,平面的立体起来,静止的活跃起来,平凡的惊心动魄起来。

联想记忆法就是这样,形象的就去"看",去"听",去"经历";抽象的就给它一些形象。记忆时看到的是字,想到的是形象;回忆时想到的是形象,表述时用的是形象代表的抽象原型--文字。

在前面的故事中,数字本来是抽象的,编成故事,就有了形象。记忆时,透过数字,看到了连绵的青山,听到了古寺的钟鸣,闻到了馥郁的酒香,体会到了先生时而狂喜、时而哀伤、时而恐怖、时而悠然的心路历程……你仿佛感到精神离开躯壳,到了山上,进了寺中……不知不觉中,整个故事已经深深地印在了你的脑海中,而原本十分令人头疼的一长串数字也象扎了根一样,要从脑中拔除它,恐怕也不容易了。当你回忆时,自然而然地会想到故事,记起口诀,还原成数字。仿佛不是你从茫茫脑海中钓出来的,而是从大脑的泉眼当中汩汩地冒出来的,堵也堵不住。

在记忆时,运用想象,注重形象,创造形象,借助形象这一中介挂住知识,是联想记忆法的第三个"秘诀"


4.
哪里没有兴趣
哪里就没有记忆

快乐的记忆永远不忘 ,讨厌的记忆眨眼消失。相信这是人们从经验中得出来的不争的共识。歌德说:"哪里没有兴趣,哪里就没有记忆。" 孔子讲:"知之者不如好之者,好之者不如乐之者。"都是这个道理。兴趣的有无,绝对是学习、记忆过程中举足轻重的因素。
学习如果充满了趣味,有谁还会厌学呢?记忆如果洋溢着乐趣,大脑皮层就会产生更强的兴奋中心,主动积极地去参与学习、记忆。注意力更集中,思维更活跃,效率更高,保持更久。


联想记忆法显然使枯燥的知识变成了有趣的,使记忆过程充满了意想不到的情趣。创造出的形象,或奇特,或风趣,成为取之不尽的快乐源泉。
联想记忆法鼓励使用者在记忆中尽量把知识与自己感兴趣的事物建立联系,这就更加增强了记忆的趣味性。日本有个叫青柳修道的人,在辅导六个儿女成才的过程中,摸索出一套基于联想的记忆法。比如对于车迷,他会建议他把需要记忆的东西概略地用小字写在汽车广告画上挂起来,时常欣赏品味,就在赏车的同时记住了挂于其上的知识。"爱屋及乌",爱车也就把爱顺便扩展到了车上的ABC或点线面上了。这样就使记忆成了逍遥自在的活动。

其实,即使不加要求,人们在联想时,也往往首先想到自己感兴趣的事物。这样,联想记忆就是不断地与你的兴趣中心打交道,自然容易乐此不疲。

古人常说"书山有路勤为径,学海无涯苦作舟。"现代人也往往引以自励。但是,掌握了记忆的技巧之后,你会体会到学习的另外一种境界:"书山有捷径,学海乐无穷。
"
需要多说一句:体味其中真趣,要有一颗童心。有的学生反馈说,已届成人的他,用这类有如幼儿过家家的方法来学习,打心眼儿里觉得幼稚,总有排斥心理。如果你也"大人所见略同",奉劝阁下想想两位前人:一是苏东坡,人家"老夫"还会偶尔"聊发少年狂"呢;另一个是我们的总工程师,他几乎把那句民间俗语变成了他的口头禅,"不管白猫黑猫,逮住耗子就是好猫"。再想想两个"何必":一是何必人未老而心先衰呢?二是何必自讨苦吃,放着自在不自在呢?若是乐在其中,幼稚一把何妨?


5.
大脑不再"滑轮"

机械识记时,往往是小和尚念经--有口无心,口里念念有词,意识早已不知所踪了。表面上勤勤恳恳,兢兢业业,梁也悬了,股也刺了,可是心也早已"不在焉"了,结果知识如流水,大脑似漏斗,装来装去半滴留不住。
而联想记忆法总叫你的大脑闲不住,遇到无意义的,你要给它找个有意义的"代理人";遇到抽象的,你得给它涂脂抹粉弄出个"看"得见、"摸"得着的形象来。忙活完了这些,还要拿出媒婆的本事来,把风马牛八竿子打不着的东西都撮合到一块儿,然后编出个连自己都不相信的"瞎话",好叫大脑愿意把它们留住。复习的时候,又得想故事,"放电影",又得把故事中暗含的知识原型给剔出来,还之以本来面目。哪还有闲工夫开小差
?
思维越积极,记忆越深刻,效果越持久,这是心理学实验证明了的普遍规律。

联想记忆法不仅能让大脑忙活起来,更重要的是它还能使左右两个半脑全部动起来,并充分联盟、合作、交流。"1+1>2",这样的效果是任何一个半脑单独活动所难以比拟的也是单纯的两脑交替使用所难以企及的。

心理学家发现人脑的左右两个半球分别负责智力的不同方面,左脑主管抽象思维,右脑主管形象思维。无论何种智力活动,"左右开弓"、"双管齐下"的效果都明显地优于"各自为政"、"单打独斗"。现在被炒得全国沸沸扬扬的《学习的革命》一书,其基本点之一也正是倡导双脑并用,在学习中更好地把抽象思维和形象思维有机地结合起来。

在联想记忆中,两个半球的功能都被调动起来。当你想象形象、回忆故事时,用的是形象思维。当你挖掘事物的内部联系时,使用词汇复述知识时用的是抽象思维。当你将抽象的编成形象的将形象的换成抽象的,两半大脑同时上场,并相互交流。整个记忆过程中,两种思维往往紧密地交织在一起,你中有我,我中有你。两半大脑无时不在飞速地运转着,交流着。所以,记忆的效果明显地高于常规方法,正是理所当然的。

====================================================================================================
神奇记忆术揭秘(4)

四 千里之行,始于足下
--基本功训练
树高千丈,叶落归根。联想记忆法具体应用起来,千变万化,但万变不离其宗。无论怎么应用,都离不开联想、想象、编码三种基本能力的发挥。这就是联想记忆法这棵大树的根基。
这些能力,虽然人人都有,人人会用,但为了适应本法的特殊要求和提高使用的熟练程度,对训练的方法做一些简单的介绍,通过一定量的练习熟悉这些方法仍是十分必要的。这就是学习本书方法这一"千里之行"的足下第一步。

1.由此及彼--联想的训练

联想即由此及彼,由一件事物想到另一件。
为什么思路会从这里跳到那里呢?一般来说,是由于它们之间存在这样的关系
:
①近似。由中国到日本,由旗杆到国旗,是相近。由公鸡到中国地图,由盆景到山水实景,是相似。

②相同。男人、女人,同属于人;茅屋、大厦,同属建筑。

③相反。黑与白,上与下,歹人与好汉,警察与小偷,相反。

④相关。云和雨、笔和墨水,是相关。

练一练。请你分别采用上述四种关系给下面三个词找到一些联想词,越多越好。这三个词是:照片 插座 电脑 。

例如,若从"蓝天"开始联想,可以联想到的词及其与起点词(即"蓝天")的关系的分别是:黄土地(相反) 兰草(相似) 白云(相近) 玉帝(相关)。当然联想涉及到的关系绝不仅此四种,使用时可以灵活变通,不拘一格。当你感到思路无法继续下去的时候,可以对这个词语代表的事物作一下属性分析,由每一属性出发又可生发出无数个联想之"彼物",仍以蓝天为例:以颜色论,是蓝色,由此可联想到兰花、景泰蓝、鬼火;以状态论,是气,可以联想到氧气瓶、氢气球、肺;以体积论,其大无比,可想到巨人、大象、长篇小说、宽银幕、震雷(声音之大)……另外,你还可以从形状、高度、气味、内容物、历史等等许多角度去展开联想。这样一来,一物可以联想到无限多的事物。对于初学者来说,轻轻松松达到100个应该不为难事。请你试试上面的练习,记下联想到的"彼物"的数量,以后可以经常做做,看看有没有进步。以后题目可以自拟,尽量避免重复。

具体训练的时候,可以灵活采用多种方式。例如
:
①联系法。任取两物,找出他们之间的内在联系,即相同、相关之处。联系必须是内在的。例如钢笔和树,联系有:树做成纸可以用钢笔写字,可以做成盒子盛钢笔;用钢笔可以画树;你小时候常在树下写作业;钢笔坏了时可以用削尖了的树枝代替;你写字用的桌子也是树做的;"树"字和"钢"字都是九画;在五行中"金"、"木"相克......几乎任何两个事物之间都存在千丝万缕的联系,只要充分发挥你的联想潜力,总能找到不少。这种训练可以有效地开拓思路,不仅在联想记忆中受益,而且通过培养发散思维能力,提高创造性思维品质,可以对解决数理化问题、写作构思问题起到明显的促进作用。

请你试试这三组事物,找出它们之间的联系
:
水--土 桌子--被子 硫酸--监狱

联系找得越多越好,尽量达到10个以上。

②辐射法。就是象前面对"蓝天"的联想一样,找出尽量多的与起点事物有联系的事物。由一个"此"发散出多个"彼"。请你试用"枕头"来练一下。

③接力法。就是由一个"此"联想到一个"彼",再从这个"彼"到另外一个"彼",如此循环下去,连绵不断。如从"水"开始,可联想到河;从河开始,可联想到鱼;从鱼开始,可想到锅......请你从"雪"开始,接力联想。

④定向法。就是指定两个事物,由一个开始,经过一系列的联想,最后到达另一个事物。例如指定始于"水",终于"钢笔",可以这样联想:水-河-污染-工厂-厂长-秘书-钢笔,。注意不要急于收兵,想得多一点才有利于锻炼联想力。请你试试以下三对:火车-手枪 女神-幼儿园蛛网-算盘。

⑤循环法。与定向法相似,不过最终是回到起点上,取物只取一个。例如:从"水"开始,最后还是回到"水"。请试试。

⑥成语接龙:许多人玩过这样的游戏。为了训练联想能力,可以采用上述②③④⑤四种方法来,而且允许以同音字相接,并且不必局限于成语,用两字或三字词汇、谚语、俗语、名言、诗词相接,都无不可。请试试这三个成语:


贴子相关图片:
倾国倾城 投笔从戎难兄难弟
为了检查训练的效果,你可以经常测一下自己的联想水平。方法也可从简:任取一事物,作辐射联想,以5分钟为限,想到一个,就在纸上画一个点,结束后查一下点数,作好记录,以便在不断的比较中看到自己的进度。

你也可以采用这样的方法测验一下联想的广度(即一次可以联想到的事物的数量):指定起点后,作辐射联想,不限时间,直到感觉吃力为止,看有多少结果,然后作好记录。在测广度的同时,也可以记下所用时间,计算一下速度。

测试的结果,可以填在如下所示的表格中以利比较。

┏━━━━┳━━┯━━┯━━┓

┃时 间 ┃速度│广度│所用┃

┃(月、日)┃ │ │方法┃

┠————╂——┼——┼——┨

┃ ┃ │ │ ┃

┠————╂——┼——┼——┨

┃ ┃ │ │ ┃

┠————╂——┼——┼——┨

┃ ┃ │ │ ┃

┠————╂——┼——┼——┨

┃ ┃ │ │ ┃

┗━━━━┻━━┷━━┷━━┛

其中的速度是用广度除以所用的时间。记下使用的方法是因为方法相同的数据之间更有可比性,所以比较时除了看速度、广度之外还应看一下方法。

2.白日做梦--想象的训练

当事物不在眼前时在脑中浮现出它形象,或以经验过的事物为基础加以加工、组合、夸张、变形从而在脑中创造出新形象的心理活动叫做想象。前者是再造想象,后者是创造想象。在联想记忆中,创造想象尤为重要。
想象的训练,题材可以任取,最好每次都有新意,避免僵化,这样才能达到训练的初衷。

在进行想象时应该注意
:
①尽量注意每一个细节,看到的形象越清晰、准确越好。当然完全清晰并非人人、次次都能做到的。几乎总是会有一些模糊的因素,对于自己不太熟悉的材料尤其如此。如果模糊得太严重,平时应对这些事物留心观察一下。通过观察,形象会日渐清晰。

②从不同的角度和层次去观察。比如一只手表,在想象时,你可以想象它的前、后、左、右,也可以进到内部看看它的齿轮,还可以想象它在不同的人的手腕上的样子,在不同的季节、不同的天气、不同的环境背景中的形象和感觉。

③动员尽量多的感觉"器官"参与进来,物体的色、香、味、嗅、触、冷暖、软硬、粗细等等,都尽力地去体会,不仅瞻仰,而且聆听、抚摸,还要舐舐、闻闻、用用,在上面踹上一脚也无不可,千万别象对待历史博物馆里的兵马俑那样敬而远之。动用的感觉越全面,印象越深刻,记忆越晰,效果自然也越好。

④通过夸张来强化事物的特征以便想象更具独特性、奇异性,对大脑的刺激更强烈,印象更深刻。例如,矮人可以在瓜子里面大排筵宴;一个人腿长,可以看到他的双腿竟从脖子开始分叉;一辆车快,可以想象它长了翅,尾灯成了火箭的助推器;一个人狂喜,可以想象他的嘴巴裂到了后脑勺,下巴张得太大,竟然落下来砸穿了此人的脚丫子,把地也砸了一个洞,当然,皮鞋也得换双新的了。

⑤想象的物体应该尽量多样化,尤其应该多想想自己不熟悉的事物。脑中积累的形象(心理学上叫做表象)越多,思路越开阔,记忆时联想起来越能得心应手。如果太少,往往容易因为把太多的东西挂在同一事物之上而容易造成混淆。如果表象太少,最好平时多观察一下周围的事物。

⑥让静止的画面动起来。大脑爱动不爱静。动态的东西容易引起它的注意,留下深刻的印象。例如,想到钢笔,最好别让它躺在柜台上,插在笔筒里,摆在铅笔盒里,可以让它拿在手中奋笔疾书,把它象飞镖一样投掷,象子弹一样射击,象火箭一样发射。又如想茶杯和老虎,不要让老虎蹲在茶杯旁,可以让它在茶杯中咆哮,让它吞下茶杯咬碎了疼得乱跳,用尾巴卷着茶杯饮水,把茶杯扳倒踩上去滚来滚去。

⑦不落俗套,不怕怪诞。有人说:"狗咬人不是新闻,人咬狗才是新闻。" 又有人讲:"男人不坏,女人不爱;文章不怪,编辑不爱。" 大脑是编辑,爱记怪"文章";大脑爱新闻,平凡容易忘。越离奇、怪诞、荒谬可笑,越能取悦大脑。例如,想象手枪和大米,完全可以把大米装入枪膛,当作威力无穷的子弹,不论这是否符合物理规律,是否有先例可循。想象老鼠时完全可以让它象人一样走,象鸟一样飞,可以和猫做朋友,成亲家。想象西瓜时,完全可以在瓜皮上开个门,打开看一看,说不定里面会有个桃源世界什么的。

⑧把想象和联想结合起来训练,尤其是想象两个事物时,这时可以用一种奇特的方式把二者联系起来。比如电风扇和帽子,可以想象一个人的头被风扇削下来了,帽子还在肩上,或者把帽子接在电机上,就成了一个土制风扇 ,或者把风扇 安在帽子上就制成了一个飞碟,你可以驾驶它去周游冥王星。即使是在想象单个事物的时候,也可以把它放在与其他事物的联系中去想象。

请熟悉一下以上要点,然后做后面的练习。

1.
细节训练。想想以下事物的各个细节,并想象用笔画出每个细节的情形:牛 电视 桌子 槐树。
2.角度训练。对上题事物从各个角度进行观察,想象从上下左右看、到里面看分别看到的景象,注意视角渐变时看到的物体的相对运动。

3.感官训练。想象坐在火炉上穿着老棉袄时的感觉;想象身着单衣坐在冰山上雨从天降;想象左手拿海绵右手拿铅球;想象一首乐曲或一首歌曲;想象坐在餐桌前可口的菜肴一盘一盘端上来的情形,注意每一盘的色香味和进入胃肠的过程。

4.夸张地想象以下事物:刽子手 骑士 罪犯 穷光蛋 机器人 工头 飞碟

5.对以下事物进行奇特联想把每组中的两件事物联系起来:泥潭-企鹅金鱼-八国联军 天安门-钟乳石 斜拉桥-沙雕 喷泉-吕布 足球-唐老鸭

6.运用你能想到的任何方式想象以下各事物,每想完一个对照八个注意事项,找出不足之处再作进一步的想象
:
垃圾箱 股票 啤酒 汽球 泰山 教师 医生 狮子 篮球 皮鞋 剧院

3.花非花--编码训练

对于抽象知识要赋予一个形象用来代表它,就是给原型找一个形象的代码,这一过程叫做编码。
通常编码的方法有
:
1.谐音。例如把"3.14"编为"山巅一寺","本质"编为"本子","追求"编为"追球","具体"编为"锯蹄",就是谐音法。用与原型发音相同、相近、相似的字来代替原型,从而获得一个形象。请用此法给以下几个原型编码
:
1354 64 知识分子 概念 钙 创造 过程 思维 联系 调整 动作 发展

2.具体化。有些原型是对许多具体事物的概括,这时可以用它包括的具体事物来代表它。例如以下编码即是:水果-苹果 怪物-猪八戒文具-橡皮 教育家-孔子。其中每对词语的前者是抽象的原型,后者是其具体化之后的代码。请用此法给以下原型编码
:
物质 天文 哲学 职业 爱国 革命 佳肴 工厂 野兽 香花 文人 演员

3.相关法。就是用与原型相关的事物代替原型。例如以下编码即是:哲学-孔子 学习-书籍 阅读-图书馆。请用此法给以下原型编码
:
方向 天气 宇宙 研究 探索 军事 语文 流行 顽症 爱心 灾害 恻隐

4.比喻法。就是给原型打个比方,它象什么就用什么来代替。例如:残暴-狼 学习-行舟 记忆-装载货物文盲-瞎子。请用此法给以下原型编码
:
想象 教育 写作 改革 爱国 朋友 线索 法律 独特 美丽 丑陋 大话

5.简化:以一当十,化繁为简,以简驭繁。一文之中有重点的段,一段之中有重点的句,一句之中有重点的词,一词之中有重点的字。从中找出关键的字词,来代表整个知识整体。

例如以下一篇短文:


"
记忆术是人类记忆的技能和方法,旨在促进人们记忆知识材料的一种程序。目前最流行而又取得公认的记忆术是PQ4R法。
PQ4R法的取名是下面所述学习材料应该遵循的6个步骤的英文缩写。

预习(Prepare):渺猎全部学习材料,以确定要探讨的一些课题,确定作为重点来阅读的各分段。

提问(Question):提出有关分段的问题把各分段的主题改为适当的问句。

阅读(Read):仔细阅读各分段的内容,尝试回答各分段所拟定的问题。

思考(Reflection):在阅读时思考内容,力图给予理解,想出一些例子,把材料和自己已有的知识联系起来。

复述(Repeat):学完一个分段后,尝试回忆其中所包含的知识,力图回答自己对各分段所提出的问题。如果不能充分回忆,就重新阅读记忆困难的部分。

复习(Review):学完材料后,默默回忆其中的要点,再次尝试回答自己所提出过的各个问题。"

这篇短文的要点是记忆术的6个步骤。介绍步骤的6段文字分别可以用一个词来概括:预习、提问、阅读、思考、复述、复习。而每个词又都可以概括为一个字:预、问、读、思、述、复。对每个字进行谐音转换编码,可以把6个字编为"语文毒死叔父",可作如下想:语文书上有毒,叔父读了,就中毒而死了;或者语文老师毒死了自己的叔父,正在上课,几个警察闯进来,铐起来装上警车,运往高墙大院,关进带铁栅的小房间。这样就把整篇文章简化成了6个字,一个小故事。
文中还提到另外一种概括法:取每个要点英文的首字母,简化为PQ4R,我们同样可以对它进行编码转换,比如数字可以谐音,字母可以做为声母字,照这思路可以编为"皮球撕人"、"怕瞧死人"等等。至于如何把这些话和题目挂起钩来,相信已经做过前面的联想练习的读者是不会被难倒的。

只要在理解文章的基础上用这种方法去记忆,经过适当的重复,在回忆时,完全可以很轻松地透过代码想出原型。古人说:"一是一切, 一切是一。" 用在这里,不是太贴切了么
?
这种方法在记忆问答题时非常实用。你不妨从课本中自己找出一些问答题或者类似上文的文章来练习一下,概括出要点,提炼出关键字,加以转换创造出一个形象词作代码。在课本中,这种例子俯拾皆是,因此此处不再出题。

除了以上方法,你还可以根据自己的思维习惯、知识背景摸索一些自己的方法。只要有效,越是不拘一格,效果越好,越是"亲生"的,越加用得顺手。当然了,多数情况下,"领养"还是以其方便快捷而备爱青睐。如果"领养"的方法并无不适,倒也不错,不必太苛求血统了。

现在请你使用任何你能记得起来、想象得到、创造得出的方法给下面一些原型找到可以作为代码的形象
:
第三世界 奋斗 科举制 协商 停火 紧张 趋势 预测 科学 昌盛 记忆 环境 探索 暴动 策略 游戏 人生 荣辱 歌德 帕斯卡 门罗 马里沃 穆尼尔古尔蒙 科索沃 马里兰 孝感 番禺 景颇族

天下兴亡匹夫有责

兴趣是最好的老师

人的素质包括身体、心理、文化、专业、技能、习惯6个方面。人的身体素质又包括体质、体力、体能、体型、精力5个方面。

柏拉图认为:人由灵魂和身体组成。灵魂由理智、激情和欲望组成,三者分别处于人的头、胸、腹部。根据三者比例的差异可以把人分为金子的、银子做的、铜铁做的。他们的职责分别是治人、卫国、受治于人。"职业"分别为统治者、武士、百姓。


4.
曲不离口--见缝插针训练法

在掌握了前面介绍的几种训练技巧之后,你不一定非得拿起这本书时或正襟危坐时才想到训练。其实,无论何时、何地、在何种情形之下,只要想练,都可以练。
这些练习,可说是"招之即来,挥之即去"。吃饭时、下课时、候车时、乘车时、散步时、失眠时、排队时、洗澡时、闲聊时、看电视时、五谷轮回时……

无事无物不可以用作训练的材料,看到的,听到的,想到的;一粒沙,一只鸟,一本书,一条凳子,一场争论,一篇文章,一条新闻,无一不可以作为想象的对象,联想的起点,编码的原型。

在随时而作的训练中,可以不必面面俱到,按部就班,可以采用一种更为简便、更易操作的方法:找到一个起点,想象它,上、下、左、右、内、外、色、香、味、嗅、触,使用各种技巧全方位多角度地想象;然后联想到另一物,再对这个"另一物"进行想象;把两物联系起来想;然后再按同样的方式依次类推,循环推进,直到想停为止。在训练中综合运用前面讲到的各种技巧,一定会越来越纯熟,越来越巧妙。训练到一定的阶段,虽在使用技巧,却又不会属意于技巧,并未刻意使用技巧,实际却在使用,正如"大象无形,大音希声"。

- 作者: 狂龙天下 2008年03月18日, 星期二 22:30  回复(0) |  引用(0) 加入博采

伟大的中文--只能阅不能读的文章
1、赵元任《施氏食狮史》
  石室诗士施氏,嗜狮,誓食十狮。施氏时时适市视狮。十时,适十狮适市。是时,适施氏适市。氏视是十狮,恃矢势,使是十狮逝世。氏拾是十狮尸,适石室。石室湿,氏使侍拭石室。石室拭,氏始试食是十狮。食时,始识是十狮,实十石狮尸。试释是事。
  
  2、杨富森<<于瑜与余欲渔遇雨>>
  
  于瑜欲渔,遇余于寓。语余:“余欲渔于渝淤,与余渔渝欤?”
  
  余语于瑜:“余欲鬻玉,俞禹欲玉,余欲遇俞于俞寓。”
  
  余与于瑜遇俞禹于俞寓,逾俞隅,欲鬻玉于俞,遇雨,雨逾俞宇。余语于瑜:“余欲渔于渝淤,遇雨俞寓,雨逾俞宇,欲渔欤?鬻玉欤?”
  
  于瑜与余御雨于俞寓,俞鬻玉于余禹,雨愈,余与于瑜踽踽逾俞宇,渔于渝淤。
  
  3、《季姬击鸡记》
  
  
  季姬寂,集鸡,鸡即棘鸡。棘鸡饥叽,季姬及箕稷济鸡。鸡既济,跻姬笈,季姬忌,急咭鸡,鸡急,继圾几,季姬急,即籍箕击鸡,箕疾击几伎,伎即齑,鸡叽集几基,季姬急极屐击鸡,鸡既殛,季姬激,即记《季姬击鸡记》。
  
  4、《遗镒疑医》
  
  伊姨殪,遗亿镒。伊诣邑,意医姨疫,一医医伊姨。翌,亿镒遗,疑医,以议医。医以伊疑,缢,以移伊疑。伊倚椅以忆,忆以亿镒遗,以议伊医,亦缢。噫!亦异矣!
  
  5、《易姨医胰》
  
  易姨悒悒,依议诣夷医。医疑胰疫,遗意易姨倚椅,以异仪移姨胰,弋异蚁一亿,胰液溢,蚁殪,胰以医。易胰怡怡,贻医一夷衣。医衣夷衣,怡怡奕奕。噫!以蚁医胰,异矣!以夷衣贻夷医亦宜矣!
  
  6、赵元任《熙戏犀》
  
  
  西溪犀,喜嬉戏。席熙夕夕携犀徙,席熙细细习洗犀。犀吸溪,戏袭熙。席熙嘻嘻希息戏。惜犀嘶嘶喜袭熙。
  
  7、《饥鸡集矶记》
  
  唧唧鸡,鸡唧唧。几鸡挤挤集矶脊。机极疾,鸡饥极,鸡冀己技击及鲫。机既济蓟畿,鸡计疾机激几鲫。机疾极,鲫极悸,急急挤集矶级际。继即鲫迹极寂寂,继即几鸡既饥,即唧唧。
  
  8、《侄治痔》
  
  芝之稚侄郅,至智,知制纸,知织帜,芝痔炙痔,侄至芝址,知之知芷汁治痔,至芷址,执芷枝,蜘至,踯侄,执直枝掷之,蜘止,侄执芷枝至芝,芝执芷治痔,痔止。
  
  9、最后也是最变态的:
  
  《羿裔熠邑彝》
  
  羿裔熠①,邑②彝,义医,艺诣。
  
  熠姨遗一裔伊③,伊仪迤,衣旖,异奕矣。
  
  熠意④伊矣,易衣以贻伊,伊遗衣,衣异衣以意异熠,熠抑矣。
  
  伊驿邑,弋一翳⑤,弈毅⑥。毅仪奕,诣弈,衣异,意逸。毅诣伊,益伊,伊怡,已臆⑦毅矣,毅亦怡伊。
  
  翌,伊亦弈毅。毅以蜴贻伊,伊亦贻衣以毅。
  
  伊疫,呓毅,癔异矣,倚椅咿咿,毅亦咿咿。
  
  毅诣熠,意以熠,议熠医伊,熠懿⑧毅,意役毅逸。毅以熠宜伊,翼逸。
  
  熠驿邑以医伊,疑伊胰痍⑨,以蚁医伊,伊遗异,溢,伊咦。熠移伊,刈薏⑩以医,伊益矣。
  
  伊忆毅,亦呓毅矣,熠意伊毅已逸,熠意役伊。伊异,噫,缢。
  
  熠癔,亦缢。
  
  注解:
  
  ①熠:医生,据说为后羿的后裔。
  
  ②邑:以彝为邑,指居住在一个彝族聚居的地方。
  
  ③伊:绝世佳丽,仪态万方,神采奕奕。
  
  ④意:对伊有意思,指熠爱上了伊。
  
  ⑤翳:有遮蔽的地方,指伊游弋到了一个阴凉的地方。
  
  ⑥毅:逍遥不羁的浪人,善于下棋,神情坚毅,目光飘逸。
  
  ⑦臆:主观的感觉,通“意”,指对毅有好感。
  
  ⑧懿:原意为“懿旨”,此处引申为要挟,命令。
  
  ⑨胰痍:胰脏出现了疮痍。
  
  ⑩刈:割下草或者谷物一类。薏:薏米,白色,可供食用,也可入药

- 作者: 狂龙天下 2008年03月7日, 星期五 06:52  回复(0) |  引用(0) 加入博采

有钱没钱
没钱的时候,养猪
有钱的时候,养狗。
没钱的时候,在家里吃野菜
有钱的时候,在酒店吃野菜。
没钱的时候,在马路上骑自行车
有钱的时候,在客厅里骑自行车。
没钱的时候想结婚,
有钱的时候想离婚
没钱的时候老婆兼秘书,
有钱的时候秘书兼老婆
没钱的时候假装有钱,
有钱的时候假装没钱
人啊,都讲实话:
说股票是毒品,都在玩;
说金钱是罪恶,都在捞;
说美女是祸水,都想要;
说高处不胜寒,都在爬;
说烟酒伤身体,就不戒;
说天堂最美好,都不去!!!
当今社会,穷吃肉,富吃虾,领导干部吃王八;
男想高,女想瘦,
狗穿衣裳人露肉;
过去把第一次留给丈夫
现在把第一胎留给丈夫;
乡下早晨鸡叫人,
城里晚上人叫鸡;
旧社会戏子卖艺不卖身,
新社会演员卖身不卖艺
工资真的要涨了
心里更加爱党了
能给孩子奖赏了
见到老婆敢嚷了
敢尝海鲜鹅掌了
闲时能逛商场了
遇见美女心痒了
结果物价又涨了
一切都他妈白想了

- 作者: 狂龙天下 2008年02月20日, 星期三 01:34  回复(0) |  引用(0) 加入博采

07年总结?

祝大家新年快乐,2007年总结如下:

存在问题:好吃饭、好泡妞、好抽烟、好喝酒。|
分析原因:饭好吃、妞好泡、烟好抽、酒好喝。
总结经验:吃饭好、泡妞好、抽烟好、喝酒好。
整改措施:饭吃好、妞泡好、烟抽好、酒喝好。
奋斗目标:吃好饭、泡好妞、抽好烟、喝好酒。

- 作者: 狂龙天下 2008年02月20日, 星期三 01:34  回复(0) |  引用(0) 加入博采

07年总结?

祝大家新年快乐,2007年总结如下:

存在问题:好吃饭、好泡妞、好抽烟、好喝酒。|
分析原因:饭好吃、妞好泡、烟好抽、酒好喝。
总结经验:吃饭好、泡妞好、抽烟好、喝酒好。
整改措施:饭吃好、妞泡好、烟抽好、酒喝好。
奋斗目标:吃好饭、泡好妞、抽好烟、喝好酒。

- 作者: 狂龙天下 2008年02月20日, 星期三 01:34  回复(0) |  引用(0) 加入博采

Effective c++:第二版 第一章 从C转向C++
Effective c++:第二版 第一章 从C转向C++ - 编程
2004年08月07日
 

 
 

第一章 从C转向C++

对每个人来说,习惯C++需要一些时间,对于已经熟悉C的程序员来说,这个过程尤其令人苦恼。因为C是C++的子集,所有的C的技术都可以继续使用,但很多用起来又不合适。例如,C++程序员会认为指针的指针看起来很古怪,他们会问:为什么不用指针的引用来代替呢?
C是一种简单的语言。它真正提供的只有有宏、指针、结构、数组和函数。不管什么问题,C都靠宏、指针、结构、数组和函数来解决。而C++不是这样。宏、指针、结构、数组和函数当然还存在,此外还有私有和保护型成员、函数重载、缺省参数、构造和析构函数、自定义操作符、内联函数、引用、友元、模板、异常、名字空间,等等。用C++比用C具有更宽广的空间,因为设计时有更多的选择可以考虑。
在面对这么多的选择时,许多C程序员墨守成规,坚持他们的老习惯。一般来说,这也不是什么很大的罪过。但某些C的习惯有悖于C++的精神本质,他们都在下面的条款进行了阐述。

 

 

条款1:尽量用const和inline而不用#define


这个条款最好称为:“尽量用编译器而不用预处理”,因为#define经常被认为好象不是语言本身的一部分。这是问题之一。再看下面的语句:

#define ASPECT_RATIO 1.653


编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号列表中。如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指的是1.653,而不是ASPECT_RATIO。如果ASPECT_RATIO不是在你自己写的头文件中定义的,你就会奇怪1.653是从哪里来的,甚至会花时间跟踪下去。这个问题也会出现在符号调试器中,因为同样地,你所写的符号名不会出现在符号列表中。
解决这个问题的方案很简单:不用预处理宏,定义一个常量:

const double ASPECT_RATIO = 1.653;


这种方法很有效。但有两个特殊情况要注意。
首先,定义指针常量时会有点不同。因为常量定义一般是放在头文件中(许多源文件会包含它),除了指针所指的类型要定义成const外,重要的是指针也经常要定义成const。例如,要在头文件中定义一个基于char*的字符串常量,你要写两次const:

const char * const authorName = "Scott Meyers";


关于const的含义和用法,特别是和指针相关联的问题,参见条款21

另外,定义某个类(class)的常量一般也很方便,只有一点点不同。要把常量限制在类中,首先要使它成为类的成员;为了保证常量最多只有一份拷贝,还要把它定义为静态成员:
   

class GamePlayer {
private:
	static const int NUM_TURNS = 5; // constant eclaration 
	int scores[NUM_TURNS];		// use of constant
	...
};


还有一点,正如你看到的,上面的语句是NUM_TURNS的声明,而不是定义,所以你还必须在类的实现代码文件中定义类的静态成员:

const int GamePlayer::NUM_TURNS;	// mandatory definition;
		// goes in class impl.file

你不必过于担心这种小事。如果你忘了定义,链接器会提醒你。

旧一点的编译器会不接受这种语法,因为它认为类的静态成员在声明时定义初始值是非法的;而且,类内只允许初始化整数类型(如:int, bool, char 等),还只能是常量。
在上面的语法不能使用的情况下,可以在定义时赋初值:

class EngineeringConstants { // this goes in the class
private:		// header file
	static const double FUDGE_FACTOR;
	...
};
	// this goes in the class implementation file
	const double EngineeringConstants::FUDGE_FACTOR = 1.35;

大多数情况下你只要做这么多。唯一例外的是当你的类在编译时需要用到这个类的常量的情况,例如上面GamePlayer::scores数组的声明(编译过程中编译器一定要知道数组的大小)。所以,为了弥补那些(不正确地)禁止类内进行整型类常量初始化的编译器的不足,可以采用称之为“借用enum”的方法来解决。这种技术很好地利用了当需要int类型时可以使用枚举类型的原则,所以GamePlayer也可以象这样来定义:

class GamePlayer {
private:
	enum { NUM_TURNS = 5 }	// "the enum hack" — makes
	// NUM_TURNS a symbolic name 
	// for 5
	int scores[NUM_TURNS];// fine
};

除非你正在用老的编译器(即写于1995年之前),你不必借用enum。当然,知道有这种方法还是值得的,因为这种可以追溯到很久以前的时代的代码可是不常见的哟。

回到预处理的话题上来。另一个普遍的#define指令的用法是用它来实现那些看起来象函数而又不会导致函数调用的宏。典型的例子是计算两个对象的最大值:

#define max(a,b) ((a) > (b) ? (a) : (b))


这个语句有很多缺陷,光想想都让人头疼,甚至比在高峰时间到高速公路去开车还让人痛苦。
无论什么时候你写了象这样的宏,你必须记住在写宏体时对每个参数都要加上括号;否则,别人调用你的宏时如果用了表达式就会造成很大的麻烦。但是即使你象这样做了,还会有象下面这样奇怪的事发生:

int a = 5, b = 0;
max(++a, b);// a 的值增加了2次
max(++a, b+10); // a 的值只增加了1次

这种情况下,max内部发生些什么取决于它比较的是什么值!
幸运的是你不必再忍受这样愚笨的语句了。你可以用普通函数实现宏的效率,再加上可预计的行为和类型安全,这就是内联函数(见条款33):

inline int max(int a, int b) { return a > b ? a : b; }

不过这和上面的宏不大一样,因为这个版本的max只能处理int类型。但模板可以很轻巧地解决这个问题:

template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }

这个模板产生了一整套函数,每个函数拿两个可以转换成同种类型的对象进行比较然后返回较大的(常量)对象的引用。因为不知道T的类型,返回时传递引用可以提高效率(见条款22)。

顺便说一句,在你打算用模板写象max这样有用的通用函数时,先检查一下标准库(见条款49),看看他们是不是已经存在。比如说上面说的max,你会惊喜地发现你可以后人乘凉:max是C++标准库的一部分。
有了const和inline,你对预处理的需要减少了,但也不能完全没有它。抛弃#include的日子还很远,#ifdef/#ifndef在控制编译的过程中还扮演重要角色。预处理还不能退休,但你一定要计划给它经常放长假。

 

 

条款2:尽量用<iostream>而不用<stdio.h>

是的,scanf和printf很轻巧,很高效,你也早就知道怎么用它们,这我承认。但尽管他们很有用,事实上scanf和printf及其系列还可以做些改进。尤其是,他们不是类型安全的,而且没有扩展性。因为类型安全和扩展性是C++的基石,所以你也要服从这一点。另外,scanf/printf系列函数把要读写的变量和控制读写格式的信息分开来,就象古老的FORTRAN那样。是该向五十年代说诀别的时候了!

不必惊奇,scanf/printf的这些弱点正是操作符>>和<<的强项:

int i;
Rational r;// r 是个有理数

...

cin >> i >> r;
cout << i << r;

上面的代码要通过编译,>>和<<必须是可以处理Rational类型对象的重载函数(可能要通过隐式类型转换)。如果没有实现这样的函数,就会出错(处理int不用这样做,因为它是标准用法)。另外,编译器自己可以根据不同的变量类型选择操作符的不同形式,所以不必劳你去指定第一个要读写的对象是int而第二个是Rational。

另外,在传递读和写的对象时采用的语法形式相同,所以不必象scanf那样死记一些规定,比如如果没有得到指针,必须加上地址符,而如果已经得到了指针,又要确定不要加上地址符。这些完全可以交给C++编译器去做。编译器没别的什么事好做的,而你却不一样。最后要注意的是,象int这样的固定类型和象Rational这样的自定义类型在读写时方式是一样的。而你用sacnf和printf试试看!

你所写的表示有理数的类的代码可能象下面这样:

class Rational {
public:
	Rational(int numerator = 0, int denominator = 1);
	
	...
	
private:
	int n, d;// 分子,分母

friend ostream& operator<<(ostream& s, const Rational& ); }; ostream& operator<<(ostream& s, const Rational& r) { s<< r.n << '/' << r.d; return s; }

上面的代码涉及到operator<<的一些微妙(但很重要)的用法,这在本书其他地方详细讨论。例如:上面的operator<<不是成员函数(条款19解释了为什么),而且,传递给operator<<的不是Rational对象,而是定义为const的对象的引用(参见条款22)。operator>>的声明和实现也类似。

尽管我不大愿意承认,可有些情况下回到那些经过证明而且正确的老路上去还是很有意义的。第一,有些iostream的操作实现起来比相应的C stream效率要低,所以不同的选择会给你的程序有可能(虽然不一定,参见条款M16)带来很大的不同。但请牢记,这不是对所有的iostream而言,只是一些特殊的实现;参见条款M23。第二,在标准化的过程中,iostream库在底层做了很多修改(参见条款49),所以对那些要求最大可移植性的应用程序来说,会发现不同的厂商遵循标准的程度也不同。第三,iostream库的类有构造函数而<stdio.h>里的函数没有,在某些涉及到静态对象初始化顺序的时候,如果可以确认不会带来隐患,用标准C库会更简单实用。

iostream库的类和函数所提供的类型安全和可扩展性的价值远远超过你当初的想象,所以不要仅仅因为你用惯了<stdio.h>而舍弃它。毕竟,转换到iostream后,你也不会忘掉<stdio.h>。

顺便说一句,本条款的标题没有打印错;我确实说的是<iostream>而非<iostream.h>。从技术上说,其实没有<iostream.h>这样的东西——标准化委员会在简化非C标准头文件时用<iostream>取代了它。他们这样做的原因在条款49进行了解释。还必须知道的是,如果编译器同时支持 <iostream>和<iostream.h>,那头文件名的使用会很微妙。例如,如果使用了#include <iostream>, 得到的是置于名字空间std(见条款28)下的iostream库的元素;如果使用#include <iostream.h>,得到的是置于全局空间的同样的元素。在全局空间获取元素会导致名字冲突,而设计名字空间的初衷正是用来避免这种名字冲突的发生。还有,打字时<iostream>比<iostream.h>少两个字,这也是很多人用它的原因。:)

 

矩阵列选主元LU分解

//矩阵LU分解
// Matrix &mtxL 下三角阵
// Matrix &mtxU 上三角阵
// Matrix &mtxP 参照矩阵
////////////////////////////////////////////////////////////////////
BOOL Matrix::SplitLU(Matrix &mtxL, Matrix& mtxU, Matrix& mtxP)
{
 double temp;
 double dMax=0.;
 long row1;
 Matrix backup(*this);
 for (long k=0; k < r; k++)  //列选主元
 {
  for (long i=k; i<r; i++)
  {
   for (long n=0; n< k; n++)
    m[i][k] -= mtxL(i,n)*mtxU(n,k);
  }
  dMax = fabs(m[k][k]);
  row1=k;
  for (i=k+1; i<r; i++)
  {
   if(fabs(m[i][k]) > dMax)
   {
    dMax = fabs(m[i][k]);
    row1=i;
   }
  }

  if (row1 !=k)     //交换行
  {        
   SwapRow(k, row1);
   mtxP.SwapRow(k, row1);
   backup.SwapRow(k,row1);
   mtxL.SwapRow(k,row1);
  }

  for (long j=k; j < r; j++)
  {
   temp = backup.m[k][j];
//   temp = m[k][j];
   for (long n=0; n < k; n++)
   {
    temp -= mtxL(k,n)*mtxU(n,j);
   }
   mtxU.SetElement(k, j, temp);
  }

  for (i=k+1; i<r; i++)
  {
   temp=m[i][k]/mtxU(k,k);
   mtxL.SetElement(i,k,temp);
  }
 }
 for(k=0;k<r;k++)
  mtxL.SetElement(k,k,1.0);
return TRUE;
}

- 作者: 狂龙天下 2006年04月1日, 星期六 02:35  回复(0) |  引用(0) 加入博采

WORD编辑论文的几点技巧[转贴]

WORD编辑论文的几点技巧

介绍如何使用WORD来编辑你的论文由于各方面的原因,大家主要还是用Microsoft Word (以下简称Word)编辑论文。
Word在写科技论文方面虽然有一些先天不足,但却提供了非常强大的功能。如果不能充分利用这些功能,
可能经常要为不断地调整格式而烦恼。我把自己以前使用Word的经验和教训总结一下,抛块砖。
原则: 内容与表现分离
====================
一篇论文应该包括两个层次的含义:内容与表现,前者是指文章作者用来表达自己思想的文字、图片、
表格、公式及整个文章的章节段落结构等,而后者则是指论文页面大小、边距、各种字体、字号等。
相同的内容可以有不同的表现,例如一篇文章在不同的出版社出版会有不同的表现;而不同的内容可以
使用相同的表现,例如一个期刊上发表的所有文章的表现都是相同的。这两者的关系不言自明。
在排版软件普及之前,作者只需关心文章的内容,文章表现则由出版社的排版工人完成,当然他们
之间会有一定交互。Word 倡导一种所见即所得(WYSIWYG)的方式,将编辑和排版集成在一起,
使得作者在处理内容的同时就可以设置并立即看到其表现。可惜的是很多作者滥用WYSIWYG,
将内容与表现混杂在一起,花费了大量的时间在人工排版上,然而效率和效果都很差。


本文所强调的"内容与表现分离"的原则就是说文章作者只要关心文章的内容,所有与内容无关的
排版工作都交给 Word 去完成,作者只需将自己的排版意图以适当的方式告诉 Word。因为Word
不仅仅是一个编辑器,还是一个排版软件,不要只拿它当记事本或写字板用。主要建议如下。

1. 一定要使用样式,除了Word原先所提供的标题、正文等样式外,还可以自定义样式。如果
你发现自己是用选中文字然后用格式栏来设定格式的,一定要注意,想想其他地方是否需要
相同的格式,如果是的话,最好就定义一个样式。对于相同排版表现的内容一定要坚持使用
统一的样式。这样做能大大减少工作量和出错机会,如果要对排版格式(文档表现)做调整,
只需一次性修改相关样式即可。使用样式的另一个好处是可以由Word 自动生成各种目录和索引。


2. 一定不要自己敲编号,一定要使用交叉引用。如果你发现自己打了编号,一定要小心,
这极可能给你文章的修改带来无穷的后患。标题的编号可以通过设置标题样式来实现,
表格和图形的编号通过设置题注的编号来完成。在写"参见第x章、如图x所示"等字样时,
不要自己敲编号,应使用交叉引用。这样做以后,当插入或删除新的内容时,所有的编号
和引用都将自动更新,无需人力维护。并且可以自动生成图、表目录。公式的编号虽然也
可以通过题注来完成,但我另有建议,见5。

3. 一定不要自己敲空格来达到对齐的目的。只有英文单词间才会有空格,中文文档没有空格。
所有的对齐都应该利用标尺、制表位、对齐方式和段落的缩进等来进行。如果发现自己打了空格,
一定要谨慎,想想是否可以通过其他方法来避免。同理,一定不要敲回车来调整段落的间距。

4. 绘图。统计图建议使用Execel生成,框图和流程图建议使用Visio画。如果不能忍受Visio对象
复制到Word的速度,还可以试试SmardDraw,功能不比Visio弱,使用不比Visio难,速度却快多了。
如果使用Word的绘图工具绘图,最好以插入Word图片的方式,并适当使用组合。

5. 编辑数学公式建议使用 MathType5.0,其实Word集成的公式编辑器是它的3.0版。安装MathType后,
Word会增加一个菜单项,其功能一目了然。一定要使用 MathType 的自动编号和引用功能。这样首先
可以有一个良好的对齐,还可以自动更新编号。Word 正文中插入公式的一个常见问题是把上下行距都撑大了,
很不美观,这部分可以通过固定行距来修正。

6. 参考文献的编辑和管理。如果你在写论文时才想到要整理参考文献,已经太迟了,但总比论文写到
参考文献那一页时才去整理要好。应该养成看文章的同时就整理参考文献的习惯。手工整理参考文献是
很痛苦的,而且很容易出错。Word没有提供管理参考文献的功能,用插入尾注的方法也很不地道。
我建议使用 Reference Manager,它与Word集成得非常好,提供即写即引用(Cite while you write,
简称Cwyw)的功能。你所做的只是像填表格一样地输入相关信息,如篇名、作者、年份等在文章中需要
引用文献的的方插入标记,它会为你生成非常美观和专业的参考文献列表,并且对参考文献的引用编号
也是自动生成和更新的。这除了可以保持格式上的一致、规范,减少出错机会外,更可以避免正文中对
参考文献的引用和参考文献列表之间的不匹配。并且从长远来说,本次输入的参考文献信息可以在今后
重复利用,从而一劳永逸。类似软件还有Endnote和Biblioscape。Endnote优点在于可以将
文献列表导出到BibTeX格式,但功能没有Reference Manager强大。
可惜这两个软件都不支持中文,据说Biblioscape对中文支持的很好,我没有用过,就不加评论了。

7.使用节。如果希望在一片文档里得到不同的页眉、页脚、页码格式,可以插入分节符,并设置
当前节的格式与上一节不同。

上述7点都是关于排版的建议,还是要强调一遍,作者关心的重点是文章的内容,文章的表现就交给
Word去处理。如果你发现自己正在做与文章内容无关的繁琐的排版工作,一定要停下来学一下Word的
帮助,因为Word 早已提供了足够强大的功能。

我不怀疑Word的功能,但不相信可靠性和稳定性,经常遇到"所想非所见"、"所见非所得"的情况让人
非常郁闷。如果养成良好的习惯,这些情况也可以尽量避免,即使遇上,也可以将损失降低到最低限度。
建议如下:

8.使用子文档。学位论文至少要几十页,且包括大量的图片、公式、表格,比较庞大。如果所有的内容
都保存在一个文件里,打开、保存、关闭都需要很长的时间,且不保险。建议论文的每一章保存到一个子文档,
而在主控文档中设置样式。这样每个文件小了,编辑速度快,而且就算文档损坏,也只有一章的损失,
不至于全军覆灭。建议先建主控文档,从主控文档中创建子文档,个人感觉比先写子文档再插入到主控文档要好。

9.及时保存,设置自动保存,还有一有空就ctrl+s。

10.多做备份,不但Word不可靠,windows也不可靠,每天的工作都要有备份才好。注意分清版本,
不要搞混了。Word提供了版本管理的功能,将一个文档的各个版本保存到一个文件里,并提供比较合并等功能。
不过保存几个版本后文件就大得不得了,而且一个文件损坏后所有的版本都没了,个人感觉不实用。
还是多处备份吧

11.插入的图片、和公式最好单独保存到文件里另做备份。否则,哪天打文档时发现自己辛辛苦苦的
编辑的图片和公式都变成了大红叉,哭都来不及了。

其他建议:

12. 使用大纲视图写文章的提纲,调整章节顺序比较方便

13. 使用文档结构图让你方便的定位章节

14. 使用文档保护,方便文章的审阅和修改

15. Word表格的排序、公式和转换的功能也是很值得学习的

- 作者: 狂龙天下 2006年03月23日, 星期四 11:03  回复(0) |  引用(0) 加入博采

处理ListView双击事件的两种方法

CListView中鼠标双击事件为 NM_DBCLICK,生成的函数为:
void CMyList::OnDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)

处理方法有如下两种

一、使用函数的参数

双击处理函数的参数pNMHDR就带着点中项的序号:
NMLISTVIEW* pNMListView = (NMLISTVIEW*)pNMHDR;
int nItem = pNMListView->iItem;
if ( ( nItem >= 0 ) && ( nItem < m_list.GetItemCount() ) )
{
  // 双击点中处理
}

二、使用GetSelectionMark()函数

 long row;
 row = m_list.GetSelectionMark();
 if(row==-1) return;
else
{
// 双击点中处理
}

- 作者: 狂龙天下 2006年03月18日, 星期六 14:00  回复(0) |  引用(0) 加入博采

VC无闪烁刷屏技术的实现
在实现绘图的过程中,显示的图形总是会闪烁,笔者曾经被这个问题折磨了好久,通过向高手请教,搜索资料,问题基本解决,现将文档整理出来以供大家参考.

1.显示的图形为什么会闪烁
  我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。例如在OnDraw(CDC *pDC)中这样写:

pDC->MoveTo(0,0);
pDC->LineTo(100,100);


  这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见闪烁。其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪烁5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画只会闪烁一次。这个也可以试验,在OnDraw(CDC *pDC)中这样写:

for(int i=0;i<100000;i++)
{
pDC->MoveTo(0,i);
pDC->LineTo(1000,i);
}


  程序有点极端,但是能说明问题。

[被屏蔽广告]  说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉害一些,但是闪烁频率要低。那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间的差异很小所以看起来不闪。如果不信,可以在动画的每一帧中间加一张纯白的帧,不闪才怪呢。


2、如何避免闪烁
  在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC提供的背景绘制过程了。实现的方法很多:
  * 可以在窗口形成时给窗口的注册类的背景刷付NULL
  * 也可以在形成以后修改背景

static CBrush brush(RGB(255,0,0));
SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);


  * 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE

  这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。
3、如何实现双缓冲
  首先给出实现的程序,然后再解释,同样在OnDraw(CDC *pDC)中:

CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象

//随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(NULL);
//这时还不能绘图,因为没有地方画
//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);

//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));

//绘图
MemDC.MoveTo(……);
MemDC.LineTo(……);

//将内存中的图拷贝到屏幕上进行显示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();


  请参阅注释。


4、如何提高绘图的效率
  实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,例如:你在OnDraw中画了两个矩形,在一次重绘中虽然两个矩形的绘制函数都有执行,但是很有可能只有一个显示了,这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是:只有在这个区内的绘图过程才会真正有效,在区外的是无效的,即使在区外执行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC中的裁剪区了。因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。
  如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。

  具体程序大家可看以下源代码:
5、无闪烁背景图的绘制代码实现

/////////////// 无闪烁背景图绘制 //////////
//// 程序设计: icemen (温冰) 树爱兵
//////////////////////////////////////////////
BOOL CStrucView::OnEraseBkgnd(CDC* pDC)
{ int nWidth;
int nHeight;

//CView::OnEraseBkgnd(pDC);
CStrucDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect;
GetWindowRect(&rect);
nWidth = rect.Width();
nHeight= rect.Height();

CDC MemDC;
CBitmap MemBitmap;

MemDC.CreateCompatibleDC (NULL);
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);

CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));

///////////////////////////////////////////////////////
//// 以上为画背景色 //////////////
//// 以下为画背景图 //////////////
///////////////////////////////////////////////////////
GetClientRect(rect);
BITMAP bm;
CDC dcMem;
VERIFY(m_bmp.GetObject(sizeof(bm),(LPVOID)&bm));
dcMem.CreateCompatibleDC(pDC);
CBitmap *pOldBMP =( CBitmap *)dcMem.SelectObject(&m_bmp);
MemDC.BitBlt( (rect.right - bm.bmWidth)/2,
(rect.bottom - bm.bmHeight)/2,
bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(pOldBMP);
///////////////////////////////////////////////////////
//// 以上为画背景图 //////////////
///////////////////////////////////////////////////////

pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

MemBitmap.DeleteObject();
MemDC.DeleteDC();

return TRUE;
}
/////////////// 无闪烁背景图绘制 //////////
/////////////////////////////////////////////



  注:程序中m_bmp 为相应 的 StrucView.h中定义,为位图资源类

protected:
CBitmap m_bmp;


  并应加上下面段,当然,你可在任何时候加入loadBitmap 子例程,也可加入文件资源,那由得你了!

CStrucView::CStrucView()
{
VERIFY(m_bmp.LoadBitmap(IDB_BITMAP3));
}


- 作者: 狂龙天下 2006年03月1日, 星期三 01:49  回复(2) |  引用(0) 加入博采

试论军阵的斜击原理及应用 (图文) [转帖]
摘要:文章提交者:银舞飞狐 加贴在 历史风云之世界史 铁血论坛 http://bbs.tiexue.net 查看全文

- 作者: 狂龙天下 2006年02月28日, 星期二 20:35  回复(0) |  引用(0) 加入博采

VC中对输入设备的响应

                     VC中对输入设备的响应

                     Respond to the input equipment in VC

                                  陆斌   何友金

摘要    本文全面介绍了Visual C++编程语言中对输入设备响应的编程方法,并对于每一种方法给出了相应的示例。

关键词  VC  输入设备

中图分类号:TP393       文献标识码 A

                   

Abstract The ways to program the respond to input equipment in Visual C++ program language are introduced in this paper, and all the examples are presented for every input equipment.   

Keywords  VC,  input equipment

一、引言

计算机的重要功能之一就是对操作人员通过输入设备对其的控制进行响应。输入设备是指人能对计算机发出指令的设备,通用的这种设备有键盘、鼠标、游戏杆等。由于这些设备的准确使用使计算机程序具备了人-机交互的强大功能,操作者通过输入设备可以实时地控制计算机各种程序的执行,计算机通过屏幕和其它输出设备把执行情况实时地反馈给操作者。这种功能是各种控制程序必须具备的,而实现程序的各种具体编程语言中也都有其相应的实现方法。Visual C++语言是目前最流行的编程语言之一,但对其介绍的书籍资料中少有专门介绍对输入设备响应的编程方法的。因此在本文中,笔者根据自己长期从事对计算机进行人—机相互控制的编程经历,较全面地介绍一下Visual C++ 编程语言中实现对输入设备响应的方法。

二、Visual C++编程语言

Visual C++是由Microsoft 公司在Microsoft C/C++7.0基础上推出的基于Windows的集成开发系统,当时的版本为1.0。到1998年推出Visual C++6.0,这是一种能最强大的32Windows可视化开发工具。到目前Microsoft 公司已经把Visual C++的版本发展到了Visual C++.net,应用于Windows 2000以上版本的操作系统。

由于Visual C++可以完成Windows的所有高级功能,而目前Windows操作系统在计算机市场中占据着垄断的地位,因此可以说Visual C++虽然不一定是最易开发和便捷的编程语言,但无疑是功能最强大的流行编程语言。尤其是其对目前流行的虚拟现实开发中必不可少的OpenGLDirectX技术的直接支持,使得其在对底层程序功能的控制开发上更加方便灵活,在从商业应用、工业控制到娱乐游戏等各方面占据了主要的位置。作为一种Windows下的GUI式的OOP语言,Visual C++有几个明显的优点:

(1)提供了功能强大的向导工具。

(2)Developer Studio以项目工作区的形式组织文件、项目和项目配置。

(3)MFC类库支持多线程应用程序的开发。

(4)具有Windows SocketMAPI支持,可以与网络和E-mail链接。

(5)最快的集成数据库访问,允许用户建立强有力的数据库应用程序。

(6)具有强有力的Internet支持。

(7)OLE提供强有力的支持。

三、Visual C++中对输入设备的响应

    如图1所示,Visual C++(以下简称VC)中键盘和鼠标的事件响应均可以在其MFC  ClassWizard窗口中的Messages下拉的事件中找到。               

1.对键盘的输入响应

 

条款5:这里为什么要加上个"[]"

调用free将会释放stringarray1指向的内存,但内存里的string对象不会调用析构函数。如果string对象象一般情况那样,自己已经分配了内存,那这些内存将会全部丢失。相反,当对stringarray2调用delete时,数组里的每个对象都会在内存释放前调用析构函数。

既然new和delete可以这么有效地与构造函数和析构函数交互,选用它们是显然的。

把new和delete与malloc和free混在一起用也是个坏想法。对一个用new获取来的指针调用free,或者对一个用malloc获取来的指针调用delete,其后果是不可预测的。大家都知道“不可预测”的意思:它可能在开发阶段工作良好,在测试阶段工作良好,但也可能会最后在你最重要的客户的脸上爆炸。

new/delete和malloc/free的不兼容性常常会导致一些严重的复杂性问题。举个例子,<string.h>里通常有个strdup函数,它得到一个char*字符串然后返回其拷贝:

char * strdup(const char *ps);	// 返回ps所指的拷贝

在有些地方,c和c++用的是同一个strdup版本,所以函数内部是用malloc分配内存。这样的话,一些不知情的c++程序员会在调用strdup后忽视了必须对strdup返回的指针进行free操作。为了防止这一情况,有些地方会专门为c++重写strdup,并在函数内部调用了new,这就要求其调用者记得最后用delete。你可以想象,这会导致多么严重的移植性问题,因为代码中strdup以不同的形式在不同的地方之间颠来倒去。

c++程序员和c程序员一样对代码重用十分感兴趣。大家都知道,有大量基于malloc和free写成的代码构成的c库都非常值得重用。在利用这些库时,最好是你不用负责去free掉由库自己malloc的内存,并且/或者,你不用去malloc库自己会free掉的内存,这样就太好了。其实,在c++程序里使用malloc和free没有错,只要保证用malloc得到的指针用free,或者用new得到的指针最后用delete来操作就可以了。千万别马虎地把new和free或malloc和delete混起来用,那只会自找麻烦。

既然malloc和free对构造函数和析构函数一无所知,把malloc/free和new/delete混起来用又象嘈杂拥挤的晚会那样难以控制,那么,你最好就什么时候都一心一意地使用new和delete吧。
 

 

 

条款4:尽量使用c++风格的注释

旧的c注释语法在c++里还可以用,c++新发明的行尾注释语法也有其过人之处。例如下面这种情形:

if ( a > b ) {
	// int temp = a;	// swap a and b
	// a = b;
	// b = temp;
}

假设你出于某种原因要注释掉这个代码块。从软件工程的角度看,写这段代码的程序员也做得很好,他最初的代码里也写了一个注释,以解释代码在做什么。用c++形式的句法来注释掉这个程序块时,嵌在里面的最初的注释不受影响,但如果选择c风格的注释就会发生严重的错误:

if ( a > b ) {
	/*	int temp = a;  /* swap a and b */
		a = b;
		b = temp;
	*/
}

请注意嵌在代码块里的注释是怎么无意间使本来想注释掉整个代码块的注释提前结束的。

c风格的注释当然还有它存在的价值。例如,它们在c和c++编译器都要处理的头文件中是无法替代的。尽管如此,只要有可能,你最好尽量用c++风格的注释。

值得指出的是,有些老的专门为c写的预处理程序不知道处理c++风格的注释,所以象下面这种情形时,事情就不会象预想的那样:

#define light_speedp 3e8	// m/sec (in a vacuum)

对于不熟悉c++的预处理程序来说,行尾的注释竟然成为了宏的一部分!当然,正象条款1所说的那样,你无论如何也不会用预处理来定义常量的。

- 作者: 狂龙天下 2006年04月1日, 星期六 02:53  回复(0) |  引用(0) 加入博采

Messages窗口

 

                            1 MFC ClassWizard窗口               

 

VC中用KeyPress表示键盘响应的所有事件,包括OnKeyDown事件(某个键按下时)、 OnKeyUp事件(某个键按下后弹起时)和 OnKeyPress事件(当按了某个键时)。(在下面用到的Object1均代表象窗体、按钮、文本框等所有可视化的控件或在程序设计中根据需要添加的成员、类等)

OnKeyuUp事件的语法为  void Object1:: OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags );

OnKeyDown事件的语法为  void Object1:: OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags );

这里参数nChar代表的是键盘上各键的代码,是编写程序时必须要写明的,而参数nRepCnt,nFlags则可以使用默认值而不必编写。

下面说明的是在VCKeyPress事件中的nChar代码与键盘中各键的对应关系:

VK_0 VK_9 表示键盘上数字“0”到“9”键(ASCII码为0x30 - 0x39)

VK_A VK_Z 表示键盘上字母“A”到“Z”键(ASCII码为0x41 - 0x5a)

VK_ADD 表示数字键盘上的“+”键。

VK_ALT 表示键盘上 ALT”键。

VK_BACK_QUOTE 表示键盘上 `”键。

VK_BACK_SLASH 表示键盘上 \”键。

VK_BACK_SPACE 表示键盘上 BACKSPACE“键。

VK_CAPS_LOCK 表示键盘上 CAPS LOCK”键。

VK_CLOSE_BRACKET 表示键盘上 ]”键。

VK_COMMA 表示键盘上 ,”键。

VK_CONTROL 表示键盘上 CTRL”键。

VK_DECIMAL 表示数字键盘上 .”键。

VK_DELETE 表示键盘上 DELETE”键。

VK_DIVIDE 表示键盘上 /”键。

VK_DOWN 表示键盘上 “向下箭头”键。

VK_END 表示键盘上 END”键。

VK_ENTER 表示键盘上 ENTER”键。

VK_EQUALS 表示键盘上 “=”键。

VK_ESCAPE 表示键盘上 ESC”键。

VK_F1 VK_F12表示键盘上 F1”到“F12”键。

VK_HOME 表示键盘上 HOME”键。

VK_INSERT 表示键盘上 INSTERT”键。

VK_LEFT 表示键盘上 “向左箭头”键。

VK_MULTIPLY 表示键盘上 *”键。

VK_NUMPAD0 VK_NUMPAD9表示数字键盘上 0”到“9”键。

VK_OPEN_BRACKET表示键盘上 [”键。

VK_PAGE_DOWN 表示键盘上 PAGE DOWN”键。

VK_PAGE_UP 表示键盘上 PAGE UP”键。

VK_PAUSE表示键盘上 PAUSE”键。

VK_PRINTSCREEN 表示键盘上 PRINT SCREEN”键。

VK_RIGHT 表示键盘上 “向右箭头”键。

VK_SCROLL_LOCK 表示键盘上 SCROLL LOCK”键。

VK_SEMICOLON 表示键盘上 “;”键。

VK_SHIFT 表示键盘上 SHIFT”键。

VK_SPACE 表示键盘上 SPACEBAR”键。

VK_SUBTRACT表示键盘上 “-”键。

VK_TAB 表示键盘上 TAB”键。

VK_UP 表示键盘上 “向上箭头”键。

用键盘在人机交互中完成对屏幕中物体位置移动的控制功能时常会用到上、下、左、右几个方向键。下面的程序可以完成对某一可视控件Object1的位置进行控制(分别按下上、下、左、右键使其分别向上、下、左、右方向移动5个屏幕单位):

{

CWnd::OnKeyDown(UINT nChar, UINT nRecpCnt, UNIT nFlages);

Switch(nChar)

{

case VK_LEFT;

    Object1.left=Object1.left-5;      //按下左键控件左移5个单位

    break;

case VK_RIGHT;

    Object1.left=Object1.left+5;      //按下右键控件右移5个单位

case VK_UP;

    Object1.top=Object1.top-5;      //按下上键控件上移5个单位

    break;

case VK_DOWN;

    Object1.top=Object1.top+5;      //按下下键控件下移5个单位

    break;

defult:

    break;

}

2.对鼠标的响应

VC中对鼠标的响应常用的有以下事件:

    a. OnLButtonDblClk:语法为void Object1 Wnd::OnLButtonDblClk( UINT nFlags, CPoint point ){},表示控件对双击鼠标左键时的响应。

    b. OnLButtonDown:语法为void Object1 Wnd::OnLButtonDown( UINT nFlags, CPoint point ){},表示控件对按下鼠标左键时的响应。

    c. OnLButtonUp:语法为void Object1 Wnd::OnLButtonUp( UINT nFlags, CPoint point ){},表示控件对按下的鼠标左键放开后的响应。

    d. OnRButtonDblClk:语法为void Object1 Wnd::OnRButtonDblClk( UINT nFlags, CPoint point ){},表示控件对双击鼠标右键时的响应。

    e. OnRButtonDown:语法为void Object1 Wnd::OnRButtonDown( UINT nFlags, CPoint point ){},表示控件对按下鼠标右键时的响应。

f. OnRButtonUp:语法为void Object1 Wnd::OnRButtonUp( UINT nFlags, CPoint point ){},表示控件对按下的鼠标右键放开后的响应。

其中的参数nFlags用于指示按下的键的代码,它可以是下面的几个值或它们的组合:

    MK_CONTROL   表示按下CTRL

    MK_LBUTTON   表示按下鼠标左键;

    MK_MBUTTON   表示按下鼠标中键;

    MK_RBUTTON   表示按下鼠标右键;

    MK_SHIFT       表示按下 SHIFT键;

Point参数表示鼠标的光标位置相对于所在窗口的左上角的水平和垂直坐标值。

VC中用鼠标响应事件来完成人机交互中的控制功能是比较容易的。例如把一个控件Object1的位置移动到鼠标光标的位置,下面简单的程序就可完成:

void Object1::OnLButtonDown(UINT nFlags, CPoint point)

{

CPoint Position

Position = point;

Object1->left=Position.x;

Object1->top=Position.y; //按下鼠标左键后控件的水平和垂直方向的值分别与鼠标的光标位置一致

}     

3.对游戏操纵杆的响应

VC中对游戏操纵杆的响应是利用Win32 APIMCI提供的一组检测游戏操纵杆、确定操纵杆性能、位置、按钮信息的函数来实现的。这些函数主要包括:

JoyGetNumDevs  检查驱动器支持的游戏操纵杆数

JoyGetPosEx  确定游戏操纵杆是否已连接

JoyGetDevCaps  获取游戏操纵杆性能的信息

JoySetCapture  通知Windows操纵杆消息应发送到哪里以及发送的频率

JoyReleaseCpture  释放指定的游戏操纵杆

其中最常用是获取游戏操纵杆消息的函数,它的语法为joyGetPos(JoystickID,&JoyInfo)。这里的参数JoystickID,表示连接的游戏杆是ID1还是ID2JoyInfo表示的是位置信息,它有三个位置信息JoyInfo.wXposJoyInfo.wYposJoyInfo.wZpos分别代表在空间xyz方向上的位置,这些位置信息的值一般为065535,反映了游戏杆从一端拉满到另一端的最大位置变化为65535

游戏操纵杆在某些需要对目标位置进行控制的操作中是非常方便的。下面的程序可以完成利用游戏杆操纵来控制一个控件(Object1)位置的功能:

在程序的头文件中需要加入“#include”语句,

JOYINFO JoyInfo;

joyGetPos (JoystickID,&JoyInfo);            // 获取游戏杆信息        

int X,Y;

X = JoyInfo.wXpos;                       //X为游戏杆的水平方向的值

Y=JoyInfo.wYpos;                        //Y为游戏杆的垂直方向值

Object1.leftX;

Object1.topY;                         //使控件的位置与游戏杆提供的位置信息一致

JoyReleaseCapture(JoystickID);                  //释放游戏杆信息

四、结论

由于VC功能强大,又是Microsoft公司大力推广的产品,因此在编写基于Windows操作系统的应用程序方面占有不可替代的位置。尤其在工程开发中,通过编写人-机交互的程序来实现对计算机及外部设备的控制功能非常重要,而这些控制的实施主要是利用文中提到输入设备的响应,因此准确理解和使用其编程方法在工程实践中有重要的意义。本文中的例程均已在Windows98平台上的VC6.0中编译通过。

参考文献

1  乔林等,Visual C++6.0高级编程技术。中国铁道出版社,2000,北京

2  Microsoft Corporation Win32 Programmer ReferenceMicrosoft Press1995

3  武永康,Direct3D原理与API参考。清华大学出版社,2001

作者简介:陆斌,男,36岁,硕士,讲师,主要从事计算机图像处理方面的教学、科研工作。

通信地址:烟台 264001 海军航空工程学院自动控制系 电话:0535-6224311-37675E-mail: paine-l@163.net

- 作者: 狂龙天下 2006年02月27日, 星期一 18:09  回复(0) |  引用(0) 加入博采

床上竟有如此风光?

不知道能不能睡得着,呵呵

- 作者: 狂龙天下 2006年02月22日, 星期三 19:19  回复(0) |  引用(0) 加入博采

刀刃的材料
摘要:附:刀行业专有术语 查看全文

- 作者: 狂龙天下 2006年02月22日, 星期三 15:29  回复(0) |  引用(0) 加入博采

最深刻的黄段子:骆驼的故事
摘要:看似情色的荤段子实则寓意深刻。 人生天地间,都在奔跑,都在追求……很多人在追逐理想的过程中麻木了,忘记了自己的初衷,或降低了自己的要求,当更好的机遇来临时,他却错过了,因为他忘记了追求的本质是什么?自己到底在追求什么? 查看全文

- 作者: 狂龙天下 2006年01月13日, 星期五 19:23  回复(0) |  引用(0) 加入博采

全选主元高斯消去法求解线性方程组

//全选主元高斯消去法求解线性方程组Ax=b
//当前矩阵为A,mtxResult为结果x
BOOL Matrix::GaussSolve(const Matrix b,Matrix& mtxResult)
{
 if (r != b.GetRow())  //判断是否方阵
 {
  AfxMessageBox("高斯求解出错:矩阵维数不合!");
  return FALSE;

 }

 Matrix mtxA(*this); //备份
 mtxResult=b;
 Matrix temp(r,1);

 long row;
 long* colList; //保存交换的列
 double dMax=0.0;
 colList = new long[r];
 for (long k=0; k<r; k++)
  colList[k]=k;


 for (k=0; k<r-1; k++)
 {
  dMax=0.0;
  long row1;
  for (row = k; row < r; row++)  //全选主元
   for(long col=k;col<r;col++)
    if(fabs(mtxA(row,col)) > dMax)
    {
     dMax = fabs(mtxA(row,col));
     row1=row;
     colList[k]=col;
    }
  if (dMax < EPS)   //若主元为0,则其右下角子阵全为零,奇异
  {
   AfxMessageBox("高斯求解出错:矩阵奇异!");
   delete[] colList;
   return FALSE;
  }
  if (row1 !=k)    //交换行
  {
   mtxA.SwapRow(k, row1);
   mtxResult.SwapRow(k, row1);
  }
  if(colList[k]!=k)   //交换列
   mtxA.SwapCol(k,colList[k]);

  for (row=k+1; row<r; row++)  //计算第k次变换的计算系数
  {
   double temp; //系数
   temp = mtxA(row,k)/mtxA(k,k);
   for (long col=k; col<c; col++)
    mtxA.SetElement(row,col, mtxA(row,col)-temp* mtxA(k,col));
   mtxResult.SetElement(row,0,mtxResult(row,0)-temp*mtxResult(k,0));
  }
 }
 
 //回代
 for(row=r-1;row>=0;row--)
 {
  for(k=r-1;k>row;k--)
  {
   double temp;
   temp=mtxResult(row,0)-mtxA(row,k)*mtxResult(k,0);
   mtxResult.SetElement(row,0,temp);
  }
  mtxResult.SetElement(row,0,mtxResult(row,0)/mtxA(row,row));
 }
 //将原来交换的列换回来,在这里我曾经范了一个错误,就是将循环从1到c-1,而不是从c-1到1,结果完全错误!
 for(long col = c-1; col>=0;col--)
  if(colList[col]!=col)
   mtxResult.SwapRow(col,colList[col]);

 delete[] colList;
 return TRUE;
}

- 作者: 狂龙天下 2006年01月11日, 星期三 23:15  回复(0) |  引用(0) 加入博采

玩牌的最高境界!

- 作者: 狂龙天下 2006年01月11日, 星期三 00:54  回复(0) |  引用(0) 加入博采