分享

系统架构 | 架构(architecture.riaos.com) | Page 271

 astrotycoon 2013-09-03

Category Archives: 系统架构

系统架构

linux新的API signalfd、timerfd、eventfd使用说明——timerfd

Posted on

看一下timerfd的例子,上代码:

#include <sys/timerfd.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>        /* Definition of uint64_t */

#define handle_error(msg) 
	   do { perror(msg); exit(EXIT_FAILURE); } while (0)

void printTime()
{  
	struct timeval tv;  
	gettimeofday(&tv, NULL);  
	printf("printTime:  current time:%ld.%ld ", tv.tv_sec, tv.tv_usec);
}

int main(int argc, char *argv[])
{
   struct timespec now;
   if (clock_gettime(CLOCK_REALTIME, &now) == -1)
	   handle_error("clock_gettime");

   struct itimerspec new_value;
   new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
   new_value.it_value.tv_nsec = now.tv_nsec;
   new_value.it_interval.tv_sec = atoi(argv[2]);
   new_value.it_interval.tv_nsec = 0;

   int fd = timerfd_create(CLOCK_REALTIME, 0);
   if (fd == -1)
	   handle_error("timerfd_create");

   if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
	   handle_error("timerfd_settime");

   printTime();
   printf("timer startedn");
   
   for (uint64_t tot_exp = 0; tot_exp < atoi(argv[3]);) 
   {
       uint64_t exp;
	   ssize_t s = read(fd, &exp, sizeof(uint64_t));
	   if (s != sizeof(uint64_t))
		   handle_error("read");

	   tot_exp += exp;
	   printTime();
	   printf("read: %llu; total=%llun",exp, tot_exp);
   }

   exit(EXIT_SUCCESS);
}

相关结构体如下:

struct timespec {
   time_t tv_sec;                /* Seconds */
   long   tv_nsec;               /* Nanoseconds */
};

struct itimerspec {
   struct timespec it_interval;  /* Interval for periodic timer */
   struct timespec it_value;     /* Initial expiration */
};

代码L25-L29:初始化定时器的参数,初始间隔与定时间隔。

L32:创建定时器fd,CLOCK_REALTIME:真实时间类型,修改时钟会影响定时器;CLOCK_MONOTONIC:相对时间类型,修改时钟不影响定时器。

L35:设置定时器的值。

L44:阻塞等待定时器到期。返回值是未处理的到期次数。比如定时间隔为2秒,但过了10秒才去读取,则读取的值是5。

编译运行:编译时要加rt库(g++ -lrt timerfd.cc -o timerfd)

[root@localhost appTest]# ./timerfd 5 2 10
printTime:  current time:1357391736.146196 timer started
printTime:  current time:1357391741.153430 read: 1; total=1
printTime:  current time:1357391743.146550 read: 1; total=2
printTime:  current time:1357391745.151483 read: 1; total=3
printTime:  current time:1357391747.161155 read: 1; total=4
printTime:  current time:1357391749.153934 read: 1; total=5
printTime:  current time:1357391751.157309 read: 1; total=6
printTime:  current time:1357391753.158384 read: 1; total=7
printTime:  current time:1357391755.150470 read: 1; total=8
printTime:  current time:1357391757.150253 read: 1; total=9
printTime:  current time:1357391759.149954 read: 1; total=10
[root@localhost appTest]#

第一个参数5为第一次定时器到期间隔,第二个参数2为定时器的间隔,第三个参数为定时器到期10次则退出。程序运行(5+2*10)S退出。

详细信息可以:man timerfd_create

System.out.println()输出到文件

Posted on
import java.io.FileNotFoundException;

import java.io.PrintStream;public class TestSystemOut {public static void main(String[] args) throws FileNotFoundException {System.setOut(new PrintStream("f:/test.txt"));System.out.println("Hello World");}}


输出到多个地方.

如: console和文件

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;

