2012,知乎面试题二(重写)

2012年4月15日 没有评论

题目

2. antispam 系统

假设我们可以获得线上的实时请求(按时间顺序)
每个请求包含如下信息:
时间(unix时间戳)
用户名
动作(提问、回答、评论)
内容

依次考虑如何解决以下问题:
1.当发现动作频率较高的用户时,输出报警(1分钟内超过10次评论、回答、提问)
2.当发现一个用户连续发重复的内容时,输出报警(连续发了10个相同的评论、回答、提问)

3.使用你觉得最优美的方法将上面的策略与程序分离开。使得上面的策略可以随时更新而不用修改程序。

要求:

服务监听一个端口,使用测试程序模拟用户行为不断向服务发送请求,

请求格式为json如
{“time”:1323333,”user”:”xxx”,”action”:”answer”,”content”:”abcde”}

服务输出报警格式如下
xxx,”频繁提问”

说明

1.antispam 跑于gunicorn 在终端输入:gunicorn –workers=1 antispam:antispam 运行,不支持多进程(workers只能等于1)
2.testclient在test文件夹里面。请先运行antispam,再运行testclient
3.testclient支持参数配置 -a 或者 -addr 为要连接的server,默认127.0.0.1:8000。-f 或者 -test_file 为测试数据文件,默认testdata

antispam.py

# -*- coding:utf-8 -*-
# @author: jzb
from urlparse import parse_qs
import json
from strategys import strategys

class Store(object):
    '''
    存放数据的地方,为一个简陋的stack
    '''
    def __init__(self):
        self._data_list = []
        self._i = 0

    def seek_top(self):
        self._i = len(self._data_list)

    def next(self):
        self._i -= 1
        return self._data_list[self._i]

    def top(self):
        n = len(self._data_list)
        return self._data_list[0 if n == 0 else n - 1]

    def push(self, e):
        self._data_list.append(e)

    def is_end(self):
        return self._i == 0

class Context(object):
    _store = Store()

    @property
    def store(self):
        return self._store

    def __init__(self, strategys = []):
        self._strategys = strategys

    def execute(self):
        for e in self._strategys:
            if not e['strategy'](self._store):
                print e['warning'] % (e['strategy'].get_warning_user())

def antispam(environ, start_response):
    '''
    wsgi应用
    '''
    params = parse_qs(environ.get('QUERY_STRING', ''))
    if 'data' in params:
        context = Context(strategys)
        context.store.push(json.loads(params['data'][0].strip()))
        context.execute()
        start_response('200 ok', [('Content-Type', 'text/html')])
        return ['Data(%s) successfully received' % (params['data'][0].strip())]
    else:
        start_response('200 ok', [('Content-Type', 'text/html')])
        return ['Error']

strategys.py

# -*- coding:utf-8 -*-
# @author: jzb
class Strategy(object):
    '''
    策略只返回True/False
    '''
    def __init__(self):
        self._user = ''

    def __call__(self, data_list):
        pass

    def get_warning_user(self):
        return self._user

class StrategyHighFrequencyAction(Strategy):
    def __init__(self, action):
        self._action = action

    def __call__(self, store):
        times = 10
        s = 60
        time_limit = int(store.top()['time']) - s
        user = store.top()['user']
        action_sum = 0
        store.seek_top()
        while not store.is_end():
            e = store.next()
            if int(e['time']) >= time_limit:
                if e['user'] == user:
                    if self._action == e['action']:
                        action_sum += 1
            else:
                break
        if action_sum >= times:
            self._user = user
            return False
        return True

class StrategyContinuousRepeatContent(Strategy):
    def __init__(self, action):
        self._action = action

    def __call__(self, store):
        store.seek_top()
        times = 10
        user = store.top()['user']
        if self._get_repeat_sum(store, self._action) > times:
            self._user = user
            return False
        return True

    def _get_repeat_sum(self, store, action):
        content = store.top()['content']
        user = store.top()['user']
        action_sum = 0
        while not store.is_end():
            e = store.next()
            if e['user'] == user and e['action'] == action:
                if content == e['content']:
                    action_sum += 1
                else:
                    break
        return action_sum

# 在这里存放要执行的策略,warning为策略返回False时,输出的警告,%s会被被警告的用户名所替代
strategys = [
        {'strategy' : StrategyHighFrequencyAction('answer'), 'warning' : u'%s, "频繁提问"'},
        {'strategy' : StrategyHighFrequencyAction('comment'), 'warning' : u'%s, "频繁评论"'},
        {'strategy' : StrategyHighFrequencyAction('question'), 'warning' : u'%s, "频繁提问"'},
        {'strategy' : StrategyContinuousRepeatContent('answer'), 'warning' : u'%s, "重复回答"'},
        {'strategy' : StrategyContinuousRepeatContent('comment'), 'warning' : u'%s, "重复评论"'},
        {'strategy' : StrategyContinuousRepeatContent('question'), 'warning' : u'%s, "重复提问"'}
    ]

testclient.py

# -*- coding:utf-8 -*-
# @author: jzb
import httplib
import os
import sys
import urllib
import argparse
class TestClient(object):

    def __init__(self, ip, file_path):
        self._ip = ip
        self._file_path = file_path

    def run(self):
        headers = {
                "Host": self._ip,
                "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1) Gecko/20090624 Firefox/3.5",
                "Accept": "text/plain"
            }
        with open(self._file_path, 'r') as f:
            for line in f:
                try:
                    value = urllib.urlencode({'data' : line})
                    conn = httplib.HTTPConnection(self._ip)
                    conn.request(method = 'POST', url = '/?%s' %(value), headers = headers)
                    conn.close()
                except httplib.NotConnected:
                    print '%s can not connect' % self._ip
                    sys.exit()
                except httplib.HTTPException:
                    print 'send data exception'
                    sys.exit()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = 'It is a simple test client.')
    parser.add_argument('-a', '--addr', default = '127.0.0.1:8000', type = str, help = 'standard format: ip:port')
    parser.add_argument('-f', '--test_file', default = 'testdata', type = str, help = 'test data file')
    args = parser.parse_args()
    test_client = TestClient(args.addr, args.test_file)
    test_client.run()

