发布新日志

  • 转眼又过了一年

    2010-12-28 16:48:18

    一眨眼,一年又划过去了。
    年底了,看看今年的成果,我都做了什么。
    还好总算忙完了2件大事:
    一是结婚大事总算办完了,二是房子也搞定了。
    明年安安心心的还钱了。
    唯一的遗憾是感觉自己有点不思上进了,需要反思,狠狠的反思。
    是安逸的生活让我太满足了吗,其实也没那样啊,房贷,那么大的一个头。
    明天最最主要的是要好好考虑工作上的进步了,今年的一个小进步只能是算一点点。
    Action最重要。
    希望明年年底再来写的时候,应该是满足的写着这一年的成就,那就太happy了。
  • 调整

    2010-03-11 14:03:51

    最近,觉得自己开始有点浮躁,静下来,静下来,保持安静.

    每个人都有自己的长处和短处,尽量帮助他人,少说闲话.

    做好自己,就够了.
  • 烦闷的春运

    2010-01-27 16:58:39

    泱泱大国, 人口那么多, 回家过个年像打仗, 买张车票比啥都难, 烦.

    想回个家都这么难, 真是的.

    请个假都还要嫌多

    我怎么就不能开心的做点自己想做的事啊.

    破春运, 开票才几分钟就喊没票了, 啥都要关系.

    没关系, 在中国活下去要多饶很多很多很多很多的弯路.

    精疲力尽!
  • 2010年的开篇之作

    2010-01-14 14:06:11

    2010年来了,要开始进行新的一年的计划了,好的开始是成功的一半。

    每天都想记下一些什么,却总总是那寥寥几语,毫无以前对生活升华的意识了,是被生活所磨灭,天天惦记着房价,怎么理财…… 麻木的不知道多说谢谢和对不起,麻木的面无表情的对待同一屋檐下的朋友,赶不上回家孝敬父母,和自己的好友相聚。即使同一城市的好友也难开心聚几次;把生活弄的跟枯木似的。哎, 在大城市,需求太多了,生活太累了。

    顺便用以下别人帖子里蜗居的经典话:
    “那天,陪妈妈去逛街,其实我们都不用走,那个人流就推着我们向前走。我想不走都不行,想停下都不行,我当时就笑了,我说这就是我们的生活,来不及细想, 没有决断,就这样懵懵懂懂的被人推着往前走,而我青春年少时候的理想上哪去了?我的理想就被这匆匆的人流推得无影无踪。”

    其实,在生活的同时还是需要思索的,不然我们都在不知不觉中被生活了。

    永远都跟在生活的后面追赶,被生活牵着鼻子走;我觉得这是生活环境所导致的,长期生活在被生活的环境中,不免也会随波逐流,不然则会被异类把。

    新的一年还是给自己定下了新的理财计划,还是要买房,旅游,孝敬父母及自己的生活需求,所有的这些都够我们想的了。
    难,难啊


  • 针对Excel表格文件操作的编程实现【转】

    2008-11-04 18:23:11


    简介
    通过本文及配套示例源码你可以更加灵活的控制Excel表格文件,其中包括创建新Excel文件、写入表格数据、读取表格数据(包括对原建Excel文件自已手工添加的行、列数据的准确读取),删除已有Excel表格,对表格中指定行、列、单元格进行查询、插入、替换等操作,同时还可以将生成的Excel文件转换为按指定分隔符分隔的其它文本格式的文件。下面是把此方法用VC6编写的示例程序运行效果:



    基本思路
    基础实现方法同上篇文章《直接通过ODBC读、写Excel表格文件》相同,都是通过ODBC来把Excel表格文件当成数据库文件来进行读、写等操作,所以在Excel表格文件中写入的行头名必须是唯一的(不要重名,相当于数据库中的ID值)。本文中对Excel文件的操作都被封装进一个类CSpreadSheet中,通过它我们可以非常简便的实现各种Excel表格数据操作,并且可以对该类进行扩充来满足自己的需求。

    具体实现

    一、 包含Excel文件操作类头文件

    #include "CSpreadSheet.h"
    二、 新建Excel文件,并写入默认数据
    // 新建Excel文件名及路径,TestSheet为内部表名
    CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    CStringArray sampleArray, testRow;
    	
    SS.BeginTransaction();
    	
    // 加入标题
    sampleArray.RemoveAll();
    sampleArray.Add("姓名");
    sampleArray.Add("年龄");
    SS.AddHeaders(sampleArray);
    
    // 加入数据
    CString strName[] = {"徐景周","徐志慧","郭徽","牛英俊","朱小鹏"};
    CString strAge[]  = {"27","23","28","27","26"};
    for(int i = 0; i < sizeof(strName)/sizeof(CString); i++)
    {
    	sampleArray.RemoveAll();
    	sampleArray.Add(strName[i]);
    	sampleArray.Add(strAge[i]);
    	SS.AddRow(sampleArray);
    }
    	
    SS.Commit();

    三、 读取Excel文件数据
    CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    CStringArray Rows, Column;
    
    //清空列表框
    m_AccessList.ResetContent();
    for (int i = 1; i <= SS.GetTotalRows(); i++)
    {
    	// 读取一行
    	SS.ReadRow(Rows, i);
    	CString strContents = "";
    	for (int j = 1; j <= Rows.GetSize(); j++)
    	{
    		if(j == 1)
    			strContents = Rows.GetAt(j-1);
    		else
    			strContents = strContents +  " --> " + Rows.GetAt(j-1);
    	}
    
    	m_AccessList.AddString(strContents);
    }

    四、 对已存在Excel表格数据进行添加、插入、替换操作
    // 初始化测试行数据,进行添加、插入及替换数据操作演示
    for (int k = 1; k <= 2; k++)
    {
    	testRow.Add("Test");
    }
    	
    SS.AddRow(testRow);		// 添加到尾部
    SS.AddRow(testRow, 2);		// 插入新行到第二行
    SS.AddRow(testRow, 6, true);	// 替换原第四行来新的内容
    SS.AddCell("徐景周", 1,2);    // 添加(不存在)或替换(存在)第二行,第一列单元格内容
    
    SS.Commit();	
    五、 对已存在Excel表格数据进行行、列、单元格查询
    void CExcelAccessDlg::OnQuery() 
    {
    	CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    	CStringArray Rows, Column;
    	CString tempString = "";
    
    	UpdateData();
    
    	if(m_strRow == "" && m_strColumn == "")         // 查询为空
    	{
    		AfxMessageBox("行号、列号不能同时为空!");
    		return;
    	}    
    	else if(m_strRow == "" && m_strColumn != "")    // 查询指定列数据
    	{
    		int iColumn = atoi(m_strColumn);
    		int iCols = SS.GetTotalColumns();
    		if(iColumn > iCols)	// 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总列数为: %d, ", iCols);
    			AfxMessageBox(str + " 查询列数大于Excel表中总列数,请重新输入!");
    			return;
    		}
    
    		// 读取一列数据,并按行读出
    		if(!SS.ReadColumn(Column, iColumn))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString tmpStr;
    		for (int i = 0; i < Column.GetSize(); i++)
    		{
    			tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", i+1,iColumn,Column.GetAt(i));
    			tempString += tmpStr;
    		}
    		
    		AfxMessageBox(tempString);
    	}
    	else if(m_strRow != "" && m_strColumn == "")     // 查询指定行数数据
    	{
    		int iRow = atoi(m_strRow);
    		int iRows = SS.GetTotalRows();
    		
    		if(iRow > iRows)	// 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总行数为: %d, ", iRows);
    			AfxMessageBox(str + " 查询行数大于Excel表中总行数,请重新输入!");
    			return;
    		}
    
    		// 读取指定行数据
    		if(!SS.ReadRow(Rows, iRow))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString tmpStr;
    		for (int i = 0; i < Rows.GetSize(); i++)
    		{
    			tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", iRow, i+1, Rows.GetAt(i));
    			tempString += tmpStr;
    		}
    
    		AfxMessageBox(tempString);
    	}
    	else if(m_strRow != "" && m_strColumn != "")     // 查询指定单元格数据
    	{
    		int iRow = atoi(m_strRow), iColumn = atoi(m_strColumn);
    		int iRows = SS.GetTotalRows(), iCols = SS.GetTotalColumns(); 
    		
    		if(iColumn > iCols)             // 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总列数为: %d, ", iCols);
    			AfxMessageBox(str + " 查询列数大于Excel表中总列数,请重新输入!");
    			return;
    		}
    		else if(iRow > iRows)
    		{
    			CString str;
    			str.Format("表中总行数为: %d, ", iRows);
    			AfxMessageBox(str + " 查询行数大于Excel表中总行数,请重新输入!");
    			return;
    		}
    
    		// 读取指定行、列单元格数据
    		if(!SS.ReadCell(tempString, iColumn, iRow))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString str;
    		str.Format("行号: %d, 列号: %d ,内容: %s", iRow,iColumn,tempString);
    		AfxMessageBox(str);
    	}
    	
    }

    六、 将存在的Excel转换另存为指定分隔的文本文件
    // 将原Excel文件转换为用分号分隔的文本,并另存为同名文本文件
    SS.Convert(";"); 
    七、 删除Excel中表格
    SS. DeleteSheet();            // 删除Excel文件中所有表格
    SS. DeleteSheet(" TestSheet ");  // 删除Excel中TextSheet表格
    
    八、 获取Excel中总行数、总列数、当前行
    int iCols = SS.GetTotalColumns();   // 总列数
    int iRows = SS.GetTotalRows();    // 总行数
    int iCurRow = SS.GetCurrentRow(); // 当前所在行号
    
    九、 获取行头数据
    CStringArray rowHeader;
    SS.GetFieldNames(rowHeader);
    CString tmpStr;
    for (int i = 0; i < rowHeader.GetSize(); i++)
    {
    		tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", 1, i+1, rowHeader.GetAt(i));
    		tempString += tmpStr;
    }
    AfxMessageBox(tempString);

    最后,如果想知道详细实现细节的话,可以在下载示例源码后,仔细查看源码既可(内有详细注释)。

    参考文献:
    直接通过ODBC读、写Excel表格文件 – 徐景周(译)
    A Class to Read and Write to Excel and Text Delimited Spreadsheet – Yap Chun Wei

  • silktest q&a[转]

    2008-11-04 18:21:04

    Q1: silktest是什么
    A1:silktest
    是一个segue公司的一个自动化测试工具。
     
    Q2:Segue
    的测试方法论是什么?
    A2:Segue
    的测试方法论是一个包括六个阶段的测试流程:
    1.
    计划。决定测试策略并且定义测试需求。
    2.
    捕捉。将你的应用程序中的GUI对象对象化,并且建立一个运行测试的框架。
    3.
    创建测试。创建自动的,可重用的测试。利用录制和编程手段建立用Segue4Test语言编写的测试脚本。
    4.
    运行测试。选择某些测试并且针对需要测试的软件执行它们。
    5.
    报告。分析测试结果并且生成缺陷报告。
    6.
    追踪。在待测软件中追踪缺陷并且执行回归测试。
     
    Q3:silktest host
    是什么?
    A3:Silktest host
    是一个用来管理和执行测试脚本的组件。Silktest host通常运行在和待测软件不同的机器上。
     
    Q4:silktest agent
    是什么?
    A4:Silktest agent
    是从silktest host接收测试指令,并且和待测软件交互的组件。它通常和待测软件运行在同一机器上。
     
     
    Q5: 4Test
    是什么
    A5:4Test
    silktest用来组成测试脚本执行自动测试的一种测试脚本语言。4Test是面向对象的第四代语言,它由三部分组成:
    一个可以使testcase可以和GUI对象交互的强壮的面向对象的类库。
    一组用来创建记录testcase的结构和逻辑的申明,操作符和数据类型。
    一个用来支持普通支持任务的内建函数库。
     
    Q6:DOM
    浏览器扩展是什么?
    A6:
    文档对象模型(DOM)浏览器扩展是为了测试Web程序的一个silktest附加组件。DOM浏览器扩展直接和Wed浏览器联系来识别,分类处理Web页面上的对象。该组件并非是使用可视化模式识别技术来进行这些对象的识别,而是通过处理实际的HTML代码来实现的。
     
    Q7:VO
    浏览器扩展是什么?
    A7:
    虚拟对象(VO)浏览器扩展是一个为了测试Web程序的silktest附加组件。VO浏览器扩展使用模式识别技术来识别浏览器中呈现出来的对象。VO扩展以页面呈现出来的样子来看待页面而不是通过识别html标记。而且VO扩展以页面中的对象例如:链接,表格,图片和附加在它们上的操作来看待它们,而不考虑它们背后所用的技术。
     
    Q8:6.0
    版本的脚本运用到6.5甚至更高版本的系统上会出现问题么?
    A8:
    从低版本到高版本的迁移不会导致问题,不过这只是一个一般性的声明,而并非适合于所有的情况。我曾经遇到6.5版本的脚本无法在7.0版本上运行的情况,原因是一些识别模式已经被改变了。而且在一些情况下,最后处于不同路径下的脚本竟然执行了基于版本的相同的操作。
    Ps
    :从6.06.5倒没有遇到任何问题。
     
    Q8.:
    近我在使用silktest V3v的是否遇到一个问题,当我记录选择菜单项时,比如:Product.File.Exit.Pick()但是当我回放时,它能够选择File菜单,但是无法选择Exit项。File菜单没有被下拉显示出来,仅仅是高亮了。这个应用是用vc开发并且运行在NT4的系统上的。
    虽然我可以使用菜单的快捷键绕过这个问题,但是在某些testcase里面我更希望能模拟鼠标进行上面的操作,有什么好的办法么?
    A8:
    我也曾经遇到这样的问题,这是由于焦点问题而产生的。首先,我们需要理解QAP/Silktest选择菜单项的原理。它并不是真正的使用鼠标,而是用键盘来高亮菜单栏,然后使用箭头选择想要操作的菜单项。试试下面这个方法:首先将你的应用置于菜单被选中之前的状态,然后手工点击F10键或者Alt键看是否菜单被高亮了并且允许你使用箭头选择菜单项。我猜可能是由于某个childwin或者dialogbox真正拥有了焦点,从而没有把键盘事件传递给mainwin。如果是这种情况,你需要向开发人员说明他们必须解决这个问题,这样你才能够进行自动测试。一个小的技巧是设置一个YourProduct.Click()函数,强制将焦点交给mainwin,然后再进行菜单的选择。
     
    Q9:silktest project
    是什么?
    A9:
    一个silktest project是一个包含测试项目信息的文件集合。
     
    Q10
    如何建立一个新的silktest项目?
    A10:
    运行
    silktest
    选择基本工作流栏

    点击打开项目。
    选择新建项目。
    在新建项目对话框中双击建立项目的图标。
    在新建项目对话框中输入你的项目名字和你的项目描述。
    点击OK
    Silktest
    将会在silktest项目目录下面新建一个子目录,然后在该子目录下存储新项目相关的所有文件。

    Q11:silktest中有没有计算web页面上单词数量的函数?
    A11
    :你可以使用Clipboard函数。使用Ctrl+aCtrl+c,然后解析stringlist.

    Q12:silktesttestplan是什么?
    A12:silktest
    testplan是一个提供软件测试过程框架的大纲,它为组织和管理你的测试需求提供了控制的重点。一个testplan由两个不同的部分组成:一个是大纲,它是测试需求的格式化描述,另一个是声明,被用来连接silktesttestplan脚本和实现测试需求的testcase

    Q13:创建新的test脚本的最佳途径是什么?
    A13:
    在自动测试中,建立测试脚本包括最基本的两个步骤:
    1
    .为所有的testcase创建测试数据。
    2
    .为自动测试编写脚本。
    第一步是分析了你的testcase需要哪些数据后的结果,这些数据被收集,脚本编写出来以后,测试数据才算准备完全了。
    第二步是测试用例自动执行的基本步骤。


    Q14
    :如何得到buttoncaption?
    A14:
    答案1:使用GetCaption ()方法。
    答案2:还可以使用sCaption属性。


    Q14:
    如何关闭不需要的窗口?
    A14:
    你是否意味着那些原窗口(定购状态)以外的一个或者多个浏览器窗口(定购请求)?
    Answer1:
    如果定购请求窗口是弹出式窗口,下面的代码将会关闭一个弹出式的激活状态的窗口。
    [-] !(if Browser.ComboBox("#1").exists())
    [ ] Browser.SetActive()
    [ ] Browser.typekeys("")
    Answer2:
    如果订购请求窗口是一个非弹出式浏览器窗口,你可以使用下面的代码关闭不需要的的浏览器。
    Order_Status.SetActive()
    Browser.CloseOthers()

    Q15:testplan文件里面的文本行有哪些类型?
    A15:
    一个testplan文件包括一些文本行,在其中有5种不同的文本行。
    1.
    注释-绿色标识,提供注释信息。
    2.
    组描述-黑色标识,提供一组测试的描述。Testplan里面的测试可以被组成多个级别的组。
    3.
    测试描述- 蓝色标识,提供单个测试的描述
    4.
    测试计划语句-暗红色标识,提供到testcase,test data,下级testplan或者引用文件的相关链接。
    5.
    打开下级testplan文件的标记-洋红色表示,提供一个到下级testplan的相关链接。


    Q16:testplan
    的属性是什么?
    A16
    Testplan的属性是用户定义属性,它和测试组的描述相关联,或者和某个测试的描述相关联。你可以通过不同的属性值来搜索,标识和报告testcase


    Q17:
    默认的testplan的属性是什么?
    A17:silktest
    提供3种预定义的默认属性:
    1.
    种类: testcase或者testcase组的类型。例如,你可以使用这个属性将你的testcase组分为boudary value testsnavagation tests等种类。
    2.
    组件:被测试的应用的模块名。
    3.
    开发者:开发testcase或者testcase组的QA工程师的名字。

    Q:如何维护恢复系统?
    A
    :在你的TestCaseExit()函数里面,你可以使用如下的代码:
    If condition == 1
    do this
    If condition == 2
    do that


    Q18:
    如何定义一个新的testplan属性?
    A18:
    1.
    确定你的测试项目是打开的。
    2.
    点击Testplan/Define Attributes菜单,定义属性的对话框会被打开,你将看到3个预先定义好的默认属性Category, Component, Developer.
    3.
    点击新建按钮,新属性对话框将被打开。
    4.
    输入你的新属性,例如:Level,用来表示testcase的复杂程度。
    5.
    选择属性的类型:Normal, Edit, 或者Set.
    6.
    点击确定。

     Q19:disabletextfield中得到文本。Silktest不能够识别disable的对象,我如何能解决这个问题。我有一个基于web的应用,在一个页面中有一个radio button。选择这个radio button可以打开一个applet窗口。现在如果我希望得到该窗口的定义,它一样会失败。Silktest被正确地配置成可识别基于javac\s结构应用。如何解决这个问题呢?
    A19:
    如果你希望从一个disabled textfield上得到数据,你首先需要disable Agent选项"OPT_VERIFY_ENABLED" 然后你可以使用GetText。其步骤是:
    Agent.SetOptions("OPT_VERIFY_ENABLED", false)
    Print(TextField.GetText())
    然后来回答你的下一个问题,答案是同样的,disable你的Agent选项,步骤如下:

    1.
    在选项菜单中,点击Agent菜单项。
    2.
    Agent窗口,点击Verification标签。
    3.
    取消所有的选项,保留最后一项,(verification of application ready)
    4.
    点击确定。

    Q20.当调用java应用后(silktest可以启动我的java应用),然后将出现登录屏木,但是silktest报一个JavaMainWin无法找到的错误。为什么?现在我无法正确启动该程序调用然后执行另外一段代码,例如输入用户名和密码登录进应用。
    A20:
    答案1:
    在调用一个应用之后,silktest将一直等待找到这个应用。在这样情况下,应用是你的java窗口。有时会出现在调用之后,silktest无法识别出,但是如果你手动调用,它却能够正常工作。
    解决方法:
    声明一个窗口变量使用start方法。这时你可以使用下面的代码:
    JavaAppWindow.Invoke ()替换为
    Window MyJavaApp
    MyJavaApp.Start ("path of exe or batch file to invoke the application")
    sleep (x) (x -->
    合适的值)

    答案2
    window MainWin MyWin //
    声明一个全局变量
    main ()
    try ()
    testcase try () appstate none
    MyWin.Start(sPath)

    答案3
    当你用start命令作为JavaMainWin的一部分时,保证你的类路径是独立运行的-silktest以外,这样它将会正常工作。

    Q21:如何给testcase的属性赋值?
    A21

    1.
    确定你的testplan处于打开状态。
    2.
    点击你准备赋属性值的testcase
    3.
    点击TestPlan/detail菜单,testplan详细对话框会出现。
    4.
    点击test attribute标签。
    5.
    点击组件域,下拉列表会出现所有组件的可选值。
    6.
    选择下拉列表中的值。
    7.
    点击确定。

    Q22:关于关闭孩子窗口
    A22:
    答案1
    1.
    识别进程句柄
    2.
    关闭它的第一个孩子然后关闭MainWindow

    答案2
    Integer HWnd=Browser.GetHandle() ///
    在孩子窗口弹出之前
    ....
    下面是你的窗口
    While Browser2.Exists()
    {
    If Browser.GetHandle()!=HWnd
    Browser.Close()
    Else
    Browser2.SetActive()
    }
    你也可以在上面的代码中使用窗口的catpion

    答案3
    我想用来识别双亲和孩子的tag不唯一,这正是为什么双亲会被关闭的原因。可以试着使window ID唯一然后关闭页面。第一个激活孩子,然后关闭应该可以管用。

    Q23:如何建立一个test frame
    A23:
    1.
    确定你的浏览器被激活并且打开了你的web应用的首页。不要最小话web页窗口。
    2.
    确定你的测试项目处于打开状态。
    3.
    点击File/New菜单,一个新的对话框将会出现。
    4.
    查看(909) 评论(0) 收藏 分享 管理

  • 【转】在silktest用excel实现测试数据驱动

    2008-11-04 17:28:34

     

    2007-12-26 10:35:10 / 个人分类:SilkTest

    [-] type DB_person is record

                    [ ] string name

                    [ ] integer age

                     

    [-] testcase testselect()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] DB_person personS

                    [ ] STRING sConnectStringSelect = "DSN=Segue DDA Excel;DBQ={sResultFile}"

                    [ ] HANDLE hDBSelect = DB_Connect (sConnectStringSelect)

                    [ ] STRING sSQLSelect = "select name,age from [person$]"

                    [ ] HANDLE hBufferSelect = DB_ExecuteSQL(hDBSelect, sSQLSelect)

                    [-] while(DB_FetchNext(hBufferSelect,person))

                                    [ ] print("Name:{person.name};Age:{person.age}")

                    [ ] DB_FinishSql (hBufferSelect)

                    [ ] DB_Disconnect (hDBSelect)

     

     [-] testcase testinsert()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] STRING sConnectStringInsert = "DSN=Segue DDA Excel;ReadOnly=False;DBQ={sResultFile}"

                    [ ] HANDLE hDBInsert = DB_Connect (sConnectStringInsert)

                    [ ] STRING sSQLInsert = "insert into [person$] (Name,Age) values ('Zhao Liu',11);"

                    [ ] HANDLE hBufferInsert = DB_ExecuteSQL(hDBInsert, sSQLInsert)

                    [ ] DB_FinishSql (hBufferInsert)

                    [ ] DB_Disconnect (hDBInsert)

                     

    [-] testcase testupdate()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] STRING sConnectStringUpdate = "DSN=Segue DDA Excel;ReadOnly=False;DBQ={sResultFile}"

                    [ ] HANDLE hDBUpdate = DB_Connect (sConnectStringUpdate)

                    [ ] STRING sSQLUpdate = "update  [person$]  set name ='51testing' where name='Zhao Liu'"

                    [ ] HANDLE hBufferUpdate = DB_ExecuteSQL(hDBUpdate, sSQLUpdate)

                    [ ] DB_FinishSql (hBufferUpdate)

                    [ ] DB_Disconnect (hDBUpdate)

  • 自我解析--考试篇

    2007-09-11 01:29:08

     实在是不知道什么原因,为什么每次考试结果是那么的出乎我的意料,是我不行吗?说实话,我真的不信,每堂课我都听的懂并不觉得困难和跟不上,但事实却总是让人无法理解。或者,其实也不是那么的难以理解吧,矛盾
     
    一直纠结每次的考试都是在及格边缘的我,或许真的对知识的掌握不是那么熟练,付出的努力和收获都是成正比的,即使我真的觉得自己付出不少了(至少比以前要认真很多),但相对于别人来说,可能真的微不足道。
     
    仔细分析:原因有几点
    一、没有按时完成每次的作业
    二、只学到了老师讲的一些表面知识,没有深入分析其缘由及如果变化后的结果
    三、没有整理老师给的课余资料,也没有看过
    四、没有好好复习,也是只是复习了表面的东西,对不懂的问题没有深入搞懂
     
    总之,把这次培训当成了任务,没有将兴趣培养出来,只是完成任务式的学习,导致总觉得学习任务很重很累,没时间完成作业。时间上没有调配好,主次不分,以致娱乐学习两误。
     
    针对以上几点,应采取措施:
    一、对老师交代的作业一定要按时按质按量的完成
    二、对每次学完后要对当天的课程回顾并解决上课没懂的地方,加深理解
    三、老师给的课余资料都是学习的辅助资料,一定要抽时间看
    四、复习,要深入,对不懂的地方一定要搞懂,不可以轻易放过,这也是对自己的负责
     
    最后,要从学习中找到乐趣,最后的一个月了,要好好把握,再不把握,实在太丢人了
     
    这段学校期间,真的学到了很多,对自己的缺点有了新的认识
    加油加油
    AZAZA!!!!!!
    FIGHT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  • sprintf的用法

    2007-08-30 16:49:21

    最近不知道sprintf的用法,特意查上,收藏,一起共享

    在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望。由于sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。这也导致sprintf 比printf 有用得多。

    sprintf 是个变参函数,定义如下:
    int sprintf( char *buffer, const char *format [, argument] ... );
    除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:
    格式化字符串上。


    printf 和sprintf 都使用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。

    格式化数字字符串
    sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf 在大多数场合可以替代
    itoa。

    如:
    //把整数123 打印成一个字符串保存在s 中。
    sprintf(s, "%d", 123); //产生"123"
    可以指定宽度,不足的左边补空格:
    sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"
    当然也可以左对齐:
    sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"
    也可以按照16 进制打印:
    sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐
    sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐

    这样,一个整数的16 进制字符串就很容易得到,但我们在打印16 进制内容时,通常想要一种左边补0 的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。
    sprintf(s, "%08X", 4567); //产生:"000011D7"
    上面以”%d”进行的10 进制打印同样也可以使用这种左边补0 的方式。


    这里要注意一个符号扩展的问题:比如,假如我们想打印短整数(short)-1 的内存16 进制表示形式,在Win32 平台上,一个short 型占2 个字节,所以我们自然希望用4 个16 进制数字来打印它:
    short si = -1;
    sprintf(s, "%04X", si);
    产生“FFFFFFFF”,怎么回事?因为spritnf 是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。

    如果你想看si 的本来面目,那么就应该让编译器做0 扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):
    sprintf(s, "%04X", (unsigned short)si);
    就可以了。或者:
    unsigned short si = -1;
    sprintf(s, "%04X", si);


    sprintf 和printf 还可以按8 进制打印整数字符串,使用”%o”。注意8 进制和16 进制都不会打
    印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16 进制或8 进制表示。

    控制浮点数打印格式
    浮点数的打印和格式控制是sprintf 的又一大常用功能,浮点数使用格式符”%f”控制,默认保
    留小数点后6 位数字,比如:
    sprintf(s, "%f", 3.1415926); //产生"3.141593"
    但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf”格式,其中m 表
    示打印的宽度,n 表示小数点后的位数。比如:
    sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"
    sprintf(s, "%-10.3f", 3.1415626); //产生:"3.142 "
    sprintf(s, "%.3f", 3.1415626); //不指定总宽度,产生:"3.142"

    注意一个问题,你猜
    int i = 100;
    sprintf(s, "%.2f", i);
    会打出什么东东来?“100.00”?对吗?自己试试就知道了,同时也试试下面这个:
    sprintf(s, "%.2f", (double)i);
    第一个打出来的肯定不是正确结果,原因跟前面提到的一样,参数压栈时调用者并不知道跟i相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数,于是可怜的保存整数i 的那4 个字节就被不由分说地强行作为浮点数格式来解释了,整个乱套了。不过,如果有人有兴趣使用手工编码一个浮点数,那么倒可以使用这种方法来检验一下你手工编排的结果是否正确。

    字符/Ascii 码对照
    我们知道,在C/C++语言中,char 也是一种普通的scalable 类型,除了字长之外,它与short,
    int,long 这些类型没有本质区别,只不过被大家习惯用来表示字符和字符串而已。(或许当年该把
    这个类型叫做“byte”,然后现在就可以根据实际情况,使用byte 或short 来把char 通过typedef 定义出来,这样更合适些)于是,使用”%d”或者”%x”打印一个字符,便能得出它的10 进制或16 进制的ASCII 码;反过来,使用”%c”打印一个整数,便可以看到它所对应的ASCII 字符。以下程序段把所有可见字符的ASCII 码对照表打印到屏幕上(这里采用printf,注意”#”与”%X”合用时自动为16 进制数增加”0X”前缀):
    for(int i = 32; i < 127; i++) {
    printf("[ %c ]: %3d 0x%#04X\n", i, i, i);
    }


    连接字符串
    sprintf 的格式控制串中既然可以插入各种东西,并最终把它们“连成一串”,自然也就能够连
    接字符串,从而在许多场合可以替代strcat,但sprintf 能够一次连接多个字符串(自然也可以同时
    在它们中间插入别的内容,总之非常灵活)。比如:
    char* who = "I";
    char* whom = "CSDN";
    sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. "
    strcat 只能连接字符串(一段以’\0’结尾的字符数组或叫做字符缓冲,null-terminated-string),但有时我们有两段字符缓冲区,他们并不是以’\0’结尾。比如许多从第三方库函数中返回的字符数组,从硬件或者网络传输中读进来的字符流,它们未必每一段字符序列后面都有个相应的’\0’来结尾。如果直接连接,不管是sprintf 还是strcat 肯定会导致非法内存操作,而strncat 也至少要求第一个参数是个null-terminated-string,那该怎么办呢?我们自然会想起前面介绍打印整数和浮点数时可以指定宽度,字符串也一样的。比如:
    char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
    char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'};
    如果:
    sprintf(s, "%s%s", a1, a2); //Don't do that!
    十有八九要出问题了。是否可以改成:
    sprintf(s, "%7s%7s", a1, a2);
    也没好到哪儿去,正确的应该是:
    sprintf(s, "%.7s%.7s", a1, a2);//产生:"ABCDEFGHIJKLMN"
    这可以类比打印浮点数的”%m.nf”,在”%m.ns”中,m 表示占用宽度(字符串长度不足时补空格,超出了则按照实际宽度打印),n 才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m 没什么大用,还是点号后面的n 用的多。自然,也可以前后都只取部分字符:
    sprintf(s, "%.6s%.5s", a1, a2);//产生:"ABCDEFHIJKL"
    在许多时候,我们或许还希望这些格式控制符中用以指定长度信息的数字是动态的,而不是静态指定的,因为许多时候,程序要到运行时才会清楚到底需要取字符数组中的几个字符,这种动态的宽度/精度设置功能在sprintf 的实现中也被考虑到了,sprintf 采用”*”来占用一个本来需要一个指定宽度或精度的常数数字的位置,同样,而实际的宽度或精度就可以和其它被打印的变量一样被提供出来,于是,上面的例子可以变成:
    sprintf(s, "%.*s%.*s", 7, a1, 7, a2);
    或者:
    sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);
    实际上,前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值,比如:
    sprintf(s, "%-*d", 4, 'A'); //产生"65 "
    sprintf(s, "%#0*X", 8, 128); //产生"0X000080","#"产生0X
    sprintf(s, "%*.*f", 10, 2, 3.1415926); //产生" 3.14"


    打印地址信息
    有时调试程序时,我们可能想查看某些变量或者成员的地址,由于地址或者指针也不过是个32 位的数,你完全可以使用打印无符号整数的”%u”把他们打印出来:
    sprintf(s, "%u", &i);
    不过通常人们还是喜欢使用16 进制而不是10 进制来显示一个地址:
    sprintf(s, "%08X", &i);
    然而,这些都是间接的方法,对于地址打印,sprintf 提供了专门的”%p”:
    sprintf(s, "%p", &i);
    我觉得它实际上就相当于:
    sprintf(s, "%0*x", 2 * sizeof(void *), &i);
    利用sprintf 的返回值
    较少有人注意printf/sprintf 函数的返回值,但有时它却是有用的,spritnf 返回了本次函数调用
    最终打印到字符缓冲区中的字符数目。也就是说每当一次sprinf 调用结束以后,你无须再调用一次
    strlen 便已经知道了结果字符串的长度。如:
    int len = sprintf(s, "%d", i);
    对于正整数来说,len 便等于整数i 的10 进制位数。
    下面的是个完整的例子,产生10 个[0, 100)之间的随机数,并将他们打印到一个字符数组s 中,
    以逗号分隔开。
    #include
    #include
    #include
    int main() {
    srand(time(0));
    char s[64];
    int ōffset = 0;
    for(int i = 0; i < 10; i++) {
    offset += sprintf(s + offset, "%d,", rand() % 100);
    }
    s[offset - 1] = '\n';//将最后一个逗号换成换行符。
    printf(s);
    return 0;
    }
    设想当你从数据库中取出一条记录,然后希望把他们的各个字段按照某种规则连接成一个字
    符串时,就可以使用这种方法,从理论上讲,他应该比不断的strcat 效率高,因为strcat 每次调用
    都需要先找到最后的那个’\0’的位置,而在上面给出的例子中,我们每次都利用sprintf 返回值把这
    个位置直接记下来了。


    使用sprintf 的常见问题
    sprintf 是个变参函数,使用时经常出问题,而且只要出问题通常就是能导致程序崩溃的内存访
    问错误,但好在由sprintf 误用导致的问题虽然严重,却很容易找出,无非就是那么几种情况,通
    常用眼睛再把出错的代码多看几眼就看出来了。


    ?? 缓冲区溢出
    第一个参数的长度太短了,没的说,给个大点的地方吧。当然也可能是后面的参数的问
    题,建议变参对应一定要细心,而打印字符串时,尽量使用”%.ns”的形式指定最大字符数。


    ?? 忘记了第一个参数
    低级得不能再低级问题,用printf 用得太惯了。//偶就常犯。:。(


    ?? 变参对应出问题
    通常是忘记了提供对应某个格式符的变参,导致以后的参数统统错位,检查检查吧。尤
    其是对应”*”的那些参数,都提供了吗?不要把一个整数对应一个”%s”,编译器会觉得你
    欺她太甚了(编译器是obj 和exe 的妈妈,应该是个女的,:P)。

    strftime
    sprnitf 还有个不错的表妹:strftime,专门用于格式化时间字符串的,用法跟她表哥很像,也
    是一大堆格式控制符,只是毕竟小姑娘家心细,她还要调用者指定缓冲区的最大长度,可能是为
    了在出现问题时可以推卸责任吧。这里举个例子:
    time_t t = time(0);
    //产生"YYYY-MM-DD hh:mm:ss"格式的字符串。
    char s[32];
    strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&t));
    sprintf 在MFC 中也能找到他的知音:CString::Format,strftime 在MFC 中自然也有她的同道:
    CTime::Format,这一对由于从面向对象哪里得到了赞助,用以写出的代码更觉优雅。

  • 如何使你的雅虎中文电邮支持POP服务!(收藏)

    2007-08-30 16:31:34

    雅虎中文对新用户现在缺省是不提供POP Access服务的, 但还留有"后门":-), 方法如下:

    (1). 用你的账号登陆进 Yahoo 电邮.

    (2). 然后把下面整个的链接贴到你的浏览器(IE)的地址栏里(注意整个都是一行!):

    http://edit.my.yahoo.com/config/set_popfwd?.src=ym&.done=http://cn.f150.mail.yahoo.com/ym/Options?YY=22797

    (3). 然后就是出现要你同意POP Access服务的网页了, 点了提交按钮以后就可以看到你的POP

    Access服务已经开通的页面了! ! 还不赶快去申请一个? :)

    (4). 如果出错, 登出Yahoo电邮后再次登陆, 然后重复上述步骤 2, 3 即可.

    雅虎中文邮件服务器设置如下:

    接收邮件(POP3)服务器:pop.mail.yahoo.com.cn

    发送邮件(SMTP)服务器:smtp.mail.yahoo.com

    如果看英文不眼晕, 也可直接到Yahoo Canada申请一个帐户, 现在仍直接支持POP Access.

    另外无论是雅虎, 雅虎中文, 还是雅虎加拿大, POP服务器其实均指向同一服务器:

      pop.vip.sc5.yahoo.com [216.136.173.10]

    SMTP服务器均指向:

      smtp.mail.vip.sc5.yahoo.com [216.136.173.12]

  • Tomcat+Jsp经典配置(转)

    2007-08-30 16:16:53

    Tomcat+Jsp经典Tomcat下JSP、Servlet和JavaBean环境的配置

    经常看到jsp的初学者问tomcat下如何配置jsp、servlet和bean的问题,于是总结了一下如何tomcat下配置jsp、servlet和ben,希望对那些初学者有所帮助。
    一、开发环境配置
    第一步:下载j2sdk和tomcat:到sun官方站(http://java.sun.com/j2se/1.5.0/download.jsp)下载j2sdk,注意下载版本为Windows Offline Installation的SDK,同时最好下载J2SE 1.5.0 Documentation,然后到tomcat官方站点(http://jakarta.apache.org/site/downloads/downloads_tomcat-5.cgi)下载tomcat(下载最新5.5.9版本的tomcat);
    第二步:安装和配置你的j2sdk和tomcat:执行j2sdk和tomcat的安装程序,然后按默认设置进行安装即可。
    1.安装j2sdk以后,需要配置一下环境变量,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的j2sdk安装在c:\j2sdk1.5.0):
    JAVA_HOME=c:\j2sdk1.5.0
    classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;(.;一定不能少,因为它代表当前路径)
    path=%JAVA_HOME%\bin
    接着可以写一个简单的java程序来测试J2SDK是否已安装成功:
    public class Test{
    public static void main(String args[]){
    System.out.println("This is a test program.");
    }
    }
    将上面的这段程序保存为文件名为Test.java的文件。
    然后打开命令提示符窗口,cd到你的Test.java所在目录,然后键入下面的命令
    javac Test.java
    java Test
    此时如果看到打印出来This is a test program.的话说明安装成功了,如果没有打印出这句话,你需要仔细检查一下你的配置情况。
    2.安装Tomcat后,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的tomcat安装在c:\tomcat):
    CATALINA_HOME=c:\tomcat
    CATALINA_BASE=c:\tomcat
    然后修改环境变量中的classpath,把tomat安装目录下的common\lib下的(可以根据实际追加)servlet.jar追加到classpath中去,修改后的classpath如下:
    classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\common\lib\servlet.jar;
    接着可以启动tomcat,在IE中访问http://localhost:8080,如果看到tomcat的欢迎页面的话说明安装成功了。
    第三步:建立自己的jsp app目录
    1.到Tomcat的安装目录的webapps目录,可以看到ROOT,examples, tomcat-docs之类Tomcat自带的的目录;
    2.在webapps目录下新建一个目录,起名叫myapp;
    3.myapp下新建一个目录WEB-INF,注意,目录名称是区分大小写的;
    4.WEB-INF下新建一个文件web.xml,内容如下:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <display-name>My Web Application</display-name>
    <descrīption>
    A application for test.
    </descrīption>
    </web-app>
    5.在myapp下新建一个测试的jsp页面,文件名为index.jsp,文件内容如下:
    <html><body><center>
    Now time is: <%=new java.util.Date()%>
    </center></body></html>
    6.重启Tomcat
    7.打开浏览器,输入http://localhost:8080/myapp/index.jsp 看到当前时间的话说明就成功了。
    第四步:建立自己的Servlet:
    1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个servlet程序,文件名为Test.java,文件内容如下:
    package test;
    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public class Test extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    PrintWriter ōut=response.getWriter();
    out.println("<html><body><h1>This is a servlet test.</h1></body></html>");
    out.flush();
    }
    }
    2 .编译
    将Test.java放在c:\test下,使用如下命令编译:
    C:\Test>javac Test.java
    然后在c:\Test下会产生一个编译后的servlet文件:Test.class
    3 .将结构test\Test.class剪切到%CATALINA_HOME%\webapps\myapp\WEB-INF\classes下,也就是剪切那个test目录到classes目录下,如果classes目录不存在,就新建一个。 现在webapps\myapp\WEB-INF\classes下有test\Test.class的文件目录结构
    4 .修改webapps\myapp\WEB-INF\web.xml,添加servlet和servlet-mapping
    编辑后的web.xml如下所示,红色为添加的内容:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <display-name>My Web Application</display-name>
    <descrīption>
    A application for test.
    </descrīption>
    <servlet>
    <servlet-name>Test</servlet-name>
    <display-name>Test</display-name>
    <descrīption>A test Servlet</descrīption>
    <servlet-class>test.Test</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>Test</servlet-name>
    <url-pattern>/Test</url-pattern>
    </servlet-mapping>
    </web-app>
    这段话中的servlet这一段声明了你要调用的Servlet,而servlet-mapping则是将声明的servlet"映射"到地址/Test上
    5 .好了,重启动Tomcat,启动浏览器,输入http://localhost:8080/myapp/Test 如果看到输出This is a servlet test.就说明编写的servlet成功了。
    注意:修改了web.xml以及新加了class,都要重启Tomcat
    第四步:建立自己的Bean:
    1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个java程序,文件名为TestBean.java,文件内容如下:
    package test;
    public class TestBean{
    private String name = null;
    public TestBean(String strName_p){
    this.name=strName_p;
    }
    public void setName(String strName_p){
    this.name=strName_p;
    }
    public String getName(){
    return this.name;
    }
    }
    2 .编译
    将TestBean.java放在c:\test下,使用如下命令编译:
    C:\Test>javac TestBean.java
    然后在c:\Test下会产生一个编译后的bean文件:TestBean.class
    3 .将TestBean.class文件剪切到 %CATALINA_HOME%\webapps\myapp\WEB-INF\classes\test下,
    4 .新建一个TestBean.jsp文件,文件内容为:
    <%@ page import="test.TestBean" %>
    <html><body><center>
    <%
    TestBean testBean=new TestBean("This is a test java bean.");
    %>
    Java bean name is: <%=testBean.getName()%>
    </center></body></html>
    5 .好了,重启Tomcat,启动浏览器,输入http://localhost:8080/myapp/TestBean.jsp 如果看到输出Java bean name is: This is a test java bean.就说明编写的Bean成功了。
    这样就完成了整个Tomcat下的jsp、servlet和javabean的配置。接下来需要做的事情就是多看书、多读别人的好代码,自己多动手写代码以增强自己在这方面开发的能力了。

    jvm应填写到
    c:\j2sdk\bin

    给你一个简单的配置::::

    JSP环境配置心得
    首先要说的是,使用jdk+tomcat完全可以配置我们的jsp服务器,不再需要其实任何东东,有很多文章介绍了Apache,其实根本用不着,一般的学习调试tomcat完全可以胜任了。
    安装jdk后,tomcat在安装之前会自动找到jdk的安装路径,一路点击"下一步",经过一段时间的文件复制,最后"close",完成comcat的安装。
    您最好去下载一个版本较高的tomcat,比如4.1以上的,因为它不需要设置太多的系统变量,右击"我的电脑",选择"属性"->"高级"->"环境变量"->"系统变量",新建一个TOMCAT_HOME,值设置成你的tomcat所在的路径,比如:D:\Program Files\Apache Group\Tomcat 5.5,配置完成。
    从开始菜单中找到tomcat选项,一般打开顺序是:开始->程序->Apache Tomcat 5.5,选择"Start Tomcat",让jsp服务器开始运行,此时会打开一个类似Dos的窗口,会显示一些相关的信息。
    如果您使用代理上网,一定要先撤掉代理,不然您的jsp程序永远也得不到执行。如果不是代理的,这一步就跳过了。
    打开浏览器,在地址栏中输入:http://localhost:8080,如果看到有老虎(我也不知道是老虎还是猫)的画面,恭喜您,您成功了一半。
    先来享受一下成功的喜悦吧,请输入下面的代码:
    <html>
    <head>
    <title>First Page</title>
    </head>
    <body>
    <H3>Today is: h
    <%= new java.util.Date() %>
    </H3>
    </body>
    </html>
    将该程序保存为:First.jsp,放到Tomcat的ROOT目录下,然后在浏览器的地址栏中输入:http://localhost:8080/First.jsp,(First.jsp跟我们保存的文件名的大小写要一致)回车,如果不出意外,应该可以看到形如Today is: h Fri Apr 11 08:32:38 CST 2003 的结果。
    注意:ROOT是tomcat的默认虚拟目录,如果要改成自己的虚拟目录怎么办呢?请继续往下看吧。
    要改成自己的虚拟目录,就要请出server.xml来了,该文件是一个配置文件,在Tomcat\conf目录下,使用任何文本编辑软件都能打开它,我们先找到下面一句:
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
    port="8080" minProcessors="5" maxProcessors="75"
    enableLookups="true" redirectPort="8443"
    acceptCount="100" debug="0" connectionTimeout="20000"
    useURIValidationHack="false" disableUploadTimeout="true" />
    这里的port="8080"就是端口,我们完全可以用别的端口来代替,但不能是被系统占用的端口(0--1023),这里简单提一下。
    下面我们再往下找,会发现以下的语句:
    </Context>
    </Host>
    我们就应该找到这两个语句,如果不懂E文,您就认定这两个语句好了。然后我们将该语句更改如下:
    </Context>
    <Context path="/myjsp" debug="0" docBase="e:/myjsp" reloadable="true">
    </Context>
    </Host>
    这里的path="/myjsp"就是我们就配置的虚拟目录了,以后在地址栏中输入http://localhost:8080/myjsp即可。而docBase="e:/myjsp" 则是机器本地路径,他们通过这个语句形成一个映射关系,其它照抄。
    将上面的First.jsp文件放到e:/myjsp目录下,输入http://localhost:8080/myjsp/First.jsp,是不是有一种喜上眉梢的感觉?
    在论坛里我见得最多的就是很多人不知道javaBean文件放到哪里,老实说开始我也不知道,更令人不解的是,十个人有九种不同的说法,这更让我们茫然。其实这问题也不是我们想像的那么复杂,我们以一个例子说明:
    先建立一个java程序,代码如下:
    package hall;
    public class SimpleBean {
    private String message = "No message specified";
    public String getMessage() {
    return(message);
    }
    public void setMessage(String message) {
    this.message = message;
    }
    }
    保存为SimpleBean.java,编译后会生成一个包,其实就相当于一个目录,也就是SimpleBean.class会存放在hall目录中,暂且保存起来,将来备用。
    再输入以下代码:
    <HTML>
    <HEAD>
    <TITLE>Reusing JavaBeans in JSP</TITLE>
    </HEAD>
    <BODY>
    <CENTER>
    <TABLE BORDER=5>
    <TR><TH CLASS="TITLE">
    Reusing JavaBeans in JSP</TABLE>
    </CENTER>
    <P>
    <jsp:useBean id="test" class="hall.SimpleBean" />
    <jsp:setProperty name="test" property="message" value="Hello WWW" />
    <H1>Message: <I>
    <jsp:getProperty name="test" property="message" />
    </I></H1>
    </BODY>
    保存在我们刚才建立的虚拟目录e:/myjsp下面,并命名为:BeanTest.jsp。
    现在我们应该将hall(包)目录放在哪儿呢?别急,我们先在e:/myjsp下建立一个文件夹WEB-INF,然后再在WEB-INF下建立一个classes文件夹,最后将hall目录放到classes下,当然,hall下的字节码文件SimpleBean.class也一并要移过来,而SimpleBean.java就和BeanTest.jsp放到同一目录吧(可以不需要放的,自己试试)。
    好了,大功告成了,重新启动机器(如果您试了好多次都不行,这一步一定要做),在浏览器中输入:http://localhost:8080/myjsp/BeanTest.jsp,您看到了什么?呵,别告诉我您什么都没看到,那肯定是您设置的问题了。
    好了,文章写完了,我也只是一只菜鸟,所以有写的不准备的地方请多多指教。祝您jsp之旅一路顺风!!!
    Java学习 - 技术文章中心
    初学者问的诸如:《怎样配置环境变量》《怎样运行Servlet》啊?这样的问题太多了,现在我写一个初学者入门必读,以便对初学者有指导作用!
    首先是下载工具:
    我建议初学者用Editplus+JDK,我觉得如果用例如JB,Eclipse,JCreator,虽然刚开始的时候比较方便,但是确使初学者门不知道怎样配置环境变量,
    从而难以达到知其然,知其所以然的地步
    可以通过如下地址下载:
    Editplus(最新版本是v2.11):http://count.skycn.com/softdown.php?id=3641&url=http://sc-http.skycn.net/down/epp211a_cn.exe(要照注册码就自己找吧,网上很多的)
    JDK(最新版本是Java2sdk1_5_0):http://192.18.97.54/ECom/EComTicketServlet/BEGIN30AA3B63E5C2F61C8C26F84B78970A98/-2147483648/926882595/1/627578/627410/926882595/2ts+/westCoastFSEND/jdk-1.5.0_04-oth-JPR/jdk-1.5.0_04-oth-JPR:3/jdk-1_5_0_04-windows-i586-p.exe(这是For Windows)
    然后就是安装JDK,我是把它装到从c:\JDK目录下面:
    然后就是CLASSPATH的问题了:
    正如操作系统利用PATH来搜索可执行程序一样,Java运行环境也会遍历CLASSPATH来查找类,即便是HelloWorld这样简单的程序,JVM也会遍历
    CLASSPATH定义的每一个路径,直到找到相应的文件为止。
    相信大家用的系统不是2k就是XP,然后就应当如下设置Path:
    我的电脑->属性->高级->环境变量
    然后在环境变量的Path后面追加: C:\JDK\bin;.;C:\JDK\lib
    也可以这样配置:C:\JDK\bin;.;C:\JDK\lib\dt.jar;C:\JDK\lib\tools.jar
    ★记住:环境变量中的 . 切记不能少,它表示当前路径,如果少掉出现的错误等会就说!
    dt.jar是关于运行环境的类库,tools.jar是关于一些工具的类库
    如果没有配置:C:\JDK\bin,则会出现 " javac´ 不是内部或外部命令,也不是可运行的程序或批处理文件。"这样的错误。
    然后下面就该写程序了:
    首先是(HelloWorld.java),打开Editplus,新建一个Java文件,请照着如下输入,要一字不漏,并且分清大小写:
    public class HelloWorld{
    public static void main(String[] args){
    System.out.println("Hello,World!");
    }
    }
    然后把这个文件保存(ctrl + s)到HelloWorld.java,记住大小写一定要分清,是HelloWorld.java不是helloworld.java或者其它的
    下面就该运行了,开始->运行->cmd
    在控制台中把目录切换到当前目录:
    javac HelloWorld.java
    java HelloWorld
    你就会在控制台上看见输出的Hello,World!(没出来?我把电脑吃了:))
    javac是编译命令,它把HelloWorld.java编译成HelloWorld.class
    java就是解释命令,JVM把HelloWorld.class解释执行.
    在这个时候:
    1。如果出现Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
    那就是你在环境变量中没有加上那个.(dot)
    2。如果出现Exception in thread "main" java.lang.NoSuchMethodError: main
    或者HelloWorld.java:1: Public class helloworld must be defined in a file called
    "HelloWorld.java".
    那就是你没有分清大小写的写入这个HelloWorld,或者保存得时候没有保存为HelloWorld.java
    这个名字一定要跟public class的名字一样
    对于环境变量的问题就说到这里,下面我先所说怎么在Editplus里面编译和运行,在Tools->参数设置->配置用户工具
    1.添加工具(添加应用程序)
    菜单文字:Compile Java Program
    程序:C:\JDK\bin\javac.exe
    参数:文件名称
    初始目录:文件目录
    2.添加工具(添加应用程序)
    菜单文字:Run Java Program
    程序:C:\JDK\bin\java.exe
    参数:文件名称(不含扩展名)
    初始目录:文件目录
    工具组名称可以随便添,比如Debug Java Program
    然后在Tools的下拉菜单中,你就会看见Compile Java Program以及Run Java Program这两个选项,以后你就可以利用ctrl + 1编译和ctrl +2运行程序了

    下面就讨论Servlet的运行:
    首先要运行Servlet,则需要JSP/Servlet container,我建议初学者用Tomcat
    Tomcat(最新版本5.5):http://apache.justdn.org/jakarta/tomcat-5/v5.5.9/bin/jakarta-tomcat-5.5.9.exe然后把这个压缩包解压到:
    C:\Tomcat
    然后再配置环境变量:
    添加三个系统变量:
    JAVA_HOME: C:\JDK
    TOMCAT_HOME: C:\Tomcat
    CLASSPATH: %JAVA_HOME%\lib;%TOMCAT_HOME%\lib
    Tomcat的环境变量就配置完毕了,下面检验Tomcat是否能够运行:
    在控制台中转到C:\Tomcat\bin这个目录,运行startup,然后回出现一个窗口,连跳一大串东西,最后表示Server已经运行
    在浏览器中输入http://localhost:8080,出现欢迎界面,则表示Tomcat没问题了
    然后和上面一样,写入你的第一个Servlet
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    public class HelloWorld extends HttpServlet
    {
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException
    {
    response.setContentType("text/html");
    PrintWriter ōut = response.getWriter();
    out.println("<html><head><title>");
    out.println("This is my first Servlet");
    out.println("</title></head><body>");
    out.println("<h1>Hello,World!</h1>");
    out.println("</body></html>");

    }
    }
    然后照样用javac HelloWorld.java来编译这个文件,如果出现无法import javax.servlet.*
    那么就是应该把C:\Tomcat\common\lib里面的servlet.jar(根据实际来看)文件拷贝到C:\JDK\jre\lib\ext中,再次编译,就没有问题了!
    然后在Tomcat目录里面的C:\Tomcat\webapps\ROOT里面按如下的文件结构:
    ROOT\index.html
    ROOT\welcom.jsp
    ROOT\WEB-INF\lib\MyServlet.jar(如果你的servlet的.class打成了.jar文件,则放在lib下面)
    ROOT\WEB-INF\classes\HelloWorld.class(把上面生成的HelloWorld.class文件放在这个里面)
    然后在浏览器中输入http://localhost:8080/servlet/HelloWorld,于是Server众望所归的报错了:Error 404--Not Found
    怎么回事呢?
    Servlet必须使用C:\Tomcat\webapps\ROOT\WEB-INF这个目录下面的web.xml文件进行注册,用EP打开这个web.xml文件,
    在里面加入
    <servlet>
    <servlet-name>HelloWorld</servlet-name>
    <servlet-class>HelloWorld</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>HelloWorld</servlet-name>
    <url-pattern>/servlet/helloworld</url-pattern>
    </servlet-mapping>
    这样的结构
    <servlet>
    <servlet-name>HelloWorld</servlet-name>
    <servlet-class>HelloWorld</servlet-class>
    </servlet>
    表示指定包含的servlet类.
    而以下的结构
    <servlet-mapping>
    <servlet-name>HelloWorld</servlet-name>
    <url-pattern>/servlet/HelloWorld</url-pattern>
    </servlet-mapping>
    表示指定HelloServlet应当映射到哪一种URL模式。
    在修改web.xml完毕过后,重新启动Server,然后再输入http://localhost:8080/servlet/HelloWorld,那么偌大一个Hello,World!等着你呢,恭喜你
    摆平了:)

  • 面试十大必考题目!(转)

    2007-08-28 21:44:31

    面试时,有几个问题是公司面试人员常常会提出的,针对这些问题好好准备,在面试时也就不会哑口无言,无言以对了,下面就面试十大必考题做出分析,也许对HR经理也是一个小参考:
    (1) 为什么想进本公司?
    这通常是面试官最先问到的问题。此时面试官就开始评断录用与否了,建议大家先判断自己去应徵的工作性质,是专业能力导向呢,或是需要沟通能力,其实现在市场多以服务为方向,所以口才被视为基本能力之一,所以在此时就要好好表现自己的口才,而口才较差者就务必表现出自己的专业能力即诚意,弥补口才不足的部分。
    回答这个问题时,一定要积极正面,如想要使自己能有更好的发展空间,希望能在相关领域中有所发展,希望能在公司多多学习等等﹔此时可以稍稍夸一下面试公司,但切记一定要诚恳,不然可是会画蛇添足,得不偿失哦!对于社会新鲜人的建议则是,由于之前没有工作经验,所以建议你可以坦承的说出自己的动机,不过用语还是要思考一下

    (2) 喜欢这份工作的哪一点?
    相信其实大家心中一定都有答案了吧!每个人的价值观不同,自然评断的标准也会不同,但是,在回答面试官这个问题时可不能太直接就把自己心理的话说出来,尤其是薪资方面的问题,不过一些无伤大雅的回答是不错的考虑,如交通方便,工作性质及内容颇能符合自己的兴趣等等都是不错的答案,不过如果这时自己能仔细思考出这份工作的与众不同之处,相信在面试上会大大加分。

    (3) 自己的优缺点为何?
    有许多面试官都喜欢问这个问题,目的是在于检视人才是否适当,求职者的诚恳度等等,在这之前应该好好分析自己,将自己的优点与缺点列张单子,在其中挑选亦是缺点亦是优点的部分,在回答问题时,以优点作为主要诉求,强调可以为公司带来利益的优点,如积极,肯学习是最普遍的回答,而缺点部分则建议选择一些无伤大雅的小缺点,或是上述那些模嶙两可的优缺点作为回答,这样才不会使面试官太过针对缺点做发挥,造成面试上的困难。

    (4) 对公司的了解有多少?
    这时准备的功夫就派上用场,将你之前所吸收的信息发挥出来吧!至少也要知道公司的产品是哪些,提供哪些服务等等,不然面试官一问当场傻在那儿就糗大了,所以一定要事前准备!

    (5) 对工作的期望与目标何在?
    这是面试者用来评断求职者是否对自己有一定程度的期望、对这份工作是否了解的问题。对于工作有确实学习目标的人通常学习较快,对于新工作自然较容易进入状况,这时建议你,最好针对工作的性质找出一个确实的答案,如业务员的工作可以这样回答:“我的目标是能成为一个超级业务员,将公司的产品广泛的推销出去,达到最好的业绩成效;为了达到这个目标,我一定会努力学习,而我相信以我认真负责的态度,一定可以达到这个目标。”其他类的工作也可以比照这个方式来回答,只要在目标方面稍微修改一下就可以了。

    (6) 为什么要离职?
    回答这个问题时一定要小心,就算在前一个工作受到在大的委屈,对公司有多少的怨言,都千万不要表现出来,尤其要避免对公司本身主管的批评,避免面试官的负面情绪及印象;建议此时最好的回答方式是将问题归咎在自己身上,例如觉得工作没有学习发展的空间,自己想在面试工作的相关产业中多加学习,或是前一份工作与自己的生涯规划不合等等,回答的答案最好是积极正面的。

    (7) 选择这份工作的原因为何?
    这是面试官用来测试应聘者对工作理解度的问题,藉以了解求职者只是基于对工作的憧憬或是确实的兴趣来应徵这份工作,此时之前所强调的事先研究功夫又再度派上用场,建议你的回答应以个人的兴趣配合工作内容特质,表现出高度的诚意,这样才可以为自己铺下迈向成功之路。

    (8) 你认为相关产业的发展为何?
    这也是事前准备的功夫,多阅读一些相关的报章杂志,做一些思考,表现出自己对此相关产业的的认识,如果是同业转职者,可强调以自己的经验为基础所做的个人见解,但若是初次接触此一行业,建议采取较为保守的方式,以目前资讯所提供的资料为主作答,表现出高度兴趣及诚意为最高指导原则。

    (9) 你希望的待遇为多少?
    这是一个非常敏感的问题,其实在目前,一般大型企业在招聘时就会事先说明基本底薪等等薪资待遇为何,而一般中小型企业有许多仍以个人能力,面试评价做作为议薪的标准,所以建议求职者可以利用现在网络科技查询薪资定位的相关资料,配合个人的价值观,经验,能力等等条件,做出最基本的薪资底限,这时建议无工作经验者应采取保守的态度为准,以客观资料作为最主要考量重点,“依公司规定”的回答是不被建议的,这样不但表示出自己对于工作的自信程度不高,在薪资无法符合个人要求时更会造成许多困扰。

    (10)在工作中学习到了些什么?
    这是针对转职者提出的问题,建议此时可以配合面试工作的特点作为主要依据来回答,如业务工作需要与人沟通,便可举出之前工作与人沟通的例子,经历了哪些困难,学习到哪些经验,把握这些要点做陈述,就可以轻易过关了
  • 面试,用30分钟决定你的职业(转)

    2007-08-28 21:39:09

     为什么你想要这份工作?

      先来做一个成语填空。我发现,这个四字成语可以用来形容许多人在找工作时的心态:东——西—— .东邪西毒?东成西就?东南西北?东方不亮西方亮?

      拜托,有点专业精神好不好。想不出来吧?我来揭晓答案,这个成语是:东食西宿。

      这是一个生僻的成语,生僻到几乎所有的汉字输入法软件的词库中都没有这个成语。

      而且这个成语因为意思刻薄,也很少在生活中为人们使用。

      它究竟是什么意思呢?这个成语背后的故事是:古时候有一户人家的女儿到了出嫁的年龄,东边邻居的儿子和西边邻居的儿子都来提亲。 东边的邻居家境殷实,但是儿子非常难看并且不解风情;西边的邻居家境清贫,但是儿子一表人才并且知书达理。父母做不了决定,就去问女儿的意见。女儿考虑了半天,终于羞答答地表态:我能不能在东家吃饭,然后晚上住在西家?

      本来,追求两全其美的心态也无可厚非。我相信在这个世界上也的确有收入又高又不辛苦的工作,然而,对于刚刚从大学里走出来的学生或者是其他资历尚浅的年轻人来说,讨价还价的能力几乎为零。文凭的意义仅仅在于可能给了你一块敲门砖,但是,如果你以为你的十年寒窗苦读能够给公司带来的价值,可以等于甚至大于一个在实践中已经摸爬滚打了10年的老手,那么你已经在心态上犯了第一个不实用主义的错误。

      从另外一个角度来说,没有东食西宿的好事,也说明了每一份工作总是会有它的不尽如人意之处。我的许多朋友,都是工作在投资银行和咨询公司的年轻精英们,他们衣着光鲜,坐飞机出差几乎如同我们普通人打车;平时出入各大写字楼、五星级宾馆,偶尔神秘地提到自己正在做的项目,满嘴的专业术语让人立刻觉得高深莫测,更不要提他们的五位数的月薪,轻松入读名牌MBA的可能,以及未来看似无限的“钱途”。这一切难道不让人羡慕不已吗?

      然而,在我没有开始找工作之前,我参加了几次他们的聚会,惊奇地发现,每次的聚会都会有一个环节叫做“抱怨比赛”。来自不同公司的精英们,开始争先恐后地抱怨自己的工作时间太长、没有个人生活的乐趣、熬夜导致健康下降、项目中自己的任务太过于无聊,等等。

      这听上去是不是颇有些令人惊奇呢?其实,著名的“二八原则”在任何一项工作中同样都是适用的——一份工作,其中令旁观者羡慕、在闪光灯下或者是给工作者带来真正的成就感的部分,大部分只占工作内容的20%而已。而另外的80%的工作内容,则可能充斥着艰苦的劳动、枯燥的重复、巨大的身心压力等等可能不为外人所知的辛苦的一面。

      我最欣赏的日本的行为心理学家、效率大师多湖辉就曾经说过,幸福的人生不过就是能够以自己喜欢做的事情为工作,并且还能够从工作中获取到合理的报酬而已。不过,这个看似简单的要求,多湖辉接着补充说,也仅有非常小的一部分人能够真正实现这种幸福。

      为什么一本讲面试的书要从讨论对工作的态度开始呢?难道高明的面试者不是可以通过面试获得这个世界上所有想要的工作吗?或者说,不论是什么工作,神奇的面试者都可以进入面试室,把自己推销出去,就好像传说中最伟大的推销员能够把梳子卖给僧侣、把冰箱卖给爱斯基摩人、把二胡卖给西洋管弦乐团一样?

      并不是这样的。假如你真的把面试看成一场推销,伟大的推销员,也是依靠自己对顾客需要的了解来赢得订单。更何况,一场好的面试,在我看来,远远不是一场推销,而更是一个坐在面试桌前的双方,互相发现对方对于自己的意义和价值的过程。你对一份工作的态度是冷淡、热情、充满兴趣、无所谓还是势在必得……会直接影响着你在面试中表现出来的态度。它们通过你的眼神、声调、动作、微笑弥散开来,透过空气,慢慢地感染到你的面试官。

      于是,你的面试官接收到了这种“感染因子”,他突然抛出一个问题:告诉我,你为什么想做这一行/进这个公司?

      你一定会在面试中遇到这个问题。而这个问题的潜台词丰富得令人难以置信。结合你们对话的上下文和面试的气氛,这个问题可能包含着面试官各种各样的微妙的态度:热身的问题:“让我再看看他的简历,我完全忘了他的背景了。让他先随便说说废话,我好趁这个时间想想该问他些什么。”这种情况大多发生在面试刚一开始的时候。

      积极的信号:“这个小伙子不错。让我来看看他对我们这行究竟有什么了解,顺便再给他一些积极的鼓励。”

      消极的信号:“你说你讨厌加班、不喜欢数学,平时的爱好就是睡觉。你为什么跑来申请一所会计师事务所?!你是不是真的走错门了?如果是这样,这就是我最后一个问题了。”

      不安全感:“这家伙看上去实力很不错,为什么跑来申请我们这种工资低又辛苦的活儿?没准就是来拿我们练练手的。”或者,“GRE、TOFEL这孩子都考了这么高的分,看上去他只差一张美国签证了。是不是明年他就准备拍拍屁股出国了?我得不动声色地问个究竟。”

      ……

      不同的情况还可能有很多种。如果你能判断出面试官的情绪和意图,你也许可以更好地调整自己的情绪和回答的内容。然而,万变不离其宗,你的回答也许永远都逃不过这个最基本的问题:你真的想做这份工作吗?为什么?而且,如同我后面还会强调的那样,按照你的真实想法回答问题,往往是回答面试问题的最正确的态度。

      更多的情况是,你往往并不知道自己是不是真的喜欢你所申请的工作,也许你申请它,不过是因为听别人说这是一份好的工作,而且人人都在申请。或者你对这个工作所知甚少,仅仅知道它的工资不错。可是,你难道真的可以说,你想做这一行是因为它的****水吗?

      是的,你可以这样说,如果这一点真的对你很重要。高报酬的薪水同样也意味着更高的责任和对职业奉献精神更高的要求,指出这一点来,说明你对这份工作的期待和认识没有什

      么不妥。如果你家境贫寒,你需要尽快****帮助你的弟弟妹妹继续完成教育,向你未来的老板指出这一点只会展现你的责任感并且赢得他们的尊重。事实上,喜欢一份报酬优厚的工作本身并没有任何的错误,特别是考虑到你的面试官同样也在享受着这份工作的这个优点。

      当然,如同那句成为越来越多的人的口头禅的话所说:钱不是问题,或者,钱不是最重要的。可是你会发现,还是有很多人在去面试之前根本就没有好好想过对这个问题的答案;或者,他们想了,但没有答案。

      我听说过的一个北邮的朋友,走进中国电信的面试室,面对“你为什么想来电信行业发展”的问题,想了半天,终于憋出来一句话:“我的手机是全球通,是中国电信的,所以我想来中国电信工作。”相信我,他不是故意想幽默。

      其实对这个“你为什么要选择这份工作”的回答,也许我们需要有一个系统的分析和观点。

      《宪法》中规定了我们都有劳动的权力,然而在现实中,我们每个人都得自己负责去寻找到一个劳动的机会。因此,对于几乎所有的毕业生而言,“就业”,是迈向职业生涯的第一个门槛。跨过去,才能够真正的开始从学校向职场的转变。就业之后,如果你幸运,或者你精心地挑选对了你的第一份工作,你发现你很喜欢也很适合,你愿意稳定地在你现有的位置上发展自我、展现你的才华、实现自己的价值,那么,应该说,你开始有了“职业”的认同,从人人都会有的对第一份工作不确定心态中稳定了下来。

      比起那些发现自己的第一份工作并不令自己满意的人来说,你可以有更长期的计划去建设你的职业,而不需要迅速地考虑跳槽甚至更改自己的行业。

      “事业”是比“职业”更高的一层状态。也许一个人对一份职业产生了强烈的热爱和认同,使得这份职业变成了自己的事业;也许一个人开始了创业,从此成为了自己的老板。“职业”更多的是一个阶段性的概念,而“事业”已经开始带有人生追求的色彩。

      如果你觉得这种“就业——职业——事业”的三分法似乎还有些道理的话,那么什么是我们就业应该考虑的方向就变得很清楚了。

      假设同时毕业的三个好朋友,A选择了去一家广告公司,一年后跳槽到一家房地产公司,一年后又跳槽到一家网络公司;B选择去了一家大型外企的人力资源部门,工作两年后被提升为经理,同时在职继续攻读人力资源方向的MBA;C进入了政府部门,在基层锻炼了两年后回到部委工作。

      这三个年轻人当然都还很年轻,他们未来的发展充满了不可预期的变化。但是让我们仅仅从“就业——职业——事业”的三分法的角度来看,A一直在就业的状态中,而B正在建设自己的职业,C开始经营的是自己的事业。

      《基业长青》中对世界上最成功的公司的战略进行了分析后,得出一个结论,那些成功的公司,最相同的地方是:长期地专注做一件有长远意义的事情,最后获得了成功。公司的发展如此,人的发展是不是也可以从中借鉴到一些道理?

      因此,如果说单纯的就业仅仅解决了你依靠劳动自食其力的问题,一个更好的就业,应该是能够使你获得一份你可以持续建设的职业,甚至是一份你可以终身经营的事业(当然,不参加就业而直接创业的,也应该归到追求事业的一类中去)。以就业为目标,也许你看重的仅仅是一份经历、工资或者就是工作本身;而以寻找到一份职业为目标,你要考虑的就应该包括这份职业会如何给你带来成就感、如何帮助你继续学习、成长,它的中远期发展前景如何;如果你是在寻找一份事业,那么,你更加需要好好地和你内心深处的渴望对话:你是一个怎样的人?你希望向什么方向前进?

      好了,经过了一番深思熟虑,现在是自信而沉稳地回答你的面试官关于“你为什么要选择这份工作”的问题的时候了。答案就是告诉他你在寻找的是什么,而为什么这个行业/公司能够提供给你所寻找的东西。

      通常,一个热情、有事业心的年轻人会希望在工作中寻找到:明确的学习内容和目标不断学习和锻炼的机会挑战感和成就感对某一个行业的特定知识和特殊技能潜在的作为终身事业追求的可能工作带来的自我实现感:报酬、社会认同、价值观有意义的工作内容、工作伙伴和工作环境……

      你可以继续在这个单子上面加上你真想要的东西。每个人都是特殊的,每个人都会有不同的内容补充进来。告诉你的面试官你真正想要的东西,这种诚实能够使你们双方产生一种开诚布公的交流氛围。更加重要的是,想清楚你真正想要什么,能够避免你自己为了得到工作本身而迷失了自己的追求,因为,当你一不小心实实在在地获得了一个工作机会时,它看上去总会变得更加顺眼一些。而如果它其实真的不是你想要的,这种额外的获得只会成为你继续寻找的阻力。但是你也必须脚踏实地地总结出你对于工作的理想和期望,不要太理想主义,走向了唱高调般的反面。一个对于咨询行业的合理的理想表述可以是:“我喜欢发现和解决困难的问题,通过努力找出答案。特别是当这个答案可以帮助到其他人更好的工作和生活时,我会更加觉得愉快与有成就感。”然而我在麦肯锡的面试现场却听说过这样的回答:“我希望我的工作能够增加中国宏观经济和微观经济运行的效率,同时积累经验,将来使自己开办的公司进入世界500强。”

      还有另一个有些异曲同工的例子,说明任何远大的理想都应该和脚踏实地的工作联系起来。我的一位好朋友告诉我,他在面试一家投资银行时,解释他为什么被投资银行业所吸引时说:“我觉得做这一行可以直接和很多企业的高层直接会面,通过我们的工作影响他们的决策,从而影响到整个经济和市场。”——他突然发现面试官的嘴角开始慢慢地往下撇,于是他紧接着说,“当然,这是在我能够成为像您这个级别的资深银行家之后。我非常清楚作为一个初级的分析员每天所面对的都是大量的基本案头工作。”

      谢天谢地,他看到面试官嘴角的曲线终于又向上弯了回去。

      第二章:世界上最漫长与最短暂的30分钟咬文嚼字有时往往能够给人带来许多有趣的启发,比方说让我们来琢磨琢磨“面试”

      这个词。从科举应试,到金銮殿试,尽管我们伟大的中华考试文化源远流长,“面试”这个词看上去却像是个舶来品——面试,顾名思义,当面的考试。似乎在引进这个词的语言学家那里,面试就已经被定性为了一种测试,因此不是面聊、面看、面笑。而测试,我们知道,它好像总是会让人紧张、手心出汗、心跳加速的……

      世界上最漫长与最短暂的30分钟

      咬文嚼字有时往往能够给人带来许多有趣的启发,比方说让我们来琢磨琢磨“面试”

      这个词。从科举应试,到金銮殿试,尽管我们伟大的中华考试文化源远流长,“面试”这个词看上去却像是个舶来品——面试,顾名思义,当面的考试。似乎在引进这个词的语言学家那里,面试就已经被定性为了一种测试,因此不是面聊、面看、面笑。而测试,我们知道,它好像总是会让人紧张、手心出汗、心跳加速的……

      反过头来看英语中的“面试”——interview,却似乎没有沾上任何和“考试”相关联的味道。除了面试之外,interview包括的意思还有:会见、采访。其令人紧张的程度怎么看也比不上考试。如果我们把interview这个词拆开,也不过是inter和 view,直接翻译成中文最多是“大家互相瞅瞅”的意思。

      也许词语的意思会随着人们生活的发展而变化,就好像今天有人说请你“吃饭”,但通常你可能根本不会吃到一粒米饭,但是还是没人肯说是去请你“吃菜”。那么,“面试”发展到了今天,除了“考试”的意思,还可以被理解成什么呢?

      有人说面试就是一场推销:你向面试官花言巧语地推销自己,试图从他那儿拿到作为订单的工作合同。

      有人说面试就是一场谈判:大家坐在桌子两端,唇枪舌剑,你来我往。谈判的目的就是要说服面试官,不雇佣你,将会是他们最大的损失。

      也有人说面试更像是一场戏:平时只穿牛仔裤的你必须换上西服,西装革履风度翩翩外交辞令地扮演一个你根本不熟悉的角色。演得好你就有资格继续演下去,演得不好你就别想有人捧你让你红。

      还有人说面试就是一场审判:面试官就是审判官,他的决定掌握着你命运的转折。你只能为自己作出无力的辩护,其他的都只能交给你上辈子积的德和你上星期在卧佛寺捐的香火(卧佛寺,因为“卧佛”谐音offer,据说求offer必应,于是成为北京地区香火最盛的寺庙之一)。

      还有人说……

      众说纷纭,不由让我想起了一桩著名的禅门公案。两僧打坐,甲僧对乙僧说,我看你像狗粪。乙僧对甲僧说,我看你像尊佛。禅师说,乙僧心中是佛,看别人也是佛;甲僧心中是狗粪,看别人也是狗粪。

      在我看来,你怎么看面试,恐怕也决定了你在面试中的感受如何。如果你进入面试屋的时候,心里想着的是进入考场、谈判场、戏场或者审判室,你的心情想必也难以愉快而轻松,你脸上的微笑也不免会生硬与干涩。

      所以,为什么不把面试看成是一场难得的对话?试着更多地把自己定位为一个前来学习人生和工作经验的学生,而面试官作为一个愿意与你分享关于工作、职业发展和人生经验的前辈。你会发现,抱着这种心态,面试压抑的气氛在不知不觉中从一问一答,而慢慢地变成了一个双向的交流。事实上,甚至应该这么说,能够和杰出的职场人士如此平等、轻易地交流(特别是想到这些人将来可能会是你好几个级别以上的老板时),面试真是再理想不过的一个机会了。

      反过来,对于那些平日忙于在商业世界里打拼的面试官们来说,回到有些陌生又有些熟悉的菁菁校园面试,见到一张张写满渴望、勇气和单纯的年轻的脸庞,为什么不和眼前的这个看上去聪明、可爱和善解人意的孩子聊聊自己的过去,指点一下他未来的发展,多获得一些崇敬的目光呢?他们当然会这样做,只要你给他们机会。

      对于任何一个富有远见的组织来说,招揽到出色的人才,无论对于公司还是其他机构,都是成功地完成自己的使命的基础。面试对于公司的意义在于,提供一个认识候选人的机会,从而在此基础上判断,谁是更加适合公司需要的人才。尽管,每家公司的面试组织程序会有所不同,但是它们还是有基本相同的先后顺序。了解这些基本的程序,能够帮助面试者减少对面试的神秘感,增加信心,更好地设计自己的面试策略。

      通常面试程序可以被分成以下几个部分:

      (1)确定所需要招聘的职位的工作描述、薪酬范围和应聘者所需要的资格。

      (2)通过招聘会、海报、广告等形式,把招聘信息传达给潜在的应聘者。

      (3)收集应聘者的简历,筛选简历得到可以进一步面试的合适数量的应聘者。

      (4)电话面试。一般由人力资源部门或者投资银行与咨询公司中资历比较浅的分析员或者咨询员打来,在面试中进一步确认应聘者的背景、语言表达能力等。通过筛选得到可以进一步面试的合适数量的应聘者。

      (5)第一轮面试。

      (6)第二轮面试。

      (7)确定入选的候选人,人力资源部门和他们保持联系,推销公司,确保他们接受合同。同时,公司也可能继续和几个作为万一“正选”拒绝接受要约后的“后备”候选人保持“暧昧”的关系。

      (8)人力资源部最后检查应聘者的背景、提供的材料无误。

      你在申请公司的时候不一定会经历所有的程序。比方说,电话面试往往只是那些非常强调英语口语能力的外企才有的步骤,他们希望借此道程序排除一部分口语能力不强的应聘者,国企、私营企业或者政府机关,基本上不会有这道门槛。

      对于外企而言,面试程序也各不相同,投资银行一般在电话面试后只会安排一轮面试,但这轮面试中会有4到6个级别不同的银行家在一个集中的时间内展开“车轮大战”式的面试。这一方面是因为银行家时间紧张,整天在天上飞来飞去,如果不固定一个时间集中面试,整个面试可能会因为每个人的时间安排不同而拖得很长;另外,这种车轮大战式的面试在另一个方面也能够很好地测试出应聘者是否能在这种长时间压力的工作环境下有良好的表现和发挥。说实话,一个人30分钟,连续3个小时的面试下来,真是有筋疲力尽、大脑缺氧的感觉。

      咨询公司的风格又不一样,他们往往在电话面试后安排两轮面试,并且面试的内容与大部分投资银行的传统面试也不相同。咨询行业的面试几乎都是案例面试,应聘者遇到最大的挑战来自解决现实中的咨询员遇到的真实问题。面试官往往仅仅告诉应聘者一些最基本的事实,应聘者必须通过与面试官的讨论,发掘、掌握更多的有用信息,决定采取某一种方法,有逻辑地找出这个问题的答案。案例面试的最终的答案有可能是一个估计出来的数字,也有可能是一套商业战略,还有可能是发现一个重要的原因。比方说,我自己曾经碰到的最让我

      摸不着头脑的一个估计数字的题目是:北京市大概有多少下水道的井盖?

      如果说投资银行的面试方式是把应聘者放在压力之下,看他的举止反应;咨询公司是把应聘者放在问题之中,看他的分析能力和聪明程度,那么,对于一般的工业性的跨国公司(P&G、Unilever、GE等等)来说,他们会更小心地详细考察应聘者过去的背景,会愿意和应聘者在一起花更多的时间,来观察和判断应聘者是否具有他们公司文化所欣赏的品质和特点,是否能够和这个庞大的公司机器上的所有人相处和谐。其中最典型的也最有名的面试风格应该是宝洁公司严格的“笔试——职业英语能力测试——性格特征测试——HR面试——广州总部部门面试”

      爱因斯坦曾经这样对年轻学生解释过相对论:当你和一个美丽的姑娘坐上两个小时,你会感到好像坐了1分钟;但要是在炽热的火炉边,哪怕只坐上1分钟,你却感到好像是坐了两小时。

      同样,面试可能是世界上最漫长的30分钟,也可能是世界上最短暂的30分钟。当你和你的面试官都有一种频频想看表的冲动时,抱歉,你的这场面试看起来是失败了。而当你走出面试间,一低头看表,发现不知不觉地已经超出了30分钟时,这往往是证明你刚才的面试进行得很顺利。

      一个面试官就曾经告诉我,当他在面试开始5分钟后,就决定不可能给这个应聘者任何机会的时候,他恨不得立刻就结束这场面试。但是,他不能,因此,他只好盯着手表,等到刚过25分钟的时候,立刻开始问应聘者:你还有什么问题吗?

      30分钟的面试时间里可以发生很多的事情,但是也可能没有发生太多的事情。毕竟,即便是中央电视台的播音员,按照1分钟300个字的速度说话,30分钟滔滔不绝地一直在说,也说不到1万个字。通过不到1万个字的信息量,你是否能够获得这个可能是命运转折的机会就这样被决定了。所以你要明白,可能真的需要字字珠玑,字字千金,你才能打动命运女神的垂青。

      一个常规面试的30分钟里可能出现的事件和顺序大致上是这样的——但是,同样,法无定法,任何变数都会发生,掌握常规和随机应变并不矛盾——敲门,你满面笑容地进去,握手,请坐。然后面试官会给你一个很短的自我介绍,时间已经过去了3分钟,面试算是正式开始了。最理想的状态,你的面试官的第一个问题是:简单地介绍一下你自己吧。正中下怀,于是你开始背你写好的稿子,啪啦啪啦啪啦,你最好最多别超过5分钟,否则面试官十有八九会打断你,他觉得你背得太熟了。于是,面试开始10分钟后,真正的较量开始了。在接下来的15分钟之内,才是你真正抓住面试官,给他留下决定性印象的时候。15分钟之内,一问一答,能够有几个回合呢?完全取决于你回答问题的长度。你可以一个问题用10分钟来回答,另一个问题用5分钟,这样你就让刁钻的面试官没有机会问你别的问题了;你也可以每个问题都用一句话来回答,这样你很快就可以让面试官弹尽粮绝,没有那么多准备好的问题来问你了——我希望你能看出来我是在开玩笑。

      对你而言,控制时间和节奏成为了和给出好的答案同样重要的任务,如果前者不是更重要的话。有几个重要的原则你必须记住:

      (1)你必须努力掌握对节奏的控制权,而不要把它交给你的面试官。

      如果你回答问题总是拖沓冗长、毫无逻辑也看不出什么时候能结束,面试官会不得不总是打断你的回答:“我明白你的意思了,那么,下一个问题是……”这种被打断回答的情况往往会带来紧张,出现几次,你就会发现清晰的思维和顺畅的表达就这样被打断了。

      所以,千万不要给面试官这种机会。通常情况下,只要你把握得当,他们也并不会主动地抢。

      然而也有这样的面试,面试官无意或者故意地不断打断你的回答,试图获得面试节奏的控制权。那么,在这种情况下,你必须保持冷静,努力地把节奏感再抢回来。你可以在面试官突然打断你的回答,插入一个问题时,有意识地保持10秒钟的沉默,装作在思索这个问题,实际上是在冷静,找回自信和节奏,然后用一种和刚才回答问题不同的语速重新开始。还有的时候,当你觉得你是在回答到关键时刻被打断的话,不要就此罢休,你应该在回答被打断之后的新问题前,有礼貌地说:“在我回答这个问题之前,我觉得我应该对刚才那个问题的回答补充一点……”然后尽快完成你刚才没有机会完成的观点。

      (2)永远不要在一个问题上纠缠太久。

      这15分钟,或者说整个面试,就是一张你无法先看到整张试卷的试题,有点像GRE的机考,更糟糕的是,你实际上连每道题的分值都不知道。在面试的时候,你不知道你在努力地向面试官说清楚的那个复杂的问题究竟能给你增加多少分,而你花了七八分钟在这个问题上,也可能下一个问题对你来说既简单、分数又多。所以,当一个问题开始出现你很难说清的情况时,不要纠缠太久,简单地说:“关于这个问题,我想我现在只能说出这么多了。”让面试向你的下个机会走去。

      (3)在15分钟内取得尽量多的共识。

      在一般情况下,面试官不是来寻找一个永远的“持异议者”的。当你在回答一些关于观点、价值、方法方面的问题时,你会发现,也许经常会出现面试官频频点头,或者他面无表情,甚至摇头的情况。点头很大程度上说明你们的共识,而通常,共识比异议更容易给你的表现加分。

      熬过了这15分钟后,接下来是你最后的机会了。面试官通常会问你有没有任何问题问他。永远别说没有,除非他之前告诉你他已经决定录用你了。最后的问题可能毁了你之前的所有的努力,也可能把你从一场失败的面试中挽救回来。

      然而想出一个好的、最后的问题往往比准备一个好的自我介绍还要难。有的时候,你希望通过一个好的问题,让人对你刮目相看。但是通常你会发现,更容易的是问一个面试官有话可回答的问题,然后你加上几句评价,把这个面试画上句号。

      如果你之前的面试进行得都很顺利的话,在最后一个问题上应该保守一些,只要不犯错误就行。所以你可以问问面试官怎么走进这一行的,怎么看待这一行等等。如果你之前的面试感觉不佳,你希望通过最后一个问题来绝地反击的话,你不妨问面试官一个让他给你出主意的问题,顺带着你可以说出一个你没有来得及在面试中提起的卖点,加深面试官对你正面的评价。

      比方说,我知道的一个聪明的问题,我的一个好朋友明白自己在面试中的英语口语能力令面试官一直表现得对她缺乏兴趣,于是她最后问道:“您知道,我在高中的时候一直是学俄语的,进入大学后我才从ABC开始学英语,现在刚刚学了3年。虽然我已经可以在托福考试中取得630分的成绩,但我知道我的英语口语还需要很大的提高,您能在这方面给我一些好的指点吗?”

      那位香港长大、哈佛毕业的面试官立刻有些羞涩地说:“不、不,你的英语已经很让人满意了。我是中国人,我的中文说得还没有你的英文好。你只学了3年就已经这么好了,应该是你给我一些指点。”

      结果,这个只学了3年英语的女孩子击败了其他学了十几年英文、口语比她好得多的竞争者——我觉得她就只用了这最后一个问题即确定胜势。
  • 几道经典C语言面试题(转)

    2007-08-23 14:30:50

    一、预处理器(Preprocessor
    1.
    用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
    #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
    考点:
    1). #define
    语法的基本知识(例如:不能以分号结束,括号的使用,等等)
    2).
    懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
    3).
    意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
    4).
    表达式中用到UL(表示无符号长整型)


    2.
    写一个标准MIN,这个宏输入两个参数并返回较小的一个。
    #define MIN(A,B) ((A) <= (B) ? (A) : (B))
    这个测试是为下面的目的而设的:
    1).
    标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
    2).
    三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
    3).
    懂得在宏中小心地把参数用括号括起来
    4).
    讨论下面宏的副作用,例如:当你写下面的代码时会发生什么事?
    least = MIN(*p++, b);


    二、数据声明(Data declarations
    用变量a给出下面的定义
    a)
    一个整型数(An integer
    b)
    一个指向整型数的指针(A pointer to an integer
    c)
    一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer
    d)
    一个有10个整型数的数组(An array of 10 integers
    e)
    一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers
    f)
    一个指向有10个整型数数组的指针(A pointer to an array of 10 integers
    g)
    一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer
    h)
    一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer
    答案是:
    a) int a; // An integer
    b) int *a; // A pointer to an integer
    c) int **a; // A pointer to a pointer to an integer
    d) int a[10]; // An array of 10 integers
    e) int *a[10]; // An array of 10 pointers to integers
    f) int (*a)[10]; // A pointer to an array of 10 integers
    g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
    h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer


    三、Static
    关键字static的作用是什么?
    C语言中,关键字static有三个明显的作用:
    1).
    在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
    2).
    在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    3).
    在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。


    四、Const
    关键字const是什么含意?
    1).
    合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
    2).
    通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
    3).
    关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
    #include <stdio.h>using namespace std;int main(){  const char *pa;    char const *pb;    char ca = 'a';    char cb = 'b';    char * const pc = &ca;    const char * const pd = &cb;    pa = &ca;    pa = &cb;    pb = &ca;    pb = &cb;    *pc = 'd';    printf("ca = %c\n", ca);    return 0;}
    经过以上测试
    const char *pa;
    char const *pb;
    上面两种定义方法一样都是 pa(pb)指向的变量的值不可改变,及*pa,*pb, pa,pb本身是可变的,如:
    pa = &ca; //ok
    ×pa = 'c' //error

    char * const pc = &ca;
    pc
    本身是不可变的(只能在定义时初始化),但指向的变量值是可变的,如
    pc = &ca;  //error
    *pc = 'd'; //ok

    const char * const pd = &cb;
    pd
    本身是不可变的,且指向的变量也是不可变的(只能在定义时初始化)
    pd = &cb;  //error
    *pd = 'c'; /error

    通过以上总结,无论怎样定义p都是一指针
    如果const*左边,表示该指针指向的变量是不可变的
    如果const*右边,表示该指针本身是不可变得


    五、Volatile
    关键字volatile有什么含意 并给出三个不同的例子。
    一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
    1).
    并行设备的硬件寄存器(如:状态寄存器)
    2).
    一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    3).
    多线程应用中被几个任务共享的变量
    这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
    回答以下问题:
    1).
    一个参数既可以是const还可以是volatile吗?解释为什么。
    2).
    一个指针可以是volatile 吗?解释为什么。
    3).
    下面的函数有什么错误:
    int square(volatile int *ptr) {
    return *ptr * *ptr;
    }
    下面是答案:
    1).
    是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
    2).
    是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
    3).
    这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
    int square(volatile int *ptr) {
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
    }
    由于*ptr的值可能被意想不到地该变,因此ab可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
    long square(volatile int *ptr) {
    int a;
    a = *ptr;
    return a * a;
    }


    六、位操作(Bit manipulation
    嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置abit 3,第二个清除a bit 3。在以上两个操作中,要保持其它位不变。
    解答:采用#defines bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
    #define BIT3 (0x1<<3)
    static int a;
    void set_bit3(void) {
    a |= BIT3;
    }
    void clear_bit3(void) {
    a &= ~BIT3;
    }
    一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。
    主要考点:说明常数、|=&=~操作。

     

    七、访问固定的内存位置(Accessing fixed memory locations
    嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
    这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa55;
    一个较晦涩的方法是:
    *(int * const)(0x67a9) = 0xaa55;
    建议采用第一种方法;


    八、代码例子(Code examples
    1.
    下面的代码输出是什么,为什么?(考查有符号类型与无符号类型之间的转换)
    void foo(void) {
        unsigned int a = 6;
    int b = -20;
    (a+b > 6)
    puts("> 6") : puts("<= 6");
    }
    这个问题测试你是否懂得C语言中的整数自动转换原则;
    这无符号整型问题的答案是输出是“>6”
    原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。
    2.
    评价下面的代码片断:(考查是否懂得处理器字长)
    unsigned int zero = 0;
    unsigned int compzero = 0xFFFF;
    /*1's complement of zero */
    对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
    unsigned int compzero = ~0;
    这一问题真正能揭露出应试者是否懂得处理器字长的重要性。好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。


    九、Typedef
    Typedef
    作用是声明一个新的类型名代替已有的类型名;
    也可以用预处理器做类似的事。例如,思考一下下面的例子:
    #define dPS struct s *
    typedef struct s * tPS;
    以上两种情况的意图都是要定义dPS tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
    这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
    dPS p1,p2;
    tPS p3,p4;
    第一个扩展为
    struct s * p1, p2;
    上面的代码定义

  • 失败

    2007-08-04 23:13:35

    第一次上传的文件没人理睬,以失败告终,555555555555555555555555
  • 回题

    2007-07-22 15:32:04

    今天很认真的回了一个技术题,至少我是这么认为,给自己加一分,哈哈

     

Open Toolbar