public class MultiOutputStream extends OutputStream {
	private List<OutputStream> outputStreams;

	public MultiOutputStream(List<OutputStream> outputStreams) throws IOException {
		super();

		if (CollectionUtils.isEmpty(outputStreams)) {
			throw new IOException("must set one OutputStream at least!");
		}

		this.outputStreams = outputStreams;
	}

	@Override
	public void write(int b) throws IOException {
		for (OutputStream outputStream : outputStreams) {
			outputStream.write(b);
		}
	}

}

			List<OutputStream> outputStreams = new ArrayList<OutputStream>();
			outputStreams.add(System.out);
			outputStreams.add(new FileOutputStream("../test.out"));
			MultiOutputStream multiOutputStream = new MultiOutputStream(outputStreams);
			System.setOut(new PrintStream(multiOutputStream));

C语言实现的trim函数str_trim

Posted on

#include <string.h>

#include <ctype.h>

 

char * str_trim_len(char * input, int len)
{
    char *head=input;
    char *tail=input + (len – 1);
   
    if (len <=0) return NULL;

    while (len >0 && !(isgraph(*head)))
    {
        head++;
        len–;

    }
    if (len <=0) return NULL;
   
    while (len >0 && !(isgraph(*tail)))
    {
        *tail=”;
        tail–;
        len–;

    }
    if (len <=0) return NULL;

    return head;

}

char * str_trim(char * input)
{
    return str_trim_len(input, strlen(input));
}

 

写递归函数的正确思维方法

Posted on

写递归函数的正确思维方法

递归是编程中一个相对难以理解但是却又很重要的概念. 对于从命令式语言开始学习编程的程序员天生对此有理解缺陷, 而对于从类似C++这种对函数式编程范式不友好的语言开始学习编程的程序员就更加如此了.(比如我自己) 碰巧(其实不巧)最近在读这本书(这本书国内没有引进, 网上只有巨贵的亚马逊卖的原版,
我读的是网上的中文版), Paul Graham在书中讲述的如何写递归函数的部分, 让我印象深刻. 因为原书是讲Lisp的, 当然这个部分也是用Lisp作为例子描述的, 考虑到国内会看这本书的人太少,
能看懂Lisp的就更不多了, 我这里根据自己的理解, 重新整理一下. 最重要的是, 书中原来的例子太少, 太简单, 我自己提供了一些额外的, 并且更加复杂的例子. 以期对问题能有更好的理解.

什么是递归

迭代的是人,递归的是神
–L. Peter Deutsch

简单的定义: “当函数直接或者间接调用自己时,则发生了递归.” 说起来简单, 但是理解起来复杂, 因为递归并不直观, 也不符合我们的思维习惯, 相对于递归, 我们更加容易理解迭代. 因为我们日常生活中的思维方式就是一步接一步的, 并且能够理解一件事情做了N遍这个概念. 而我们日常生活中几乎不会有递归思维的出现.
举个简单的例子, 即在C/C++中计算一个字符串的长度. 下面是传统的方式, 我们一般都这样通过迭代来计算长度, 也很好理解.

size_t length(const char *str) {
  size_t length = 0;
  while (*str != 0) {
    ++length;
    ++str;
  }

  return length;
}

而事实上, 我们也可以通过递归来完成这样的任务.

size_t length(const char *str) {
  if (*str == 0) {
    return 0;
  }
  return length(++str) + 1;
}

只不过, 我们都不这么做罢了, 虽然这样的实现有的时候可能代码更短, 但是很明显, 从思维上来说更加难以理解一些. 当然, 我是说假如你不是习惯于函数式语言的话. 这个例子相对简单, 稍微看一下还是能明白吧.
迭代的算法可以这样描述: 从第一个字符开始判断字符串的每一个字符, 当该字符不为0的时候, 该字符串的长度加一.
递归的算法可以这样描述: 当前字符串的长度等于当前字符串除了首字符后, 剩下的字符串长度+1.
作为这么简单的例子, 两种算法其实大同小异, 虽然我们习惯迭代, 但是, 也能看到, 递归的算法无论是从描述上还是实际实现上, 并不比迭代要麻烦.