2012,知乎面试题一(重写)

2012年4月15日 没有评论

1.sendemail支持参数配置 -e 或者 -sender_email 为要连接的发送者email,默认None。-p 或者 -sender_email_pwd 为发送者email的密码,默认None。-a 或者 -addressee_email 为接送者的email,默认为None。-f 或者 -attachment_paths 为附件,多个附件以空格分开,默认空列表。-d 或者 -debug 为httplib的debug开关。True开,False关

# -*- coding:utf-8 -*-
#@author: jzb
import os
import re
import sys
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders
import argparse

class Email(object):
    def __init__(self, sender = {}, recipient_email = None, email_subject = None, email_content = None, attachment_paths = []):
        self._sender = sender
        self._recipient_email = recipient_email
        self._email_subject = email_subject
        self._email_content = email_content
        self._attachment_paths = attachment_paths
        self._verify()
        self._email = self._create_email()

    @property
    def sender(self):
        return self._sender;

    @property
    def recipient_email(self):
        return self._recipient_email

    @property
    def attachment_paths(self):
        return self._attachment_paths

    @property
    def email(self):
        return self._email

    def _verify(self):
        if not self._sender['email'] or not self._is_email(self._sender['email']):
            print 'warning: %s is not email!' % self._sender['email']
            print 'end'
            sys.exit()
        if not self._recipient_email or not self._is_email(self._recipient_email):
            print 'warning: %s is not email!' % self._recipient_email
            print 'end'
            sys.exit()
        for path in self._attachment_paths:
            if not os.path.isfile(path):
                print 'warning: %s is not file!' % path
                print 'end'
                sys.exit()

    def _create_email(self):
        email = MIMEMultipart()
        email['From'] = self._sender['email']
        email['To'] = self._recipient_email
        email['Date'] = formatdate(localtime = True)
        email['Subject'] = self._email_subject
        email.attach(MIMEText(self._email_content))
        for path in self._attachment_paths:
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(open(path, 'r').read())
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(path))
            email.attach(part)
        return email

    def _is_email(self, email):
        str = r"^[-_A-Za-z0-9\.]+@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,32}$"
        return re.match(str, email)

class EmailClient(object):
    _config = {
            'smtps' : [
                    'smtp.gmail.com:25',
                    'smtp.qq.com:25',
                    'smtp.sina.com:25',
                    'smtp.sohu.com:25',
                    'smtp.163.com:25'
                ],
            'email' : {
                    'subject' : 'hello, world!',
                    'content' : 'hello, world!'
                }
        }

    def _get_smtp_addr_by_email(self, email):
        name = email[email.find('@')+1 : email.find('.')]
        for e in self._config['smtps']:
            if name in e:
                return e

    def __init__(self, sender = {}, recipient_email = '', attachment_paths = [], debug = True):
        self._debug = debug
        self._email = Email(sender, recipient_email, self._config['email']['subject'], self._config['email']['content'], attachment_paths)

    def _is_gmail(self, email):
        return 'gmail' in email

    def run(self):
        try:
            self.smtp = smtplib.SMTP()
            self.smtp.set_debuglevel(self._debug)
            self.smtp.connect(self._get_smtp_addr_by_email(self._email.sender['email']))
            if self._is_gmail(self._email.sender['email']):
                self.smtp.starttls()
            self.smtp.login(self._email.sender['email'], self._email.sender['pwd'])
            self.smtp.sendmail(self._email.sender['email'], self._email.recipient_email, self._email.email.as_string())
            self.smtp.close()
            print 'Sent successfully'
        except smtplib.SMTPServerDisconnected:
                print "warning:the SMTP server can not connect"
                print 'end'
                sys.exit()
        except smtplib.SMTPConnectError:
                print "warning:the SMTP server connection error"
                print 'end'
                sys.exit()
        except smtplib.SMTPSenderRefused:
                print "warning:sender address refused"
                print 'end'
                sys.exit()
        except smtplib.SMTPDataError:
                print "warning:the SMTP server refused to accept the email"
                print 'end'
                sys.exit()
        except smtplib.SMTPAuthenticationError:
                print "warning:SMTP server authentication went wrong"
                print 'end'
                sys.exit()
def main():
    parser = argparse.ArgumentParser(description = 'It is a simple email client.')
    parser.add_argument('-e', '--sender_email', default = None, type = str, help = 'the sender\'s email')
    parser.add_argument('-p', '--sender_email_pwd', default = None, type = str, help = 'the sender\'s email password')
    parser.add_argument('-a', '--addressee_email', default = None, type = str, help = 'the addressee\'s email')
    parser.add_argument('-f', '--attachment_paths', default = [], help = 'the email\'s attachments', nargs = '+')
    parser.add_argument('-d', '--debug', default = False, type = bool, help = 'debug email client')
    args = parser.parse_args()
    send_email = EmailClient({'email' : args.sender_email, 'pwd' : args.sender_email_pwd}, args.addressee_email, args.attachment_paths, args.debug)
    send_email.run()

if __name__ == '__main__':
    main()

2012,知乎笔试第二题

2012年3月26日 没有评论

题目
2. antispam 系统

假设我们可以获得线上的实时请求(按时间顺序)
每个请求包含如下信息:
时间(unix时间戳)
用户名
动作(提问、回答、评论)
内容

依次考虑如何解决以下问题:
1.当发现动作频率较高的用户时,输出报警(1分钟内超过10次评论、回答、提问)
2.当发现一个用户连续发重复的内容时,输出报警(连续发了10个相同的评论、回答、提问)

3.使用你觉得最优美的方法将上面的策略与程序分离开。使得上面的策略可以随时更新而不用修改程序。

要求:

服务监听一个端口,使用测试程序模拟用户行为不断向服务发送请求,

请求格式为json如
{“time”:1323333,”user”:”xxx”,”action”:”answer”,”content”:”abcde”}

服务输出报警格式如下
xxx,”频繁提问”

我的答案

