把握命运,追逐梦想

对自己所做的事要有兴趣,同时还要能够坚持不懈

统计

留言簿(1)

阅读排行榜

评论排行榜

#

关于com聚合 CoCreateInstance的第二个参数

CoCreateInstance的第二个参数是用在聚合时的内部组件创建时使用的,这个参数把外部组件的IUnknown的指针传递给内部组件,内部组件的代理IUnknown按照需要调用这个外部组件的IUnknow接口,或者调用内部组件自己的非代理IUnknown。

posted @ 2009-08-07 09:58 把握命运 阅读(421) | 评论 (0)编辑 收藏

DLL 初始化 以及 MFC DLL

DLL 通常具有在 DLL 加载时必须执行的初始化代码(如分配内存)。使用 Visual C++ 时,在何处添加初始化 DLL 的代码取决于生成的 DLL 类型。如果不需要添加初始化代码或终止代码,则在生成 DLL 时没有什么特别的事情要做。如果需要初始化 DLL,则下表描述了应在何处添加代码。

DLL 类型

添加初始化代码和终止代码的位置

规则 DLL

在 DLL 的 CWinApp 对象的 InitInstanceExitInstance 中。

扩展 DLL

在“MFC DLL 向导”生成的 DllMain 函数中。

非 MFC DLL

在您提供的称为 DllMain 的函数中。

在 Win32 中,所有 DLL 都可能包含一个可选的入口点函数(通常称为 DllMain),初始化和终止时都要调用此函数。这使您有机会在需要时分配或释放其他资源。Windows 在四种情况下调用入口点函数:进程附加、进程分离、线程附加和线程分离。

C 运行时库提供了一个名为 _DllMainCRTStartup 的入口点函数,并调用 DllMain。根据 DLL 类型的不同,应在源代码中包含一个名为 DllMain 的函数,或应用 MFC 库中提供的 DllMain

为初始化非 MFC DLL,DLL 源代码必须包含一个名为 DllMain 的函数。下列代码显示了一个基本主干,说明 DllMain 定义的大概样子:

 

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved)
{
    
switch( ul_reason_for_call ) {
    
case DLL_PROCESS_ATTACH:
    
    
case DLL_THREAD_ATTACH:
    
    
case DLL_THREAD_DETACH:
    
    
case DLL_PROCESS_DETACH:
    
    }

    
return TRUE;
}



posted @ 2009-08-04 00:08 把握命运 阅读(1169) | 评论 (0)编辑 收藏

C语言项目练习

C语言编程练习
题目: 
A出版社、B出版社是图书出版发行领域的巨头,A出版社出版的书籍种类涉及科技、
外文、社科、卫生、生活、体育等方面;B 出版社出版的书籍种类涉及科技、社科、卫生、
生活、体育、教育等方面。 
C 书店、D书店、E 书店是 
3 家著名的图书销售商,C 书店以销售科技类书图书闻名,
同时也销售外文、教育类书籍;D书店以销售外文书籍店闻名,同时兼营科技、社科、教育
类书籍;E 书店为销售图书种类最完全而著名,书籍种类包括科技、外文、社科、卫生、生活、体育、教育等方面。 
F、G是两个典型的图书购买者(图书用户),定期或不定期的去 E 书店买书;其中 F
是一个个人用户,对科技、体育、生活类图书非常感兴趣,对这 
3 类图书是逢书必买;G是一个单位用户,它对所有类的图书都感兴趣。 
 
实体 A、B、C、D、E、F、G工作过程参见附一。 
各个实体的初始化描述参见附二

题目要求: 
请在Window下的VC6.0环境下,使用Win32 Console Application方式并采用多线程编程方式来模拟实体 A、B、C、D、E 之间的工作过程。 

具体要求: 
1.出版社、书店、图书用户作为独立的单位,各自内部信息相互保密,一般不随意暴露: 
 
2.出版社给书店提供以下接口: 
注册接口: 供书店用户登陆注册自己的信息,便于发定购通知; 
参数信息:  书店 ID、 
书店经营图书的种类、 
通知的 Callback 函数 
等等 
查询接口: 供书店用户定购前查询; 
参数信息:  图书种类 
查询种类(全部、新书、再版) 
查询结果返回 
等等 
定购接口: 供书店来定购书籍; 
参数信息:  书店 ID 
           图书名 
           购买数量 
           联络方式的 Callback(上次不足图书的再版通知) 
           等等 

3.书店(特别是 E 书店)给图书购买者提供以下接口:
查询接口: 供图书购买者购买前进行查询; 
参数信息: 图书种类
查询种类(全部、新书、再版) 
查询结果返回 
等等 
购买接口: 供图书购买者进行购买; 
参数信息: 购买者ID 
图书名称 
购买数量 
联络方式的Callback(上次不足图书的到货通知) 
等等