理解递归

在初学递归的时候, 看到一个递归实现, 我们总是难免陷入不停的回溯验证之中, 因为回溯就像反过来思考迭代, 这是我们习惯的思维方式, 但是实际上递归不需要这样来验证. 比如, 另外一个常见的例子是阶乘的计算.
阶乘的定义: “一个正整数的阶乘(英语:factorial)是所有小于或等于该数的正整数的积,并且0的阶乘为1。” 以下是Ruby的实现:

def factorial(n) 
  if n <= 1 then
    return 1
  else
    return n * factorial(n - 1)
  end
end

我们怎么判断这个阶乘的递归计算是否是正确的呢? 先别说测试, 我说我们读代码的时候怎么判断呢?
回溯的思考方式是这么验证的, 比如当n = 4时, 那么factoria(4)等于4
* factoria(3)
, 而factoria(3)等于3
* factoria(2)
factoria(2)等于2
* factoria(1)
, 等于2 * 1, 所以factoria(4)等于4
* 3 * 2 * 1
. 这个结果正好等于阶乘4的迭代定义.
用回溯的方式思考虽然可以验证当n = 某个较小数值是否正确, 但是其实无益于理解.
Paul Graham提到一种方法, 给我很大启发, 该方法如下:

  1. 当n=0, 1的时候, 结果正确.
  2. 假设函数对于n是正确的, 函数对n+1结果也正确.
    如果这两点是成立的,我们知道这个函数对于所有可能的n都是正确的。

这种方法很像数学归纳法, 也是递归正确的思考方式, 事实上, 阶乘的递归表达方式就是1!=1,n!=(n-1)!?n(见wiki).
当程序实现符合算法描述的时候, 程序自然对了, 假如还不对, 那是算法本身错了…… 相对来说, n,n+1的情况为通用情况, 虽然比较复杂, 但是还能理解, 最重要的, 也是最容易被新手忽略的问题在于第1点, 也就是基本用例(base case)要对. 比如, 上例中, 我们去掉if
n <= 1
的判断后, 代码会进入死循环, 永远不会结束.

使用递归

既然递归比迭代要难以理解, 为啥我们还需要递归呢? 从上面的例子来看, 自然意义不大, 但是很多东西的确用递归思维会更加简单……
经典的例子就是斐波那契数列, 在数学上, 斐波那契数列就是用递归来定义的:

F0 = 0
F1 = 1 
Fn = Fn – 1 + Fn – 2

有了递归的算法, 用程序实现实在再简单不过了:

def fibonacci(n)
  if n == 0 then
    return 0
  elsif n == 1 then
    return 1
  else
    return fibonacci(n - 1) + fibonacci(n - 2)
  end
end

改为用迭代实现呢? 你可以试试.
上面讲了怎么理解递归是正确的, 同时可以看到在有递归算法描述后, 其实程序很容易写, 那么最关键的问题就是, 我们怎么找到一个问题的递归算法呢?
Paul Graham提到, 你只需要做两件事情:

  1. 你必须要示范如何解决问题的一般情况, 通过将问题切分成有限小并更小的子问题.
  2. 你必须要示范如何通过有限的步骤, 来解决最小的问题(基本用例).
    如果这两件事完成了, 那问题就解决了. 因为递归每次都将问题变得更小, 而一个有限的问题终究会被解决的, 而最小的问题仅需几个有限的步骤就能解决.

这个过程还是数学归纳法的方法, 只不过和上面提到的一个是验证, 一个是证明.
现在我们用这个方法来寻找汉诺塔这个游戏的解决方法.(这其实是数学家发明的游戏)

有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
1.每次只能移动一个圆盘.
2.大盘不能叠在小盘上面.

