博文
最简单的MFC程序(2007-01-22 17:23:00)
摘要:#include <afxwin.h>
//定义一个CWinApp的派生类
class CMinApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
//重载CWinApp成员函数InitInstance()
BOOL CMinApp::InitInstance() //应用程序初始化
{
CFrameWnd* pFrame=new CFrameWnd; //动态生成主窗口类对象
pFrame->Create(0,_T("A Minimal MFC Program")); //创建主窗口
pFrame->ShowWindow(SW_SHOWMAXIMIZED); //显示主窗口
pFrame->UpdateWindow(); //刷新主窗口
AfxGetApp()->m_pMainWnd=pFrame; //指定应用程序主窗口
re......
指针专题(2007-01-12 21:51:00)
摘要:一、数组的指针、指针数组以及指向指针的指针
考虑数组的指针的时候我们要同时考虑类型和维数这两个属性。换一句话,就是说一个数组排除在其中存储的数值,那么可以用类型和维数来位置表示他的种类。
A)一维数组
在c和c++中数组的指针就是数组的起始地址(也就第一个元素的地址),而且标准文档规定数组名代表数组的地址(这是地址数值层面的数组表示)。例如:int a[10];
int *p;
p=&a[0]//和p=a是等价的:
因为a是数组名,所以他是该数组的地址,同时因为第一个元素为a[0],那么&a[0]也代表了该数组的地址。但是我们是不是就说一个数组名和该数组的第一个元素的&运算是一回事呢?在一维的时候当时是的,但是在高维的时候,我们要考虑到维数给数组带来的影响。
a[10]是一个数组,a是数组名,它是一个包含10个int类型的数组类型,不是一般的指针变量噢!(虽然标准文档规定在c++中从int[]到int*直接转换是可以的,在使用的时候似乎在函数的参数为指针的时候,我们将该数组名赋值没有任何异样),a代表数组的首地址,在数字层面和a[10]的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。
所以我们要注意以下问题:
(1) p[i]和a[i]都是代表该数组的第i+1个元素;
(2) p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用 *(p+I)和*(a+I)来引用对象元素;
(3)p+1不是对于指针数量上加一,而是表示从当前的位置跳过当前指针指向类型长度的空间,对于win32的int为4byte;
B)多维数组
对于二维数组a[4][6];由于数组名代表数组的起始地址,所以a(第一层)和第一个元素a[0][0]地址的数字是相同的,但是意义却是不同的。对于该数组我们可以理解为:a的一维数组(第一层),它有四个元素a[0]、a[1]、a[2]、a[3](第二层),而每个元素又含有6个元素a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三层),…到此我们终于访问到了每个元素了,这个过程我们经历了:a->a[0]->a[0][0];
整体来讲:a是一个4行5列的二维数组,a表示它......
汇编实验4-查找电话号码(2007-01-07 21:51:00)
摘要:IBM-PC汇编的一个实验:
;the fouth
dataseg segment
namepar label byte
maxnlen db 21
actnlen db ?
_name db 21 dup(?) ;在MASM5.0下不能用name哦
phonepar label byte
maxplen db 9
actplen db ?
phone db 9 dup(?)
crlf db 13,10,'$'
endaddr dw ?
mess1 db 'Input name:','$'
mess2 db 'Input a telephone number:','$'
mess3 db 'Do you want a telephone number?(Y/......
派生类的拷贝构造函数(2006-12-25 19:29:00)
摘要:刚刚弄了一个关于派生类的实验,里面涉及到了派生类的拷贝构造函数,这时才发现自己在这个知识点上还很模糊。在CSDN上面看了下相关的一篇文章后,稍微有了点感觉。现总以一个例子总结如下:
情况(1). 派生类的copy constructor未定义
#include <iostream>
using namespace std ;
class base
{
public:
base() { cout << "base::base()" << endl ; }
base( const base& ) { cout << "base::base( const base&)" << endl ; }
virtual ~base() { cout << "base::~base()" << endl&n......
库组织和容器(2006-12-03 23:15:00)
摘要:哪些东西应该出现在标准库里?一种思想是,程序员应该能在库里找到所有有意思的、重
要的并具有合理普遍性的类、函数、模板等。然而,这里的问题并不是“什么东西应该出
现在某个库里?”而是“什么东西应该出现在标准库里?”说“所有的东西!”是对前一
问题的合理的一阶逼近,但却不是对后一个问题的回答。标准库应该是某种每个实现者都
必须提供的,以至于每个程序员都可以依靠的东西。
C++标准库:
[1]提供了对一些语言特征的支持,例如,对于存储管理和运行时信息的支持。
[2]提供了有关实现所确定的语言方面的一些信息,例如最大的float值。
[3]提供了那些无法在每个系统上由语言本身做出最优实现的函数,如sqrt()和memmove()等。
[4]提供了一些非基本的功能,使程序员可以为可移植而依靠它们,例如表,映射、排序函数和I/O流。
[5]提供了一个为扩展它所提供功能的基本框架。例如,使用户可以按照内部类型I/O的风格为用户定义类型提供I/O机制的规则和支持功能。
[6]为其他库提供了一个公共的基础。
此外,标准库还提供了少量的功能,例如随机数生成器,简单说,就是因为做这些事情很方便,而且也很有用。
这个库的设计主要是由它所扮演的后三种角色所主导,这些角色都是密切相关的。例如,可移植性是对任何特殊的库都适用的一种重要设计准则;而公共容器类型,例如表和映射,又是分别开发的库之间提供方便通信的基础。
从设计的角度看,这里的最后一个角色特别重要,因为它帮助划定了标准库的边界,对它的功能提出了约束。例如,标准库提供了串和表的功能,如果它们不在这里,分别开发的库就只能利用内部类型相互通信。然而,这里就没有提供模式匹配和图形功能,这些功能很明确,使用也非常广泛,但是它们却很少涉足于分别开发的库之间的通信。
除非对于支持这些角色而言,一种功能在某种意义下是必需的,否则就可以将它们留给标准库之外的某些库。无论是好是坏,将某些东西留给标准之外,也给那些针对某一思想提出相互竞争的具体实现的库提供了一个机会。
......
#pragma 预处理指令详解 (2006-10-19 22:26:00)
摘要:在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。
#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。
依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
其格式一般为: #pragma para
其中para为参数,下面来看一些常用的参数。
(1)message 参数
message参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,
这对于源代码信息的控制是非常重要的。其使用方法为:
#pragma message("消息文本")
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,
此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏,
可以用下面的方法:
#ifdef _X86
#pragma message("_X86 macro activated!")
#endif
我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示"_86 macro activated!"。
我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。
......
C/C++ 程序设计员应聘常见面试试题深入剖析(2006-10-05 19:36:00)
摘要:1.引言
本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵。文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见。
许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度,我们能真正写好一个strcpy函数吗?我们都觉得自己能,可是我们写出的strcpy很可能只能拿到10分中的2分。读者可从本文看到strcpy函数从2分到10分解答的例子,看看自己属于什么样的层次。此外,还有一些面试题考查面试者敏捷的思维能力。
分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。
2.找错题
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
试题2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
解答:
试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;
对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字......
指针与数组(2006-08-28 15:18:00)
摘要: 这是一个看似简单,但却不是那么容易搞清楚的问题。以下是在Andrew Koenig的杰作中看到的一些关于数组和指针的讲解,我只作了部分整理。
C语言中指针与数组这两个概念之间的联系是如此密不可分,以至于如果不能理解一个概念,就无法彻底理解另一个概念。
C语言中的数组值得注意的地方有以下两点:
1:C语言只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。然而,C语言中数组的元素可以是任何类型的对象,当然可以是另外一个数组,这样啊,要“仿真”出一个多维数组就不是一件难事。(C99标准允许变长数组(VLA)。GCC编译器实现了变长数组,但是细节与C99标准不完全一致。)
2:对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其他关于数组的操作,哪怕他们看上去是以数组下标进行运算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。一旦我们彻底理解这两点以及他们所隐含的意思,那么理解C语言的数组运算不过就是“小菜一碟”。
对于指针加上一个整数,与给该指针的二进制表示加上同样的整数,两者的含义截然不同,这点大家应该都是清楚的。
下面一个问题是关于指针加减问题的:
如果两个指针指向的是同一个数组中的元素,我们可以把这两个指针相减,这样是有意义的,例如:int *q=p+i;我们可以通过q-p而得到i的值。值得注意的是如果他们指向的不是同一个数组的
元素,即使他们所指向的地址在内存中的位置正好间隔一个数组元素的整数倍,所得的结果仍然是无法保证其正确性的。至于指针相加的情况暂时好象没有发现有。
现在定义一个数组int a[3];如果我们在应该出现指针的地方,却采用了数组名来替换,那么数组名就被当作指向该数组下标为0的元素的指针,这点大家也都很清楚。但是要注意一点,除了a被用做运算符sizeof的参数这一情......
指针数组和数组指针(2006-08-23 01:00:00)
摘要:这个问题大家应该都碰到过,指针数组和数组指针,刚开始看时觉得还是能看懂,但是过些时又搞混了,最后发现还是没有真正理解。
下面就简单说说这两个概念:
一:指针数组,顾名思义,就是说的首先是一个数组吧,然后数组的元素是指针而已。
说明形式为:type *pointer_array[constant1][constant2]...[constantn];
例如:int *pai[3];
由于‘*’是自右向左结合,因此从右向左看,首先看到[4]说明是一个数组,是一个包含4个元素的数组,然后看到‘*’,显然是指针类型,由此可以看出数组中存放的是指针而不是一般的类型。同理,char *pac[2][3]是包含有6个元素,每一个元素都是一个字符型指针。再来说说他们的初始化:
int *pai[3];既然是一个包含4个整形指针的数组那么其对应的将是一个二维整形数组,因为一个整形指针对应一个一维整形数组。
那我就用一个二维整形数组来初始化它,事实上一般也都是这么做的,这里有一个二维数组,int arr[3][2]={{1,2},{3,4},{5,6}},一个三行两列的整形数组,注意这里的行必须和你的指针数组的维数一致,否则是不允许的,不信你可以试试。
这个初始化有很多种选择,以下只列举常见的两中:
第一种也是很好理解的:
for(int i=0;i<3;i++)
pai[i]=arr[i];
显然arr[i]是每一行的首地址,相当于一个一维数组的数组名,如是把它送给一个整形指针pai[i]是理所当然的了。
第二种方法:
在说明指针数组时就初始化:int (*ap)[2]={{1,2},{3,4},{5,6}};哈哈这个不用说了吧。
注意:不能将二维数组的数组名赋给指针数组的数组名,pai=arr(错),因为两者的类型不一致,二维数组名的类型是指向int[][]型的指针,而指针数组的的数组名是指向int *[]类型的指针。
在c/c++语言中,指针数组最常用的场合就是说明一个字符串数组。即说明一个数组,它的每个元素都是一个字符串。
二:数组指针:指向一个数组的指针。
说明形式为:type (*pointer_array)[constant1][constant2]...[......