4.在主线程中,控制各个实体的初始化、上述模拟活动的开始和停止; 
5.出版社、书店、图书购买的工作活动按照时间顺序输出到文件work.txt中; 
6.为了验证程序执行的正确性,各个实体(A、B、C、D、E、F、G)都应记载数据, 
出版社应记录: 出版(再版)书目、 库存量、销售量、销售明细(每次销售给那个书店多少册)、定购书目数量以及明细(每次向谁定购了什么书、多少本)、销售书目数量以及明细 
图书购买者:记录购买书目数量以及明细。
以上信息每隔30秒输出一次,以便于核对程序执行的正确性。 
7.程序要考虑使用良好的程序结构和数据结构、程序讲求效率。


附一A、B、C、D、E的工作描述 
一、关于出版社工作 
1.1出版 
出版类型: 
出版图书类型:新书、再版(主要是由于销售好而再版);

出版数量:
新书出版的数量
A、B出版社:每隔10秒出版一种新图书,每次1000册,即
A出版图书的顺序为:科技(
1000->外文(1000->社科(1000->卫生(1000->生活(1000->体育(1000->科技(1000); 

B出版图书的顺序为:科技(
1000->社科(1000->卫生(1000->生活(1000->体育(1000->教育(1000->科技(1000

再版图书的数量以及再版 
当出现缺货时进行再版,每个书再版的数量为 
1)再版500册(当缺货数量<=500册时); 
2)大于缺货数量并为1000的整数倍(当缺货数量>500册时); 再版请求要进行管理,每次再版不花时间。 

出版书目相关信息 书目信息包括:编号、书名、种类、出版社等。
1.2发行(销售) 
具体工作包括: 
发行通知: 出版新书,向所有订阅此分类的书店通知, 再版,只通知订购此种图书但因缺货没买到书的书店。
接受书店定购:如有货,则发货 否则,存货部分进行销售(同步完成),剩余部分转再版处理(异步完成); 并且定购接口中,要有书店的信息,以便于再版后的通知(对上次购买不足的书店)。

1.3提供书目查询服务
提供向书店提供书目查询服务,查询分类查书目、库存等。 
提供查询希望能够讲求效率。


二、关于书店工作 
2.1定购工作 
定购分类两类:一类是主动定购、另一类是被动定购; 
被动定购:接到书店定购通知后去定购; 
主动定购:当前书店销售库存为0,而发生的定购; 
每次定购不限于一种图书。 
定购前,应该进行相关书目信息的查询。

E书店接到新书通知后每次订购200册

如果书店定购的图书,出版社货不足,则库存有多少购买多少,不足部分等到图书再版后通知再购买。(例如要购买500本,而库存只有300本,则先购300本,剩下200本等到再版后再购买)


三、关于图书购买者
G是一个单位用户,对科技、外文、社科、卫生、生活、体育、教育类图书都感兴趣,不定期从E书店购买新书,每次购买的数量是一个随机数(小于500); 这里的不定期可以认为G每隔几秒(小于8的随机数)到E书店查询一次,看看是否有新书,如果有新书则一定购买新书,否则随机购买一种原有的书,如果货物不足,则库存有多少购买多少,不足部分等到书店通知到货后再购买。(例如要购买50本,而库存只有30本,则先购30本,剩下20本等到书店到货后再购买)

附二 系统的初始化描述 A出版社、B出版社、 C书店、 D书店、 E书店、F图书购买者、G图书购买者初始的数据都为空。 活动开始的顺序为:
1.    A、B出版社开始出书
2. 出版后,出版社通知注册的书店(C、D、E),来定购; 
3. 书店定购后,开始图书销售; 
4. 图书购买者(G)定期到书店买书; 

练习要求:先模拟出版社A,书商E,图书购买者G的交易过程,其余待完善

posted @ 2009-08-03 17:13 把握命运 阅读(736) | 评论 (0)编辑 收藏

extern "C" __declspec(dllexport) __declspec(dllimport) 和 def

前面的extern "C"  __declspec(dllexport)  __declspec(dllimport)都是用于函数或者变量,甚至类的声明的(可以把extern "C"放在class的前面,但是编译器会忽略掉,最后产生的还是C++修饰符,而不是C修饰符)这样的用法有个好处就是下面的代码可以在混有类的函数和变量上使用下面的宏,虽然对类不起作用:
#ifdef __cplusplus
extern "C"
{
//函数声明
//变量声明,变量一般前面都有extern
//类声明,这个不起作用,编译器直接忽略掉class前面的extern “C”
#ifdef __cplusplus
}

#endif
C 和C++ 对应不同的调用约定,产生的修饰符也各不相同,如下:
调用约定 extern "C" 或 .c 文件 .cpp、.cxx 或 /TP

C 命名约定 (__cdecl)

_test

?test@@ZAXXZ

Fastcall 命名约定 (__fastcall)

@test@0

?test@@YIXXZ

标准调用命名约定 (__stdcall)

_test@0

?test@@YGXXZ


__declspec(dllexport)  __declspec(dllimport)一般也是使用宏的形式:
#ifdef ONEDLL_EXPORTS
#define ONEDLL_API __declspec(dllexport)
#else
#define ONEDLL_API __declspec(dllimport)
#endif
这样在DLL代码本身就是__declspec(dllexport) ,在使用DLL的程序中就变成了__declspec(dllimport),这两标志分别用来指明当前的函数将被导出,和当前函数是被导入的。
 

上面的两个宏结合一下就是下面这样的了:
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 ONEDLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// ONEDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef ONEDLL_EXPORTS
#define ONEDLL_API __declspec(dllexport)
#else
#define ONEDLL_API __declspec(dllimport)
#endif

// 此类是从 OneDll.dll 导出的
#ifdef __cplusplus
extern "C"
{
#endif
class ONEDLL_API COneDll {
public:
    COneDll(
void);
    
~COneDll(void);
    
    
// TODO: 在此添加您的方法。
    int m_a;
    
int m_b;
    
int *m_p;
    
int m_n;

    
void AddValue();

}
;

extern ONEDLL_API int nOneDll;

ONEDLL_API 
int fnOneDll(void);

#ifdef __cplusplus
}

#endif

如果调用模块和被调用模块都是C++(而且是同一种编成环境,如VC,甚至需要同一版本的VC),那么就不需要extern “C”了,因为这个标志的作用就是用在函数和变量声明前,无论是调用模块,还是被调用模块,都将生成C修饰符,调用模块将需要C修饰符的函数,而被调用模块将产生C修饰符的函数,所以这个标志在两者都是C++的时候使用并不受影响,不使用这个标志,也不受影响。
但是如果C模块要调用C++ 模块,那么C++模块就需要使用extern “C”,当然C不用,由于是在头文件的声明中使用,所以使用下面的宏能够使得这个头文件也在C中顺利使用:
#ifdef __cplusplus
extern "C"
{
//函数声明
//变量声明,变量一般前面都有extern
//类声明,这个不起作用,编译器直接忽略掉class前面的extern “C”
#ifdef __cplusplus
}

#endif

如果C++模块要调用C模块,那么C++模块还是需要extern “C”,当然C不用,由于是在头文件的声明中使用,所以使用上面的宏同样能够使得这个头文件也在C中顺利使用。

总结一下就是加上extern “C”在什么情况下都没错,但是要注意函数重载的问题。



def文件是一种比较麻烦的方法,下面是MSDN中的部分内容:
 

模块定义 (.def) 文件是包含一个或多个描述 DLL 各种属性的 Module 语句的文本文件。如果不使用 __declspec(dllexport) 关键字导出 DLL 的函数,则 DLL 需要 .def 文件。

.def 文件必须至少包含下列模块定义语句:
1.文件中的第一个语句必须是 LIBRARY 语句。此语句将 .def 文件标识为属于 DLL。LIBRARY 语句的后面是 DLL 的名称。链接器将此名称放到 DLL 的导入库中。
2.EXPORTS 语句列出名称,可能的话还会列出 DLL 导出函数的序号值。通过在函数名的后面加上 @ 符和一个数字,给函数分配序号值。当指定序号值时,序号值的范围必须是从 1 到 N,其中 N 是 DLL 导出函数的个数。

例如,包含实现二进制搜索树的代码的 DLL 看上去可能像下面这样:

LIBRARY   BTREE
EXPORTS
   Insert   @
1
   Delete   @
2
   Member   @
3
   Min   @
4

提示:

如果希望优化 DLL 文件的大小,请对每个导出函数使用 NONAME 属性。使用 NONAME 属性时,序号存储在 DLL 的导出表中而非函数名中。如果导出许多函数,这样做可以节省相当多的空间。


其实__declspec(dllexport)的作用就是让编译器按照某种预定的方式(前面大致解释了这种方式的规则)来输出导出函数及变量的符号,而def文件则是自己为每一个函数和变量指定导出符号,所以def是一个非自动化,手工很强的方式,不是特殊情况的话,实在没有必要浪费这些时间。
还有一个问题,就是使用def会把调用方式和__declspec(dllexport)的作用全部覆盖掉,所以还需要自己处理调用方式不同产生的错误。
一般使用def文件的情况是你需要使用运行时加载,并且需要使用GetProcAddress函数获得函数地址,这个函数需要直接指明函数产生的导出符号,而可以自己指定导出符号的方式就是使用def。
def文件的具体语法可以看看msdn。

posted @ 2009-08-03 17:12 把握命运 阅读(18436) | 评论 (0)编辑 收藏

一个C++DLL的简单例子

     摘要:   // PureApp.cpp : 定义应用程序的入口点。//// Windows 头文件:#include <windows.h>// C 运行时头文件#include <stdlib.h>#include <malloc.h>#include&n...  阅读全文

posted @ 2009-08-03 15:41 把握命运 阅读(1983) | 评论 (0)编辑 收藏

scanf在循环里的特殊用法

#include<stdio.h>

int func(float ar[],float *aver,int num);
int main()
{
    printf(
"输入人数:");
    
int n = 0;
    scanf(
"%d",&n);
    
float * pAr =new float[n];
    printf(
"输入所有成绩,空格隔开:");
    
for(int i = 0; i<n; i++)
    
{
        scanf(
"%f",&pAr[i]);
    }


    
float aver = 0;
    
int num  =func(pAr,&aver,n);

    printf(
"不及格的人数是%d,平均分是%f",num,aver);


}


int func(float ar[],float *aver,int num)
{
    
float sum = 0
    
for(int i = 0; i<num; i++)
    
{
        sum
+= ar[i];
    }

    
*aver =  sum/num;
    
int n = 0;
    
for(int i = 0; i<num; i++)
    
{
        
if(ar[i]<sum/num)
        
{
            n
++;
        }

    }

    
return n;
}

posted @ 2009-08-03 13:41 把握命运 阅读(214) | 评论 (0)编辑 收藏

绕圆相遇问题

#include<stdio.h>
int main()
{
    printf(
"请输入A坐标 A速度 B坐标 B速度 纬线L长\n");
    
int apos,aspeed,bpos,bspeed,l;
    scanf(
"%d %d %d %d %d",&apos,&aspeed,&bpos,&bspeed,&l);

    
for(int i = 1!(((apos+i*aspeed)%== apos) && ((bpos+i*bspeed)%== bpos)); i++)
    
{
        
if((apos+i*aspeed)%== (bpos+i*bspeed)%l)
        
{
            printf(
"\n需要跳%d次\n",i);
        }


    }






    printf(
"无法会面");
    
return 0;
}

posted @ 2009-08-03 11:22 把握命运 阅读(186) | 评论 (0)编辑 收藏

传递指针引用

#include<stdio.h>

void find1(char arr[],char search,char*&pa);

int main()
{
    
int i = 20;
    
int *pi = &i;
    
int **ppi =&pi;
    printf(
"%d\n%d\n%d",i,pi,ppi);

    
char a[]="adgdsgsdg";
    
char *pa;
    find1(a,
'd',pa);
    printf(
"%c",*pa);
    
return 0;
}


void find1(char arr[],char search,char*&pa)
{
    
int i;
    
for( i =0;*(arr+i)!= '\0';i++)
    
{
        
if(*(arr+i)==search)
        
{
            pa 
= arr+i;
            
break;
        }

        
else if(*(arr+i)== 0)
        
{
            pa 
= 0;
            
break;
        }

    }

}

posted @ 2009-08-03 10:02 把握命运 阅读(116) | 评论 (0)编辑 收藏

航空订票小程序

     摘要: #include<stdlib.h>#include<stdio.h>#include<memory.h>#define NOSMOKE 10#define SMOKE 10struct PlaneSeat{    int noSmoke[NOSMOKE];&nb...  阅读全文

posted @ 2009-07-30 15:34 把握命运 阅读(174) | 评论 (0)编辑 收藏

很奇怪,input1和input2总是相同

#include<memory.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>

int main()
{
    
char * input1 ,*input2;
    input1 
= (char*)malloc(100);
    strcpy(input1,
"this is string1");
    printf(
"%s\n",input1);

    free(input1);

    input2 
= (char*)malloc(20);
    strcpy(input2,
"this is string2");
    printf(
"%s\n",input2);

    
if(input1 != NULL)
    
{
        strcpy(input1,
"hello world");
    }


    printf(
"%s\n",input1);
    printf(
"%s\n",input2);

    
return 0;
}

posted @ 2009-07-30 14:21 把握命运 阅读(342) | 评论 (1)编辑 收藏

仅列出标题
共5页: 1 2 3 4 5