汉诺塔
这个游戏在只有3个盘的时候玩起来较为简单, 盘越多, 就越难, 玩进去后, 你就会进入一种不停的通过回溯来推导下一步该干什么的状态, 这是比较难的. 我记得第一次碰到这个游戏好像是在大航海时代某一代游戏里面, 当时就觉得挺有意思的. 推荐大家都实际的玩一下这个游戏, 试试你脑袋能想清楚几个盘的情况.
现在我们来应用Paul Graham的方法思考这个游戏.

一般情况:
当有N个圆盘在A上, 我们已经找到办法将其移到C杠上了, 我们怎么移动N+1个圆盘到C杠上呢? 很简单, 我们首先用将N个圆盘移动到C上的方法将N个圆盘都移动到B上, 然后再把第N+1个圆盘(最后一个)移动到C上, 再用同样的方法将在B杠上的N个圆盘移动到C上. 问题解决.

基本用例:
当有1个圆盘在A上, 我们直接把圆盘移动到C上即可.

算法描述大概就是上面这样了, 其实也可以看作思维的过程, 相对来说还是比较自然的. 下面是Ruby解:

def hanoi(n, from, to, other)
  if n == 1 then
    puts from + ' -> ' + to
  else
    hanoi(n-1, from, other, to)
    hanoi(1, from, to, other)
    hanoi(n-1, other, to, from)
  end
end

当n=3时的输出:

A -> C
A -> B
C -> B
A -> C
B -> A
B -> C
A -> C

上述代码中, from, to, other的作用其实也就是提供一个杆子的替代符, 在n=1时, 其实也就相当于直接移动. 看起来这么复杂的问题, 其实用递归这么容易, 没有想到吧. 要是想用迭代来解决这个问题呢? 还是你自己试试吧, 你试的越多, 就能越体会到递归的好处.

递归的问题

当然, 这个世界上没有啥时万能的, 递归也不例外, 首先递归并不一定适用所有情况, 很多情况用迭代远远比用递归好了解, 其次, 相对来说, 递归的效率往往要低于迭代的实现, 同时, 内存好用也会更大, 虽然这个时候可以用尾递归来优化,
但是尾递归并不是一定能简单做到.

参考

  1. Ansi Common Lisp
  2. 精通递归程序设计

extern "C"

Posted on

d:/linux/linuxkernel/WORKING_DIRECTORY/android-omap-20111108-gingerbread/libcore/luni/src/main/native/java_net_InetAddress.cpp:94: undefined reference to `getaddrinfo(char const*, char const*, addrinfo const*, addrinfo**)@16′
d:/linux/linuxkernel/WORKING_DIRECTORY/android-omap-20111108-gingerbread/libcore/luni/src/main/native/java_net_InetAddress1.cpp:73: undefined reference to `getaddrinfo@16′
C:MinGW-4.6.1includews2tcpip.h
#ifdef  __cplusplus
extern "C" {
#endif

int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
       struct addrinfo**);
#ifdef  __cplusplus
}

#endif

http://www./Macaulish/archive/2008/06/17/53689.html

CSS实现带箭头的DIV

Posted on

          毕业设计要做一个提示框:当鼠标放在某个链接上时,下边显示有提示功能的窗体。如下:

          具体代码实现如下:

     CSS:

.rhsyyhqDIV{
	position:absolute;
	top:555px;
	left:200px;
	font-size: 9pt;
	display:block;
	height:335px;
	width:405px;
	background-color:transparent;
	display: none;
}

s{
	position:absolute;
	top:-20px;
	left:50px;
	display:block;
	height:0;
	width:0;
	font-size: 0; 
	line-height: 0;
	border-color:transparent transparent #FA0505 transparent;
	border-style:dashed dashed solid dashed;
	border-width:10px;
}