# -*- coding:utf-8 -*-
'''
Created on 2012-3-22
@author: jzb
主要功能:实现了一个模拟antispam系统,对用户实时信息进行处理反馈
程序分为三个部分
1.数据发送客户端:模拟用户行为向服务器发送数据
2.数据接收服务器:用于接收发送的数据
3.Antispam:数据分析系统,策略写在config里面
ps:之前只在写gae的时候用过python,所以python基本新学的,如果在哪里犯了一些写python的低级错误,见谅
'''
import time
import thread
import SocketServer
import socket
import json
import os
import sys
import threading

'''
@author: jzb
全局变量
'''
DEBUG = True
HOST = '127.0.0.1'
CONFIG_PATH = ur"../config"
INF = 60 * 60 * 24

class Utils:
    '''
    @author: jzb
            工具类
    '''

    @staticmethod
    def createDictByJson(strJson):
        '''
        @author: jzb
                    通过json数据生成字典
        '''
        ret = {}
        try:
            ret = json.JSONDecoder().decode(strJson)
        except Exception:
            print strJson
        return ret

    @staticmethod
    def isFileExist(filePath):
        '''
        @author: jzb
                    判断文件是否存在
        '''
        return os.path.isfile(filePath)

class IO:
    '''
    @author: jzb
    IO类
    '''
    @staticmethod
    def input(filePath):
        '''
        @author: jzb
                    按行读入数据
        '''
        if not Utils.isFileExist(filePath):
            print 'can not find the file: %s' %(filePath)
            sys.exit()
        data = []

        try:
            f = open(filePath, 'r')
        except Exception:
            print Exception
            sys.exit()

        while True:
            line = f.readline()
            if len(line) == 0:
                break
            data.append(line)
        f.close()
        return data

    @staticmethod
    def inputCmd(filePath):
        '''
        @author: jzb
                    读入命令
        '''
        if not Utils.isFileExist(filePath):
            print 'can not find the file: %s' %(filePath)
            sys.exit()
        try:
            f = open(filePath, 'r')
        except Exception:
            print Exception
            sys.exit()
        data = f.read()
        f.close()
        return data

class Buf:
    '''
    @author: jzb
            缓存
            被换行符玩死了
    '''
    lock = threading.RLock()
    stringBuf = ""

    @staticmethod
    def write(data):
        '''
        @author: jzb
                    将从端口上得到的数据写入缓存
        '''
        Buf.lock.acquire()
        tmp = Buf.stringBuf
        tmp = tmp + data
        tmp = ''.join(tmp.split())
        Buf.stringBuf = tmp
        Buf.lock.release()

    @staticmethod
    def popLine():
        '''
        @author: jzb
                    从缓存中读出一行数据,并在缓存中将其删除
        '''
        Buf.lock.acquire()
        i = Buf.stringBuf.find('}')
        ret = Buf.stringBuf[0:i+1]
        Buf.stringBuf = Buf.stringBuf[i+1:]
        Buf.lock.release()
        return ret

class DataList:
    '''
    @author: jzb
        数据分析列表
    '''
    dataList = []
    first = None
    @staticmethod
    def insert(str):
        '''
        @author: jzb
                    插入数据到列表
        '''
        json = Utils.createDictByJson(str)
        DataList.first = json
        DataList.dataList.reverse()
        DataList.dataList.append(json)
        DataList.dataList.reverse()
    @staticmethod
    def find(map = {}):
        '''
        @author: jzb
                    程序核心函数,通过传入的参数,返回过滤后的列表
                    这段代码写的有点丑陋,将就的用了
        '''
        ret = []
        isContinuous = False
        if 'isContinuous' in map:
            isContinuous = map['isContinuous']
            del map['isContinuous']
        if isContinuous:
            f = True
            for e in DataList.dataList:
                for key in map:
                    if key == 'time':
                        if map[key] >= e[key]:
                            f = False
                            break
                    else:
                        if map[key] != e[key]:
                            f = False
                            break
                if f:
                    ret.append(e)
        else:
            for e in DataList.dataList:
                f = True
                for key in map:
                    if key == 'time':
                        if map[key] >= e[key]:
                            f = False
                            break
                    else:
                        if map[key] != e[key]:
                            f = False
                            break
                if f:
                    ret.append(e)
        return ret

class Strategy():
    '''
    @author: jzb
        策略类
    '''
    context = DataList
    cmds = Utils.createDictByJson(IO.inputCmd(CONFIG_PATH))

    @staticmethod
    def analysis():
        '''
        @author: jzb
                    根据策略对数据进行分析
        '''
        for e in Strategy.cmds:
            Strategy.handle(e)

    @staticmethod
    def handle(cmd):
        '''
        @author: jzb
                    根据命令选择不同的处理函数
        '''
        if Strategy.getTimePeriodByCmd(cmd) != -1:
            Strategy.handleTimePeriod(cmd)
        else:
            Strategy.handleSameContent(cmd)

    @staticmethod
    def handleTimePeriod(cmd):
        '''
        @author: jzb
                    按时间段处理数据
        '''
        user = Strategy.context.first['user']
        action = Strategy.getActionByCmd(cmd)
        isContinuous = Strategy.getIsContinuousByCmd(cmd)
        currentTime = Strategy.context.first['time']
        cutOffTime = currentTime - Strategy.getTimePeriodByCmd(cmd)
        if len(Strategy.context.find({'user' :user, 'action' : action, 'time' : cutOffTime, 'isContinuous' : isContinuous})) >= Strategy.getFrequencyByCmd(cmd):
            Strategy.printWarning(user,cmd)

    @staticmethod
    def handleSameContent(cmd):
        '''
        @author: jzb
                    按相同内容处理数据
        '''
        user = Strategy.context.first['user']
        action = Strategy.getActionByCmd(cmd)
        isContinuous = Strategy.getIsContinuousByCmd(cmd)
        sameContentTimes = Strategy.getSameContentTimesByCmd(cmd)
        content = Strategy.context.first['content']
        if len(Strategy.context.find({'user' :user, 'action' : action, 'content' : content, 'isContinuous' : isContinuous})) >= sameContentTimes:
            Strategy.printWarning(user,cmd)

    @staticmethod
    def getActionByCmd(cmd):
        '''
        @author: jzb
                    得到命令中Action
        '''
        return cmd['action']

    @staticmethod
    def getWarningByCmd(cmd):
        '''
        @author: jzb
                    得到命令中的Warning
        '''
        return cmd['warning']

    @staticmethod
    def getFrequencyByCmd(cmd):
        '''
        @author: jzb
                    得到命令中的Frequency
        '''
        if 'frequency' not in cmd:
            return -1
        return cmd['frequency']['value']

    @staticmethod
    def getTimePeriodByCmd(cmd):
        '''
        @author: jzb
                    根据命令中的Frequency,生成TimePeriod
        '''
        if 'frequency' not in cmd:
            return -1
        unit = cmd['frequency']['unit']
        if unit == 's':
            return 1
        elif unit == 'm':
            return 1 * 60
        elif unit == 'h':
            return 1 * 60 * 60

    @staticmethod
    def getSameContentTimesByCmd(cmd):
        '''
        @author: jzb
                    得到命令中的SameContent
        '''
        if 'sameContentTimes' not in cmd:
            return -1
        return cmd['sameContentTimes']

    @staticmethod
    def getIsContinuousByCmd(cmd):
        '''
        @author: jzb
                    得到命令中的IsContinuous
        '''
        return cmd['isContinuous']

    @staticmethod
    def printWarning(user, cmd):
        '''
        @author: jzb
                    打印警告
        '''
        print "%s:%s" %(user, Strategy.getWarningByCmd(cmd))

