博文

select函数详解及应用(2008-10-31 21:26:00)

摘要:Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、 accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。下面详细介绍一下!

Select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明):

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

先说明两个结构体:

第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来操作,比如清空集合 FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set *),将一个给定的文件描述符从集合中删除FD_CLR(int ,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。一会儿举例说明。

第二,struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。

具体解释select的参数:

int maxfdp是一个整......

阅读全文(6190) | 评论:1 | 复制链接

利用结构体返回多个函数值(2008-10-24 23:53:00)

摘要:#include <iostream.h>
#include <malloc.h>
#include <string.h>

typedef struct student
{
    char name[10];
    int age;
}Student;

Student* fun1()
{
    Student* ps = new Student;
    strcpy(ps->name, "zhong");
    ps->age  = 0x100;
    return ps;
}

void main()
{
    Student* ps=fun1();  
    cout<<"name:"<<ps->name<<"\t"<<"age:"<<hex<<(*ps).age<<endl;
    delete ps;
}
一般的函数只能由一个返回值
如何同时返回 name 和age 呢?
我们可以将其封装到一个结构体中,这样就可以通过结构体的方式同时返回这两个参数

注意:每次使用了fun1后,一定要释放其内部声请的内存空间
比如本程序中的 delete ps; ,否则将造成内存泄漏

......

阅读全文(3008) | 评论:0 | 复制链接

强制CPU开始新的周期的方法(2008-09-18 01:02:00)

摘要:#include <afx.h>
#include <stdio.h>

void GetCylc( unsigned int *lowPart, unsigned int *highPart )
{
    __asm {
        cpuid         // 强制CPU开始新的周期
        mov ecx, lowPart;
        mov ebx, highPart;
        rdtsc
        mov [ecx], eax;
        mov [ebx], edx;
    }
}

unsigned int lowPart1, lowPart2, highPart;

int main()
{
    char *s1 = "2o3i4jiojrewjeroiksopf";

    GetCylc( &lowPart1, &highPart );

    for(int i1=0;s1[i1]!=0;i1++)
        printf("%c",s1[i1]);
    printf("\n");

    CString s2 = "2o3i4jiojrewj......

阅读全文(2448) | 评论:0 | 复制链接

memcpy函数的正确调用方法(2008-09-04 12:33:00)

摘要:memcpy函数的正确调用方法
memcpy函数的一般调用方法为"memcpy(dest,src,n);".
其功能为把源串src中前n个字符拷贝到目的串dest中,因此目的串de
st的最后长度应是n.当目的串为空或目的串原来的长度不大于n时,
memcpy的结果是正确的,而当目的串原来的长度大于n时则调用memcp
y函数后得到的结果是错误的,如例2所示.
例2.编制memcpy函数演示程序
#include<stdio.h>
#include<mem.h>
#include<string.h>
void main(void)
{int i;
static char dest[7]="First";
static char src[]="Second";
printf("\nTarget string 1 is :%s",dest);
memcpy(dest,src,3);
printf("\nTarget string 2 is :%s",dest);
memcpy(dest,src,strlen(src));
printf("\nTarget string 3 is :%s",dest);
}
本程序输出结果应为:Target string 1 is:First
Target string 2 is:Sec
Target string 3 is:Second
但实际输出结果却是:Target string 1 is:First
Target string 2 is:Secst
Target string 3 is:Second
显然,如此调用memcpy函数有时会得到错误的结果.若用如下语
句代替"memcpy(dest,src,n);"语句,即可得到正确的结果.
if(strlen(dest)>n)
{for(i=0;dest[i]!='\0';i++)
dest[i]=' ';/*将dest赋空格*/
dest[i]='\0';
memcpy(dest,src,n);
}
el......

阅读全文(9909) | 评论:0 | 复制链接

VC中检测内存泄露的代码(2008-08-31 16:26:00)

摘要:/*----------------------------------------------------------------
VC中检测内存泄露的代码:
在申请了动态内存空间后常常会忘记在不用的时候释放,这样会造成内存的浪费等其他问题。
怎样检查你的代码有没有内存泄露呢? 需要在前面加上这些代码:

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <string.h>
#include <stdio.h>

#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

然后在要检测的代码前面加上:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
在后面加上:
_CrtDumpMemoryLeaks();
-------------------------------------------------------------------*/

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <string.h>
#in......

阅读全文(3249) | 评论:0 | 复制链接

ofstream 对象的使用注意点(2008-08-31 09:12:00)

摘要:// VS6 2008/8/30

#include <iomanip>
#include <fstream>
#include <iostream>
using namespace std;

struct data{
    unsigned type    :    2 ;
    unsigned d        :    1 ;
    unsigned context:    5 ;
};

// ofstream 对象不能复制,只能引用传参
void fprint(ofstream &file,struct data t)
{
    int temp = (t.type<<6) + (t.d<<5) + t.context;
    if (temp<16)
    {
        file<<hex<<0 ;
    }
    file<<hex<<temp<<endl ;
}

int main(void)
{
    int j;
    ofstream fsOut("TestData.dat");
    
    for(j=0;j<16;j++)
    {
   &nb......

阅读全文(2085) | 评论:0 | 复制链接

测试程序效率的方法(2008-08-30 15:00:00)

摘要:http://1001night.blogbus.com/logs/17125497.html 光看书似乎不解决问题,难道要做题 当然要做题,而且做题也要循序渐进。 首先是教材正文中的示例,然后是书后的练习题。 第二步可以做国家等级考试二级三级的C语言题。在线上可以找到,大量二级题库。三级题推荐南开的三级100题。此外VCgood群的共享文件中也有一些这一难度的题目。 正如前面讲过,当第二步的题目都做完后,语法已经不是问题,应该开始学习数据结构和算法。这个方面的练习题可以去各大OJ。OJ是什么,请看下一节。 OJ是什么 OJ是OnlineJudge的缩写。OnlineJudge是一种在线裁判系统。她可以对程序原代码进行编译和执行,并通过预先设计的测试数据来检验程序原代码的正确性。 首先,他是一个在线的题库,有很多习题,你可以任选其中之一来解答。然后,系统的编译器能够编译执行你所提交的代码。如果编译通过,针对每个题目,系统将使用自带的多组测试数据检验你的程序,如果程序都能得到正确的输出,那么你顺利地解决了这个问题。最后,系统还能对所有参与答题的用户进行统计和排名。 OJ的题目大部分是关于算法的。题目的输入输出通常是命令行方式,而非图形界面。也就是说,要关注的不是平台的兼容性、文件的格式抑或窗口的布置这种无关紧要的细节,而是问题本身的逻辑实现。一个用户提交的程序在Online Judge系统下执行时将受到比较严格的限制,包括运行时间限制,内存使用限制和安全限制等。用户程序执行的结果将被Online Judge系统捕捉并保存,然后再转交给一个裁判程序。该裁判程序或者比较用户程序的输出数据和标准输出样例的差别,或者检验用户程序的输出数据是否满足一定的逻辑条件。最后系统返回给用户一个状态,通过、错误、超时、溢出或是无法编译。 Online Judge系统来自ACM和IOI大赛。由美国计算机协会(ACM Association for Computing Machinery)发起和组织的ACM国际大学生程序设计竞赛(简称ACM/ICPC)是目前世界上规模最大的计算机学科赛事。IOI则是国际信息学奥林匹克竞赛,和数学奥林匹克竞赛一样著名。Online Judge系统是IOI或A......

阅读全文(2786) | 评论:0 | 复制链接

避免窗口一闪而过(2008-08-03 21:11:00)

摘要: 大家知道,调试C语言程序的时候,点下run后,运行结果往往闪了一下就消失了,这是因为我们调试的程序都不大,所以基本上都来不及看结果,窗口就自动关闭了,这时可以在主程序的返回之前加上getch(),就可以了,按下任意键后窗口才关闭。 但是在dev C++环境下调试C++程序,学着加上getch(),提示错误,但我们可把原来的getch()以cin.get()替换就可以获得同样效果了 如下所示: #include #include using namespace std; int main(int argc, char *argv[]) { system("PAUSE"); //getch(); cin.get(); return EXIT_SUCCESS; } 其实只是上面用了C++ 的一些函数库不包含getch()而已,如果我们仍来使用C的函数库,在dev C++环境下也是可以使用的,如下: #include #include int main(int argc, char *argv[]) { system("PAUSE"); getch(); //cin.get(); return EXIT_SUCCESS; }......

阅读全文(2747) | 评论:0 | 复制链接

虚基类的用法(2008-07-29 23:58:00)

摘要:虚基类的用法 原文: http://www.3800hk.com/Article/cxsj/vc/zhlbcvc/2005-08-06/Article_31730.html 在《多继承》中讲过的例子中,由类A,类B1和类B2以及类C组成了类继承的层次结构。在该结构中,类C的对象将包含两个类A的子对象。由于类A是派生类C两条继承路径上的一个公共基类,那么这个公共基类将在派生类的对象中产生多个基类子对象。如果要想使这个公共基类在派生类中只产生一个基类子对象,则必须将这个基类设定为虚基类。 虚基类的引入和说明 前面简单地介绍了要引进虚基类的原因。实际上,引进虚基类的真正目的是为了解决二义性问题。 虚基类说明格式如下: virtual 其中,virtual是虚类的关键字。虚基类的说明是用在定义派生类时,写在派生类名的后面。例如: class A { public: void f(); protected: int a; }; class B : virtual public A { protected: int b; }; class C : virtual public A { protected: int c: }; class D : public B, public C { public: int g(); private: int d; }; 由于使用了虚基类,使得类A,类B,类C和类D之间关系用DAG图示法表示如下: A{ f(), a } / \ B{b} C{c} \ / D{g(),d} 从该图中可见不同继......

阅读全文(1996) | 评论:0 | 复制链接

清除进程(2008-06-30 23:03:00)

摘要:最近在写程序时碰到这样一个问题:我想将文件备份到网络驱动器上,但是有一些文件正在被其它程序使用,处于打开状态,而且是被独占打开,这时是没法对文件进行备份操作的。因此,要想备份这些文件,必须将打开它们的那些进程kill掉。那么如何干净地杀死这些打开文件的进程呢?相信看完本文后,自然会有办法解决! 其实,在较新的Windows操作系统版本中有一个工具程序叫tskill.exe,用它就可以解决问题。如图一所示: 11.gif (9.91 KB) 2008-6-30 14:38 图一 tskill程序 要杀掉某个程序的进程,可以输入下面的命令便可以杀死其运行实例: tskill 程序名 但是我想在自己写的代码里实现tskill的功能该如何做呢?最安全的杀死进程的方法是向运行程序的主窗口发送WM_CLOSE消息。 HWND hwnd = // 获得主窗口 PostMessage(hwnd, WM_CLOSE, 0, 0); 发送此消息后,通常应该等待直到进程确实终止: HANDLE hp = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid); WaitForSingleObject(hp, 5000); // 等待5秒 当进程终止时,它发出状态信号,并且 WaitForSingleObject 返回WAIT_OBJECT_0。如果返回别的值,进程要么挂起了,要么仍然在进行处理。在这种情况下,杀死这个进程的唯一方法是用功能更强大的 TerminateProcess: if (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0) TerminateProcess(hp,0); 如果想干得漂亮一点,可以在关闭之前向主窗口发送一个WM_QUERYENDSESSION消息。当用户结束会话(log out)或者有人调用ExitWindows时,应用程序会收到这个消息。然后准备即将来临的死亡。此时一般都会弹出一个确认对话框,告诉世人:“我要完蛋了,如果要保存修改的东西,现在是最佳时机,想保存吗?”有三种选择(Yes/No/Cancel)。此外,WM_QUERYENDSESSION甚至可以拒绝死亡(按下"C......

阅读全文(2186) | 评论:0 | 复制链接