i{
	position:absolute;
	top:-9px;
	*top:-9px;
	left:-10px;
	display:block;
	height:0;
	width:0;
	font-size: 0;
	line-height: 0;
	border-color:transparent transparent #FFFFFF transparent;
	border-style:dashed dashed solid dashed;
	border-width:10px;
}

.rhsyyhqDIV .content{
	border:1px solid #FA0505;
	-moz-border-radius:3px;
	-webkit-border-radius:3px;
	position:absolute;
	background-color:#FEFEF4;
	width:100%;
	height:100%;
	padding:5px;
	*top:-2px;
	*border-top:1px solid #FA0505;
	*border-top:1px solid #FA0505;
	*border-left:none;
	*border-right:none;
	*height:102px;
}

    HTML

    <div class="rhsyyhqDIV">
    	<div class="content">
    		<div  class="title">
    			<font>使用优惠码说明</font>
    		</div>
    		<div class="main">
    			<ul>
    				<li> 如下图:登陆成功后,在文本框中输入优惠码,点击"使用"按钮</li>
    				<li><img src="${/paixie/images/proscenium/rhsyyhq_01.jpg"/></li>
    				<li><img src="${/paixie/images/proscenium/rhsyyhq_02.jpg"/></li>
    			</ul>
    		</div>
    	</div>
    	<s><i></i></s>
    </div>

               

HICON与HBITMAP相互转换

Posted on

将BMP转换成ICON图标

方法一、

HICON HICONFromCBitmap( CBitmap& bitmap)
{
  BITMAP bmp;
  bitmap.GetBitmap(&bmp);
 
  HBITMAP hbmMask = ::CreateCompatibleBitmap(::GetDC(NULL),
    bmp.bmWidth, bmp.bmHeight);
 
  ICONINFO ii = {0};
  ii.fIcon = TRUE;
  ii.hbmColor = bitmap;
  ii.hbmMask = hbmMask;
 
  HICON hIcon = ::CreateIconIndirect(&ii);
  ::DeleteObject(hbmMask);
 
  return hIcon;
}

方法二、

#include <gdiplus.h>
#pragma comment(lib,"GdiPlus.lib")
 
HICON CreateIcon(HBITMAP hBitmap)
{
 Gdiplus::Bitmap* pTmpBitmap=Gdiplus::Bitmap::FromHBITMAP(hBitmap,NULL);
 HICON hIcon=NULL;
 pTmpBitmap->GetHICON(&hIcon);
 delete pTmpBitmap;
 return hIcon;
}

 

HICON转HBITMAP

利用GetIconInfo函数获取ICONINFO信息, 再将其复制到位图当中去, 代码如下:

HBITMAP ConvertIconToBitmap(HICON  hIcon)

{
  HBITMAP   hBmp;
  BITMAP   bmp;
  CDC   bmpDC;
  CDC   iconDC;
  ICONINFO         csII;
  int bRetValue   =   ::GetIconInfo(hIcon,   &csII);
  if   (bRetValue   ==   FALSE)   return   NULL;
  bmpDC.Attach(::GetDC(NULL));
  iconDC.CreateCompatibleDC(&bmpDC);
  if   (::GetObject(csII.hbmColor,   sizeof(BITMAP),   &bmp))
  {
    DWORD       dwWidth   =   csII.xHotspot*2;
    DWORD       dwHeight   =   csII.yHotspot*2;
    hBmp=   ::CreateBitmap(dwWidth,   dwHeight,   bmp.bmPlanes,  
      bmp.bmBitsPixel,   NULL);
    iconDC.SelectObject(csII.hbmColor);
    bmpDC.SelectObject(hBmp);
    bmpDC.BitBlt(0,0,dwWidth,dwHeight,&iconDC,0,0,SRCCOPY);
    return   hBmp;
  }
  return NULL;
}

还有一种方法就是先创建一个兼容位图, 然后通过API函数::DrawIcon()复制上去, CopyImage函数可以用来替换创建兼容DC以后的那些骤了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多