class Antispam:
    '''
    @author: jzb
        开启一个线程,进行数据分析
    '''
    @staticmethod
    def executive():
        '''
        @author: jzb
                    线程执行体
        '''
        print 'turn on the Antispam\n'
        while True:
            line = Buf.popLine()
            if len(line) == 0:
                continue
            DataList.insert(line)
            Strategy.analysis()

    @staticmethod
    def run():
        '''
        @author: jzb
                    启动线程
        '''
        thread.start_new_thread(Antispam.executive,())

class DataRecvServer(SocketServer.BaseRequestHandler):
    '''
    @author: jzb
        开启一个线程,接收发送的数据
    '''
    def handle(self):
        '''
        @author: jzb
        server处理函数,将接收到的数据存入缓存
        '''
        print 'turn on the DataRecvServer\n'
        while True:
            dataReceived = self.request.recv(1024)
            if not dataReceived or len(dataReceived) == 0:
                break
            Buf.write(dataReceived)

    @staticmethod
    def executive(host, port):
        '''
        @author: jzb
                    线程执行体
        '''
        server = SocketServer.ThreadingTCPServer((host, port), DataRecvServer)
        server.serve_forever()

    @staticmethod
    def run(host, port):
        '''
        @author: jzb
                    启动线程
        '''
        thread.start_new_thread(DataRecvServer.executive, (host, port))

'''
@author: jzb
开启一个线程,模拟用户行为向服务器发送数据
'''
class DataSendClient:
    @staticmethod
    def executive(host, port, testFilePath):
        '''
        @author: jzb
                    线程执行体
        '''
        print 'turn on the DataSendClient\n'
        print 'input test data\n'
        data = IO.input(testFilePath)
        print 'successfully enter the test data\n'
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((host, port))
            for e in data:
                sock.send(e)
        except socket.error, (value,message):
            if sock:
                sock.close()
            print "Could not open socket: " + message
            sys.exit(1)
        sock.close()
    @staticmethod
    def run(host, port, testFilePath):
        '''
        @author: jzb
                    启动线程
        '''
        thread.start_new_thread(DataSendClient.executive, (host, port, testFilePath))

'''
@author: jzb
程序入口,开启三个线程
'''
def main():
    DataRecvServer.run(HOST, 9527)
    DataSendClient.run(HOST, 9527, ur"../test.txt")
    Antispam.run()
    time.sleep(INF)
if __name__ == '__main__':
    main()

config文件

[
{"action":"question", "frequency":{"value":10, "unit":"m"}, "warning":"频繁提问", "isContinuous":"false"},
{"action":"answer", "frequency":{"value":10, "unit":"m"}, "warning":"频繁回答", "isContinuous":"false"},
{"action":"comment", "frequency":{"value":10, "unit":"m"}, "warning":"频繁评论", "isContinuous":"false"},
{"action":"question", "sameContentTimes":10, "warning":"重复提问", "isContinuous":"true"},
{"action":"answer", "sameContentTimes":10, "warning":"重复回答", "isContinuous":"true"},
{"action":"comment", "sameContentTimes":10, "warning":"重复评论", "isContinuous":"true"}
]
分类: python, 知乎面试 标签: , ,

2012,知乎笔试第一题

2012年3月26日 没有评论

题目

1. 写一个邮件发送的脚本

接受参数输入发件人邮箱、发件人密码,收件人地址,以及若干文件名,要求以文件为附件,发到收件人邮箱去。

要求: 至少支持gmail,163,sohu,sina,qq邮箱

我的答案

# -*- coding:gb2312 -*-
'''
Created on 2012-3-21
@author: jzb
主要功能:实现了简单的邮件发送客户端,接受参数输入发件人邮箱、发件人密码,收件人地址,以及若干文件名,要求以文件为附件,发到收件人邮箱去。
ps:之前只在写gae的时候用过python,所以python基本新学的,如果在哪里犯了一些写python的低级错误,见谅
'''
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email import Encoders
from email.Utils import formatdate
import smtplib
import re
import os

'''
@author: jzb
全局变量
'''
smtpPort = 25

'''
@author: jzb
邮件发送者
'''
class Sender:
    def __init__(self, email = None, password = None):
        self.iEmail = email
        self.password = password
    def __str__(self):
        return "Sender:{email:%s, password:%s}" %(self.iEmail, self.password)

'''
@author: jzb
邮件接受者
'''
class Addressee:
    def __init__(self, email = None):
        self.iEmail = email

    def __str__(self):
        return "Addressee:{email:%s}" %(self.iEmail)

'''
@author: jzb
邮件的附件
'''
class Attachment:
    def __init__(self, path = None):
        self.path = path

    def __str__(self):
        return "Attachment:{path:%s}" %(self.path)

'''
@author: jzb
邮件的内容,数据集合
'''
class SendContent:
    def __init__(self, sender = None, addressee = None, attachments = None):
        assert type(attachments) == list
        self.sender = sender
        self.addressee = addressee
        self.attachments = attachments

    def printSendContent(self):
        print self.sender
        print self.addressee
        for e in self.attachments:
            print e

'''
@author: jzb
IO类
'''
class IO:
    '''
    @author: jzb
            从控制台中得到输入数据
    '''
    @staticmethod
    def inputAll():

        senderEmail = IO.inputEmail("please enter the email of the sender:")
        senderPwd = raw_input("please enter the password of the sender email:")
        addresseeEmail = IO.inputEmail("please enter the email of the addressee:")
        attachments = IO.inputFilePaths("please input the path of the attachment, and end with #:")
        return IEmail.createEmail(senderEmail, senderPwd, addresseeEmail, attachments)

    '''
    @author: jzb
            输入邮箱地址,当地址正确时返回
    '''
    @staticmethod
    def inputEmail(prompt):
        while True:
            try:
                email = raw_input(prompt)
                if Utils.isEmail(email):
                    break
                else:
                    print 'email address is not correct'
            except EOFError:
                break
        return email

    '''
    @author: jzb
            输入文件路径,排除路径不正确的文件,输入#结束
    '''
    @staticmethod
    def inputFilePaths(prompt):
        attachments = []
        print prompt
        while(True):
            try:
                filePath = raw_input()
                if(filePath == '#'):
                    break
                if Utils.isFileExist(filePath):
                    attachments.append(filePath)
                else:
                    print 'file does not exist'
            except EOFError:
                break
        return attachments
'''
@author: jzb
工具类
'''
class Utils:
    '''
    @author: jzb
            通过email中得到公司名
    '''
    @staticmethod
    def getNameByEmail(email):
        b = email.find('@')
        e = email.find('.')
        return email[b+1:e]

    '''
    @author: jzb
            通过公司名得到该公司的smtp地址
    '''
    @staticmethod
    def getSmtpByName(name):
        return 'smtp.'+name+'.com'

    '''
    @author: jzb
            通过email得到该公司的smtp地址
    '''
    @staticmethod
    def getSmtpByEmail(email):
        return Utils.getSmtpByName(Utils.getNameByEmail(email))

    '''
    @author: jzb
            匹配正则表达式
    '''
    @staticmethod
    def regex(regexStr , str):
        if str is None or regexStr is None:
            return False
        if re.search(regexStr, str):
            return True
        else:
            return False
    '''
    @author: jzb
            判断email格式是否正确
    '''
    @staticmethod
    def isEmail(str):
        regexStr = ur"^[-_A-Za-z0-9\.]+@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,32}$"
        return Utils.regex(regexStr , str)

    @staticmethod
    def isFileExist(filePath):
        return os.path.isfile(filePath)
'''
@author: jzb
IEmail类,封装了对SendContent,MIMEMultipart的操作
'''
class IEmail:
    def __init__(self, sendContent = None):
        self.sendContent = sendContent
        self.msg = MIMEMultipart()
        self.createMIMEMultipart()
    '''
    @author: jzb
            将sendContent转化为mIMEMultipart
    '''
    def createMIMEMultipart(self):
        self.msg['From'] = self.getSenderEmail()
        self.msg['To'] = self.getAddresseeEmail()
        self.msg['Date'] = formatdate(localtime=True)
        self.msg['Subject'] = "hello, zhihu!"
        for e in self.getSenderAttachments():
            part = MIMEBase('application', "octet-stream")
            part.set_payload(open(e.path,"rb").read())
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(e.path))
            self.msg.attach(part)
    '''
    @author: jzb
            生成email的接口
    '''
    @staticmethod
    def createEmail(senderEmail, senderPwd, addresseeEmail, filePath):
        sender = Sender(senderEmail, senderPwd)
        addressee = Addressee(addresseeEmail)
        attachments = []
        for e in filePath:
            attachment = Attachment(e)
            attachments.append(attachment)
        sendRequest = SendContent(sender, addressee, attachments)
        iEmail = IEmail(sendRequest)
        return iEmail

    '''
    @author: jzb
            得到发送者的email
    '''
    def getSenderEmail(self):
        return self.sendContent.sender.iEmail

    '''
    @author: jzb
            得到发送者的password
    '''
    def getSenderPwd(self):
        return self.sendContent.sender.password

    '''
    @author: jzb
            得到发送者的附件
    '''
    def getSenderAttachments(self):
        return self.sendContent.attachments

    '''
    @author: jzb
            得到接受者的email
    '''
    def getAddresseeEmail(self):
        return self.sendContent.addressee.iEmail

    '''
    @author: jzb
            得到接受者的email的smtp的域名
    '''
    def getSmtp(self):
        return Utils.getSmtpByEmail(self.sendContent.sender.iEmail)
'''
@author: jzb
测试类
'''
class Test:
    '''
    @author: jzb
            测试数据
            测试密码就不给出了
    '''
    data = [
            {"sender" : { "email" : "exmorn@gmail.com", "password" : "xxx"}, "addressee" : { "email" : "452428967@qq.com"}, "attachments" : [ur"j:\topic_1\test0.png", ur"j:\topic_1\test1.rar", ur"j:\topic_1\test2.rar", ur"j:\topic_1\蒋中博简历.doc"]},
            {"sender" : { "email" : "452428967@qq.com", "password" : "xxx"}, "addressee" : { "email" : "exmorn@gmail.com"}, "attachments" : [ur"j:\topic_1\test0.png", ur"j:\topic_1\test1.rar", ur"j:\topic_1\test2.rar", ur"j:\topic_1\蒋中博简历.doc"]},
            {"sender" : { "email" : "exmorn@163.com", "password" : "xxx"}, "addressee" : { "email" : "452428967@qq.com"}, "attachments" : [ur"j:\topic_1\test0.png", ur"j:\topic_1\test1.rar", ur"j:\topic_1\test2.rar", ur"j:\topic_1\蒋中博简历.doc"]},
            {"sender" : { "email" : "exmorn@sina.com", "password" : "xxx"}, "addressee" : { "email" : "452428967@qq.com"}, "attachments" : [ur"j:\topic_1\test0.png", ur"j:\topic_1\test1.rar", ur"j:\topic_1\test2.rar", ur"j:\topic_1\蒋中博简历.doc"]},
            {"sender" : { "email" : "exmorn@sohu.com", "password" : "xxx"}, "addressee" : { "email" : "452428967@qq.com"}, "attachments" : [ur"j:\topic_1\test0.png", ur"j:\topic_1\test1.rar", ur"j:\topic_1\test2.rar", ur"j:\topic_1\蒋中博简历.doc"]},
    ]

    '''
    @author: jzb
            将测试数据转化为email实体列表
    '''
    @staticmethod
    def createEmails():
        emails = []
        for e in Test.data:
            iEmail = IEmail.createEmail(e["sender"]["email"], e["sender"]["password"], e["addressee"]["email"], e["attachments"])
            emails.append(iEmail)
        return emails

'''
@author: jzb
smtp客户端
'''
class SmtpClient:
    smtpPort = smtpPort
    def __init__(self, iEmail = None, debug = True):
        self.iEmail = iEmail
        self.debug = debug
        self.smtp = smtplib.SMTP()

    '''
    @author: jzb
            设置debug
    '''
    def init(self):
        self.smtp.set_debuglevel(self.debug)

    '''
    @author: jzb
            连接smtp服务器
    '''
    def connect(self):
        self.smtp.connect(self.iEmail.getSmtp(), self.smtpPort)

    '''
    @author: jzb
            登录smtp服务器
    '''
    def senderLogin(self):
        self.smtp.login(self.iEmail.getSenderEmail(), self.iEmail.getSenderPwd())

    '''
    @author: jzb
            判断是否是gmail
    '''
    def isGmail(self):
        if Utils.getNameByEmail(self.iEmail.getSenderEmail()) == "gmail":
            return True
        else:
            return False

    '''
    @author: jzb
            发送邮件
    '''
    def send(self):
        self.smtp.sendmail(self.iEmail.getSenderEmail(), self.iEmail.getAddresseeEmail(), self.iEmail.msg.as_string())

    '''
    @author: jzb
            关闭smtp
    '''
    def close(self):
        self.smtp.close()

    '''
    @author: jzb
    SmtpClient调用接口
    '''
    def sendEmail(self):
        print 'Start sending email from %s to %s' %(self.iEmail.getSenderEmail(), self.iEmail.getAddresseeEmail())
        self.init()
        print 'begin to connect to %s' %(self.iEmail.getSenderEmail())
        self.connect()
        print 'a successful connection'
        #果然gmail靠谱,不加密发不了
        if(self.isGmail()):
            self.smtp.starttls()
        print 'start the login %s' %(self.iEmail.getSmtp())
        self.senderLogin()
        print 'login is successful'
        self.send()
        print 'sending email'
        print 'email sent successfully'
        self.close()
        print ''

'''
@author: jzb
email客户端
'''
class EmailClient():
    def __init__(self, emails = [], debug = True):
        assert type(emails)==list
        self.emails = emails
        self.debug = debug

    '''
    @author: jzb
    EmailClient调用接口
    '''
    def sendEmail(self):
        for email in self.emails:
            smtpClient = SmtpClient(email, self.debug)
            smtpClient.sendEmail()

    '''
    @author: jzb
            程序入口
    '''
    @staticmethod
    def run():
        #emails = Test.createEmails()
        while True:
            try:
                emails = [IO.inputAll()]
                emailClient = EmailClient(emails, False)
                emailClient.sendEmail()
            except smtplib.SMTPServerDisconnected:
                print "warning:the SMTP server can not connect"
                continue
            except smtplib.SMTPConnectError:
                print "warning:the SMTP server connection error"
                continue
            except smtplib.SMTPSenderRefused:
                print "warning:sender address refused"
                continue
            except smtplib.SMTPDataError:
                print "warning:the SMTP server refused to accept the email"
                continue
            except smtplib.SMTPAuthenticationError:
                print "warning:SMTP server authentication went wrong"
                continue

if __name__ == '__main__':
    EmailClient.run()

2011年12月19日 没有评论

分类: 原创, 杂谈 标签: ,

Play framework 无法连接 sqlserver2005问题 的解决方案

2011年12月12日 没有评论

出现的错误

Oops: UnsupportedOperationException
An unexpected error occured caused by exception UnsupportedOperationException:
I do not know which hibernate dialect to use with com.microsoft.sqlserver.jdbc.SQLServerDriver and I cannot guess it, use the property jpa.dialect in config file

从提示中不难看出是hibernate dialect问题。在application.conf中加一行

jpa.dialect=org.hibernate.dialect.SQLServer2005Dialect

即可解决

Java与C#的DES加密通信(DES加密解密部分)

2011年11月13日 没有评论

之前做了一个项目,用java写前台,调用用C#写的webService。因为webService接收和返回的是DES加密后的数据,所以就涉及到java与C#解密对方加密出来的数据。如果单纯用其中一种语言加密解密是不难的,网上代码一搜一大把,基本都能用。但是涉及两种语言的,却很少有人讲清楚。
先奉上代码,代码是网上找的,我修改使其兼容

java部分

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import com.szds.G.Config;
/**
 * 使用DES加密和解密的方法
 *
 * @author:azhong User: Administrator Date: 2007-10-27 Time: 10:54:36
 * @change:exmorning
 * */
public class CryptoTools {

	private final byte[] DESkey = Config.secretKey.getBytes("UTF-8");// 设置密钥,略去
	private final byte[] DESIV = {0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};// 设置向量,略去

	private AlgorithmParameterSpec iv = null;// 加密算法的参数接口,IvParameterSpec是它的一个实现
	private Key key = null;

	public CryptoTools() throws Exception {
		DESKeySpec keySpec = new DESKeySpec(DESkey);// 设置密钥参数
		iv = new IvParameterSpec(DESIV);// 设置向量
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 获得密钥工厂
		key = keyFactory.generateSecret(keySpec);// 得到密钥对象

	}

	public String encode(String data) throws Exception {
		Cipher enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 得到加密对象Cipher
		enCipher.init(Cipher.ENCRYPT_MODE, key, iv);// 设置工作模式为加密模式,给出密钥和向量
		byte[] pasByte = enCipher.doFinal(data.getBytes("utf-8"));
		BASE64Encoder base64Encoder = new BASE64Encoder();
		return base64Encoder.encode(pasByte);
	}

	public String decode(String data) throws Exception {
		Cipher deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
		deCipher.init(Cipher.DECRYPT_MODE, key, iv);
		BASE64Decoder base64Decoder = new BASE64Decoder();

		byte[] pasByte = deCipher.doFinal(base64Decoder.decodeBuffer(data));

		return new String(pasByte, "UTF-8");
	}
	public static void main(String[] args) {
		try {
			String test = "zh~123456~44:37:E6:08:23:9A";
			CryptoTools des = new CryptoTools();//自定义密钥
			System.out.println("加密前的字符:"+test);
			System.out.println("加密后的字符:"+des.encode(test));
			System.out.println("解密后的字符:"+des.decode(des.encode(test)));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

C#部分

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace DESTest
{
    class DES
    {
        #region des

        /// <summary>
        /// 加密数据
        /// </summary>
        /// <param name="input">加密前的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(string input)
        {
            return EncryptDES(input, "kingszds");
        }
        /// <summary>
        /// 解密数据
        /// </summary>
        /// <param name="input">加密后的字符串</param>
        /// <returns>加密前的字符串</returns>
        public static string Decrypt(string input)
        {
            return DecryptDES(input, "kingszds");
        }

        //加密:EncryptDES("要加密的字符串", "kingszds");
        //解密:DecryptDES("要解密的字符串", "kingszds");
        //默认密钥向量
        private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
        public static string EncryptDES(string encryptString, string encryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
                byte[] rgbIV = Keys;
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            catch
            {
                return encryptString;
            }
        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
        /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
        public static string DecryptDES(string decryptString, string decryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
                byte[] rgbIV = Keys;
                byte[] inputByteArray = Convert.FromBase64String(decryptString);
                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(mStream.ToArray());
            }
            catch
            {
                return decryptString;
            }
        }
        #endregion
        static void Main(string[] args)
        {
            string strInput = "zh~123456~44:37:E6:08:23:9A";
            Console.WriteLine(strInput);
            Console.WriteLine(Encrypt(strInput));
            Console.WriteLine(Decrypt(Encrypt(strInput)));
            Console.WriteLine(System.DateTime.Now.ToLongTimeString());
        }
    }
}

刚开始就遇到了问题。两边采用同样的密钥,对同一个字符串加密出来的结果却不一样。去网上翻了翻。从这两篇文章中发现了一些线索

1.DES加密解密(C#,java)
2. 用 Java 解密 C# 加密的数据(DES)

有了线索,在之后的测试中发现,决定DES加密出来的值的内容有3个因数:密钥,密钥向量,算法模式(c#默认的CBC模式,PKCS7padding;java默认的是ECB模式,PKCS5padding)。设置一样后就没问题了

分类: c#, 原创, 算法, 编程语言 标签: , ,

隐式类型转换之implicit_cast

2011年8月13日 没有评论

implicit_cast,它用来告诉编译器执行什么隐式类型转换。但它不属于c++语法。需要自己编写。至于为什么要专门写一个以及有什么用。这个具体的看下面这篇文章,这位大牛已经讲的很明白。我就不再班门弄斧了。

url:BOOST::IMPLICIT_CAST
namespace simple
{
	template<typename T>
	struct identity { typedef T type; };
	template <typename T>
	inline T implicit_cast (typename identity<T>::type x)
	{
		return x;
	}
}
分类: c++, 原创 标签: , ,

C++对象计数

2011年8月8日 没有评论
#pragma once
namespace simple
{
	template<class T>
	class ObjCounter
	{
	public:
		inline	ObjCounter(int step = 1)
		{
			m_step = step;
			static_m_obj_cnt += m_step;
		}
		inline	~ObjCounter()
		{
			static_m_obj_cnt -= m_step;
		}
		inline	static int getObjCnt()
		{
			return static_m_obj_cnt;
		}
	private:
		static int static_m_obj_cnt;
		int m_step;
	};
	template<class T>
	int ObjCounter<T>::static_m_obj_cnt = 0;
}

使用方式

#include<iostream>
#include "ObjCounter.h"
using namespace simple;
int main()
{
	struct node
	{
		int index;
		ObjCounter<node> node_cnter;
	};
	node a;
	printf("%d\n", ObjCounter<node>().getObjCnt());
	return 0;
}

注意:最后返回的值是2,因为

ObjCounter<node>().getObjCnt()

也生成一个对象

分类: c++, 原创 标签: , , ,

c++支持引用计数的智能指针类模板(beta 1)

2011年8月8日 没有评论
//////////////////////////////////////////////////////////////////
// SmartPtr - 智能指针类模板
//
// Author:  exmorning
// Blog:    blog.ideapp.us
// E-Mail:  exmorn@gmail.com
// Version: 0.1
//
// History:
//		2011/8/8:实现引用计数,垃圾自动收集。
//			应该还有不少bug。
//////////////////////////////////////////////////////////////////
#pragma once
namespace simple
{
	template<class T>
	class SmartPtr;
	template<class T>
	class RefCnt;
///////////////////////////////////////////////////////////
//class RefCnt
///////////////////////////////////////////////////////////
	template<class T>
	class RefCnt
	{
	private:
		template<class T>
		friend class SmartPtr;
		int m_refCnt;
		T* m_t_ptr;
	protected:
		RefCnt(void);
		RefCnt(T t);
		~RefCnt(void);
		explicit RefCnt(T* p);
		void addRef();
		void removeRef();
	};
	// 实现
	template<class T>
	inline RefCnt<T>::~RefCnt()
	{
		delete m_t_ptr;
	};
	template<class T>
	inline RefCnt<T>::RefCnt()
		: m_refCnt(0)
		, m_t_ptr(NULL)
	{
		m_t_ptr = new T;
		addRef();
	}
	template<class T>
	inline RefCnt<T>::RefCnt(T t)
		: m_refCnt(0)
		, m_t_ptr(NULL)
	{
		m_t_ptr = new T;
		*m_t_ptr = t;
		addRef();
	}
	template<class T>
	inline RefCnt<T>::RefCnt(T* p)
		: m_refCnt(0)
		, m_t_ptr(NULL)
	{
		m_t_ptr = p;
		addRef();
	}
	template<class T>
	inline void RefCnt<T>::addRef()
	{
		++m_refCnt;
	}
	template<class T>
	inline void RefCnt<T>::removeRef()
	{
		if(--m_refCnt == 0)
		{
			delete m_t_ptr;
			m_t_ptr = NULL;
		}
	}

///////////////////////////////////////////////////////////////////
//class SmartPtr
///////////////////////////////////////////////////////////////////
	template<class T>
	class SmartPtr
	{
	private:
		RefCnt<T>* m_ref_ptr;
		friend class SmartPtr<T>;
		friend class RefCnt<T>;
	public:
		SmartPtr();
		SmartPtr(const T t);
		~SmartPtr();
		SmartPtr(T *p);
		template<class U>
		SmartPtr(SmartPtr<U>& rhs);

	//操作符重载
	public:
		SmartPtr<T>& operator = (const T t);
		SmartPtr<T>& operator = (T* p);
		SmartPtr<T>& operator = (const SmartPtr<T>& rhs);
		T& operator * ();
		T* operator -> ();
		operator void*();
	private:
		void addRef();
		void removeRef();
	};
//////////////////////////////////////////////////////////////////
	template<class T>
	SmartPtr<T>::SmartPtr()
		:m_ref_ptr(NULL)
	{
	};

	template<class T>
	SmartPtr<T>::SmartPtr(const T t)
		:m_ref_ptr(NULL)
	{
		m_ref_ptr = new RefCnt<T>(t);
	};

	template<class T>
	SmartPtr<T>::SmartPtr(T *p)
		:m_ref_ptr(NULL)
	{
		m_ref_ptr = new RefCnt<T>(p);
	};

	template<class T>
	template<class U>
	inline SmartPtr<T>::SmartPtr(SmartPtr<U>& rhs)
		:m_ref_ptr(NULL)
	{
		if(this == &rhs)
			return;
		m_ref_ptr = rhs.m_ref_ptr;
		addRef();
	};
	template<class T>
	inline SmartPtr<T>::~SmartPtr()
	{
		if(m_ref_ptr == NULL)
			return;
		if(--m_ref_ptr->m_refCnt == 0)
			delete m_ref_ptr;
		m_ref_ptr = NULL;
	};

	// operator overdo
	template<class T>
	inline SmartPtr<T>& SmartPtr<T>::operator =(T* p)
	{
		if(m_ref_ptr != NULL)
		{
			if(m_ref_ptr->m_refCnt == 1)
			{
				m_ref_ptr->removeRef();
				m_ref_ptr->m_t_ptr = new T();
				m_ref_ptr->m_t_ptr = p;
				m_ref_ptr->addRef();
			}
			else
			{
				removeRef();
				m_ref_ptr = NULL;
				m_ref_ptr = new RefCnt<T>(p);
			}
		}
		else
			m_ref_ptr = new RefCnt<T>(p);
		return *this;
	};
	template<class T>
	inline SmartPtr<T>& SmartPtr<T>::operator =(const T t)
	{
		if(m_ref_ptr != NULL)
		{
			if(m_ref_ptr->m_refCnt == 1)
			{
				m_ref_ptr->removeRef();
				m_ref_ptr->m_t_ptr = new T();
				*(m_ref_ptr->m_t_ptr) = t;
				m_ref_ptr->addRef();
			}
			else
			{
				removeRef();
				m_ref_ptr = NULL;
				m_ref_ptr = new RefCnt<T>(t);
			}
		}
		else
			m_ref_ptr = new RefCnt<T>(t);
		return *this;
	};
	template<class T>
	inline SmartPtr<T>::operator void*()
	{
		if(m_ref_ptr != NULL)
			return (void *)true;
		else
			return (void *)false;
	};
	template<class T>
	inline SmartPtr<T>& SmartPtr<T>::operator =(const SmartPtr<T> &rhs)
	{
		if(this == &rhs)
			return *this;
		if(m_ref_ptr == rhs.m_ref_ptr)
			return *this;
		if(m_ref_ptr != NULL)
		{
			removeRef();
			m_ref_ptr = rhs.m_ref_ptr;
			addRef();
		}
		else
		{
			m_ref_ptr = rhs.m_ref_ptr;
			addRef();
		}
		return *this;
	};
	template<class T>
	inline T& SmartPtr<T>::operator * ()
	{
		if(m_ref_ptr == NULL)
		{
			this->m_ref_ptr = new RefCnt<T>();
		}
		else
		{
			if(m_ref_ptr->m_t_ptr == NULL)
				m_ref_ptr->m_t_ptr = new T();
			else
			{
				if(m_ref_ptr->m_refCnt == 1)
					return *(this->m_ref_ptr->m_t_ptr);
				else
				{
					T t = *(this->m_ref_ptr->m_t_ptr);
					removeRef();
					m_ref_ptr = new RefCnt<T>(t);
				}
			}
		}
		return *(this->m_ref_ptr->m_t_ptr);
	};
	template<class T>
	inline T* SmartPtr<T>::operator -> ()
	{
		if(m_ref_ptr == NULL)
			m_ref_ptr = new RefCnt<T>();
		return m_ref_ptr->m_t_ptr;
	};

	template<class T>
	inline void SmartPtr<T>::addRef()
	{
		m_ref_ptr->addRef();
	}
	template<class T>
	inline void SmartPtr<T>::removeRef()
	{
		m_ref_ptr->removeRef();
		if(m_ref_ptr->m_t_ptr == 0)
			delete m_ref_ptr;
		m_ref_ptr = NULL;
	}
};

使用方法:

#include<iostream>
#include "SmartPtr.h"
int main()
{
	typedef simple::SmartPtr<int> intPtr;
	typedef simple::SmartPtr<std::string> stringPtr;
	stringPtr p_str = new std::string("hello"), p_str2;
	printf("%s\n", p_str->c_str());
	p_str2 = p_str;
	printf("%s\n", p_str->c_str());
	return 0;
}

无觅相关文章插件,快速提升流量

script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-23590836-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();