第十五章 并发编程

1.操作系统的发展史

参考:http://www.cnblogs.com/Eva-J/articles/8253521.html

知识点

输入输出 -- 大部分时间都不会占用CPU,但会降低你程序的效率

操作系统的三种基本类型:多道批处理系统、分时系统、实时系统。

现在操作系统

基于多道批处理系统和分时系统

多个程序、作业在遇到IO操作的时候,操作系统会帮助你进行切换

让CPU的利用率得到最大的提高

2.进程

初识进程

进程: 运行中的程序

操作系统 只负责管理调度进程

进程是操作系统中资源分配的最小单位

每一个运行中的程序都需要有自己的内存、资源

都分配给进程 记录执行的状态 管理自己的内存资源

在Python中,每一个运行的程序 都是一个进程

如何使用python来开启一个进程--我们使用multiprocessing模块,process-进程,multi多元的

并发编程例:

import os
import time
from multiprocessing import Process
def func(num):
    print(num,os.getpid())
    time.sleep(0.5)
    print(num,os.getpid())
    time.sleep(0.5)
    print(num, os.getpid())
    time.sleep(0.5)
    print(num, os.getpid())

# 创建一个进程
if __name__ == ‘__main__‘:  # windows,开启子进程的时候,会执行import
    print(os.getpid())
    p = Process(target=func, args=(10,))
    p.start() # 开启进程
    print(os.getpid())
    time.sleep(1)
    print(os.getpid(),1)
    time.sleep(1)
    print(os.getpid(),2)

# 运行结果
#                  时间轴
# 17500              0
# 17500              0
# 10 12656           0+
# 10 12656           0.5
# 17500 1            1
# 10 12656           1+
# 10 12656           1.5+
# 17500 2            2

几个概念:

同步:一个时刻只能做一件事

异步:同时做多件事

异步可以有效地提高程序的效率子

进程:主进程中开启的新的进程

主进程:运行的这个程序

父进程:创造出子进程的进程

注意:进程与进程之间都是异步的,而且开启一个进程是有时间开销的

进程的进阶

什么是进程:运行中的程序,计算机中最小的资源分配单位

程序开始执行就会产生一个主进程

python中可以主进程中用代码启动一个进程 -- 子进程

同时主进程也被称为父进程父子进程之间的代码执行是异步的,各自执行自己的

父子进程之间的数据不可以共享

例:

import time
from multiprocessing import Process

n = 100
def func():
    global n
    n = 0
    print(n)
    print(‘----------‘)

if __name__ == ‘__main__‘:
    Process(target=func).start()
    time.sleep(1)
    print(n)
# 0
# ----------
# 100
# 说明:父进程中n的值并没有随着子进程的运行而改变

进程什么时候结束

主进程什么时候结束:主进程会等待子进程结束之后再结束,父进程会等待回收子进程所占用的资源

例:直接开启多个子进程

import time
from multiprocessing import Process

n = 100
def func(n):
    time.sleep(1)
    print(‘-‘*n)

if __name__ == ‘__main__‘:
    Process(target=func, args=(1,)).start()
    Process(target=func, args=(2,)).start()
    Process(target=func, args=(3,)).start()
    Process(target=func, args=(4,)).start()

# 说明:主要看时间片的轮转,是一个随机事件
# -
# ----
# ---
# --

例:使用for循环开启多个子进程

import time
from multiprocessing import Process

n = 100
def func(n):
    time.sleep(1)
    print(‘-‘*n)

if __name__ == ‘__main__‘:
    for i in range(10):
        Process(target=func, args=(i,)).start()
# -
# --
# --------
# ----
# ---
# -----
# ---------
# ------
# -------

阻塞

例:使用阻塞(join)开启子进程

import time
from multiprocessing import Process

n = 100
def func(n):
    time.sleep(1)
    print(‘-‘*n)

if __name__ == ‘__main__‘:
    p = Process(target=func, args=(1,))
    p.start()
    print(‘子进程开始了‘)
    p.join() # 阻塞 直到子进程都执行完毕
    print(‘十条信息已经都发送完了‘)
# 子进程开始了
# -
# 十条信息已经都发送完了

例:使用阻塞(join)循环开启多个子进程

import time
from multiprocessing import Process

n = 100
def func(n):
    time.sleep(1)
    print(‘-‘*n)

if __name__ == ‘__main__‘:
    lst = []
    for i in range(10):
        p = Process(target=func, args=(i,))
        p.start()
        lst.append(p)
    for p in lst:p.join()

    print(‘十条信息已经都发送完了‘)

# -----
# -
# ---
# -------
# --
# ---------
# ----
# --------
# ------
#
# 十条信息已经都发送完了

守护进程

守护进程也是一个子进程

定义:当主进程的代码执行完毕之后自动结束的子进程叫做守护进程

例:

import time
from multiprocessing import Process
def deamon_func():
    while True:
        print(‘我还活着‘)
        time.sleep(0.5)

if __name__ == ‘__main__‘:
    p = Process(target=deamon_func)
    # 开启守护进程
    p.daemon = True
    p.start()
    for i in range(3):
        print(i*‘*‘)
        time.sleep(0.4)

# 我还活着
# *
# 我还活着
# **
# 我还活着
# 说明:正常情况下,父进程会等待子进程结束才结束
# 而设置守护进程后,父进程结束了,子进程的死循环即可停止

练习:分析程序请问会打印多少个我还活着

import time
from multiprocessing import Process
def deamon_func():
    while True:
        print(‘我还活着‘)
        time.sleep(0.5)

def wahaha():
    for i in range(10):
        time.sleep(1)
        print(i*‘#‘)

if __name__ == ‘__main__‘:
    Process(target=wahaha).start()
    p = Process(target=deamon_func)
    p.daemon = True
    p.start()
    for i in range(3):
        print(i*‘*‘)
        time.sleep(1)

# 我还活着
# 我还活着
# *
#
# 我还活着
# 我还活着
# **
# #
# 我还活着
# 我还活着
# ##
# ###
# ####
# #####
# ######
# #######
# ########
# #########
# 说明:因为‘我还活着‘是守护进程打印的,所以当父进程结束后,停止打印,3/0.5=6次
# 但程序不会停止,需要等待子进程wahaha结束

例:主进程添加阻塞

import time
from multiprocessing import Process
def deamon_func():
    while True:
        print(‘我还活着‘)
        time.sleep(0.5)

def wahaha():
    for i in range(10):
        time.sleep(1)
        print(i*‘#‘)

if __name__ == ‘__main__‘:
    p2 = Process(target=wahaha)
    p2.start()
    p = Process(target=deamon_func)
    p.daemon = True
    p.start()
    for i in range(3):
        print(i*‘*‘)
        time.sleep(1)
    p2.join()

# 我还活着
# 我还活着
# *
#
# 我还活着
# 我还活着
# **
# #
# 我还活着
# 我还活着
# ##
# 我还活着
# 我还活着
# ###
# 我还活着
# 我还活着
# ####
# 我还活着
# 我还活着
# #####
# 我还活着
# 我还活着
# ######
# 我还活着
# 我还活着
# #######
# 我还活着
# 我还活着
# ########
# 我还活着
# 我还活着
# #########
# 我还活着

总结

# 开启一个子进程 start
# 子进程和主进程是异步的
# 如果在主进程中要等待子进程结束之后再执行某行代码:join
# 如果有多个子进程 不能在start一个进程之后就立刻join,把所有的进程放到列表中
# 等待所有的进程都start之后再逐一join
# 守护进程 -- 当主进程的代码执行完毕之后自动结束的子进程叫做守护进程

添加锁是为了保证程序的运行顺序,牺牲了效率但是保护数据的安全

例:未添加阻塞、锁

import os
import time
import random
from multiprocessing import Process,Lock

def work(n):
    print(‘%s: %s is running‘ %(n,os.getpid()))
    time.sleep(random.random())
    print(‘%s:%s is done‘ %(n,os.getpid()))

if __name__ == ‘__main__‘:
    for i in range(3):
        p=Process(target=work,args=(i,  ))
        p.start()
# 0: 23192 is running
# 2: 6064 is running
# 1: 22560 is running
# 1:22560 is done
# 0:23192 is done
# 2:6064 is done
# 说明:在没有使用阻塞,锁的时候,因为时间片是随机事件,所以随机子进程开始

例:使用阻塞保证子进程的独立运行

import os
import time
import random
from multiprocessing import Process,Lock

def work(n):
    print(‘%s: %s is running‘ %(n,os.getpid()))
    time.sleep(random.random())
    print(‘%s:%s is done‘ %(n,os.getpid()))

if __name__ == ‘__main__‘:
    for i in range(3):
        p=Process(target=work,args=(i,  ))
        p.start()
        p.join()

# 0: 13184 is running
# 0:13184 is done
# 1: 22868 is running
# 1:22868 is done
# 2: 22200 is running
# 2:22200 is done

例:使用锁

import os
import time
import random
from multiprocessing import Process,Lock

def work(n, lock):
    lock.acquire()
    print(‘%s: %s is running‘ %(n,os.getpid()))
    time.sleep(random.random())
    print(‘%s:%s is done‘ %(n,os.getpid()))
    lock.release()

if __name__ == ‘__main__‘:
    lock = Lock()
    for i in range(3):
        p=Process(target=work,args=(i,lock))
        p.start()

# 0: 18864 is running
# 0:18864 is done
# 1: 23264 is running
# 1:23264 is done
# 2: 15820 is running
# 2:15820 is done

信号量

信号量本质是锁+计数器

from multiprocessing import Process,Semaphore
import time,random

def go_ktv(sem,user):
    sem.acquire()
    print(‘%s 占到一间ktv小屋‘ %user)
    time.sleep(random.randint(3,5)) #模拟每个人在ktv中待的时间不同
    sem.release()
    print(‘%s 走出ktv小屋‘ % user)

if __name__ == ‘__main__‘:
    sem=Semaphore(4)
    p_l=[]
    for i in range(13):
        p=Process(target=go_ktv,args=(sem,‘user%s‘ %i,))
        p.start()
        p_l.append(p)

    for i in p_l:
        i.join()
    print(‘============》‘)

# 信号量的本质就是 锁+计数器
# user12 占到一间ktv小屋
# user8 占到一间ktv小屋
# user0 占到一间ktv小屋
# user7 占到一间ktv小屋
# user12 走出ktv小屋
# user4 占到一间ktv小屋
# user6 占到一间ktv小屋
# user0 走出ktv小屋
# user8 走出ktv小屋
# user3 占到一间ktv小屋
# user7 走出ktv小屋
# user11 占到一间ktv小屋
# ******
# ============》
# 说明:程序设置Semaphore(4),表示同时只能有四个子进程存在,如果有结束的,再添加新的,知道所有子进程结束

事件

事件内部内置了一个标志wait 方法 如果这个标志是True,那么wait == passwait 方法 如果这个标志是False,那么wait就会陷入阻塞,一直阻塞到标志从False变成True

一个事件在创建之初 内部的标志默认是FalseFalse -> True set()True -> False clear()

红绿灯模型

# 红绿灯模型
from multiprocessing import Process, Event
import time, random

def car(e, n):
    while True:
        if not e.is_set():  # 进程刚开启,is_set()的值是Flase,模拟信号灯为红色
            print(‘\033[31m红灯亮\033[0m,car%s等着‘ % n)
            e.wait()    # 阻塞,等待is_set()的值变成True,模拟信号灯为绿色
            print(‘\033[32m车%s 看见绿灯亮了\033[0m‘ % n)
            time.sleep(random.randint(3, 6))
            if not e.is_set():   #如果is_set()的值是Flase,也就是红灯,仍然回到while语句开始
                continue
            print(‘车开远了,car‘, n)
            break

def traffic_lights(e, inverval):
    while True:
        time.sleep(inverval)   # 先睡3秒
        if e.is_set():         # 标志是True
            print(‘######‘, e.is_set())
            e.clear()  # ---->将is_set()的值设置为False
        else:                 # 标志是False
            e.set()    # ---->将is_set()的值设置为True
            print(‘***********‘,e.is_set())

if __name__ == ‘__main__‘:
    e = Event()   #e就是事件
    t = Process(target=traffic_lights, args=(e, 3))  # 创建一个进程控制红绿灯
    for i in range(10):
        p=Process(target=car,args=(e,i,))  # 创建是个进程控制10辆车
        p.start()
    t.start()

    print(‘============》‘)

# 10个进程 模拟车 :车的行走要依靠当时的交通灯
# 交通灯是绿灯 车就走
# 交通灯是红灯 车就停 停到灯变绿
# wait 来等灯
# set clear 来控制灯

队列

管道+锁 = 队列

管道也是一个可以实现进程之间通信的模型

但是管道没有锁,数据不安全

from multiprocessing import Queue,Process

def func(q,num):
    try:
        t = q.get_nowait()
        print("%s抢到票了"%num)
    except:pass

if __name__ == ‘__main__‘:
    q = Queue()
    q.put(1)
    for i in range(10):
        Process(target=func,args=(q,i)).start()

3.线程

什么是进程 :是计算机资源分配的最小单位

什么是线程 :是CPU调度的最小单位

线程和进程的关系:

  每个进程中都至少有一个线程

多线程服务的时候才能感受到线程的存在

本质的区别:

  同一个进程的每个线程之间数据共享

  线程之间也是异步的

  线程是轻量级的:创建一个线程的时间开销要远远小于进程

  线程是CPU调度的最小单位

例:线程的开启

import os
import time
from threading import Thread
def func(i):
    print(os.getpid())
    time.sleep(1)
    print(‘thread‘,i)

Thread(target=func,args=(1,)).start()
print(123*‘*‘)
print(‘main‘, os.getpid())
# 23280
# ***************************************************************************************************************************
# main 23280
# thread 

总结:

# 每一个进程里至少有一个主线程负责执行代码
# 在主线程中可以再开启一个新的线程
# 在同一个进程中就有两个线程同时在工作了
# 线程才是CPU调度的最小单位
# 多个线程之间的数据是共享的
# GIL锁 全局解释器锁# 解释器的锅 Cpython解释器的问题# 在同一个进程中 同一时刻 只能有一个线程被CPU执行# 导致高计算型 代码 不适合用python的多线程来解决# 用多进程或者分布式来解决高计算型代码

守护线程

例:

from threading import Thread
import time
def foo():
    while True:
        print(123)
        time.sleep(1)

def bar():
    print(456)
    time.sleep(3)
    print("end456")

t1 = Thread(target=foo)
t2 = Thread(target=bar)

t1.daemon = True
t1.start()
t2.start()
print("main-------")

# 主线程结束了之后守护线程也同时结束
# 守护线程会等待主线程完全结束之后才结束

例:

from threading import Thread,Lock
import time
def work():
    global n
    lock.acquire()
    temp=n
    time.sleep(0.1)
    n = temp-1
    lock.release()
if __name__ == ‘__main__‘:
    lock=Lock()
    n=100
    l=[]
    for i in range(100):
        p=Thread(target=work)
        l.append(p)
        p.start()
    for p in l:
        p.join()
    print(n)

# 当你的程序中出现了取值计算再赋值的操作 数据不安全 —— 加锁

线程池

程序可以开启的进程数和线程数

CPU的个数+1 进程数

CPU的个数*5 线程数

池的介绍
#1 介绍
concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用
Both implement the same interface, which is defined by the abstract Executor class.

#2 基本方法
#submit(fn, *args, **kwargs)
异步提交任务

#map(func, *iterables, timeout=None, chunksize=1)
取代for循环submit的操作

#shutdown(wait=True)
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前

#result(timeout=None)
取得结果

#add_done_callback(fn)
回调函数

例:

import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func(num):
    print(num)
    time.sleep(1)
    print(num)
if __name__ == ‘__main__‘:
    t = ThreadPoolExecutor(20)
    for i in range(100):
        t.submit(func,i)
    t.shutdown()  # join整个池子,必须添加
    print(‘done‘)
# 说明:线程会以20个为一组开启

例:使用map取代了for+submit

import os,time,random
from concurrent.futures import ThreadPoolExecutor
def task(n):
    print(‘%s is runing‘ %os.getpid(),n)
    time.sleep(random.randint(1,3))
    return n**2
if __name__ == ‘__main__‘:
    executor=ThreadPoolExecutor(max_workers=3)
    executor.map(task,range(1,12)) #map取代了for+submit

callback回掉函数 - 当拿到返回值的时候,立刻进行某操作

我有10个http的网页请求,把这10个网页上的信息分析了

例:

import time
import random
from concurrent.futures import ThreadPoolExecutor
from threading import current_thread
urls=[
        ‘https://www.baidu.com‘,
        ‘https://www.python.org‘,
        ‘https://www.openstack.org‘,
        ‘https://help.github.com/‘,
        ‘http://www.sina.com.cn/‘
        ‘http://www.cnblogs.com/‘
        ‘http://www.sogou.com/‘
        ‘http://www.sohu.com/‘
    ]

def analies(content):
    print(‘分析网页‘,current_thread())
    print(content.result())

def get_url(url):
    print(‘爬取网页‘,current_thread())
    time.sleep(random.uniform(1,3))
    # analies(url*10)
    return url*10

t = ThreadPoolExecutor(3)
print(‘主线程‘,current_thread())
for url in urls:
    t.submit(get_url,url).add_done_callback(analies)

concurrent.futures callback是由子线程做的

线程的其他知识与进程类似

4.协程

协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

进程 计算机中资源分配的最小单位 cpu+1

线程 CPU 调度最小单位 cpu*5

协程 把一个线程拆分成几个 500

进程 线程 都是操作系统在调度

协程 是程序级别调度

减轻了操作系统的负担、增强了用户对程序的可控性

例1:

from gevent import monkey;monkey.patch_all()
import gevent
import time
def eat(name):
    print(‘%s eat 1‘ %name)
    time.sleep(2)
    print(‘%s eat 2‘ %name)

def play(name):
    print(‘%s play 1‘ %name)
    time.sleep(1)
    print(‘%s play 2‘ %name)

g1=gevent.spawn(eat,‘egon‘)
g2=gevent.spawn(play,name=‘egon‘)
g1.join()
g2.join()
# gevent.joinall([g1,g2])
print(‘主‘)
# egon eat 1
# egon play 1
# egon play 2
# egon eat 2
# 主

例2:

from gevent import monkey;monkey.patch_all()
import gevent
import requests
import time

def get_page(url):
    print(‘GET: %s‘ %url)
    response=requests.get(url)
    if response.status_code == 200:
        print(‘%d bytes received from %s‘ %(len(response.text),url))

start_time=time.time()
gevent.joinall([
    gevent.spawn(get_page,‘https://www.python.org/‘),
    gevent.spawn(get_page,‘https://www.yahoo.com/‘),
    gevent.spawn(get_page,‘https://github.com/‘),
])
stop_time=time.time()
print(‘run time is %s‘ %(stop_time-start_time))
# GET: https://www.python.org/
# GET: https://www.yahoo.com/
# GET: https://github.com/
# 48801 bytes received from https://www.python.org/
# 527368 bytes received from https://www.yahoo.com/
# 59420 bytes received from https://github.com/
# run time is 6.552013397216797

原文地址:https://www.cnblogs.com/gnaix/p/9214480.html

时间: 2024-10-03 21:35:19

第十五章 并发编程的相关文章

[CSAPP笔记][第十二章并发编程]

第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟悉的例子. 我们主要将并发看做是一种操作系统内核用来运行多个应用程序的机制. 但是,并发不仅仅局限于内核.它也可以在应用程序中扮演重要的角色. 例如 Unix信号处理程序如何允许应用响应异步事件 例如:用户键入ctrl-c 程序访问虚拟存储器的一个未定义的区域 其他情况 访问慢速I/O设备 当一个应

第十二章 并发编程 学习笔记

第十二章 并发编程 进程是程序级并发,线程是函数级并发. 三种基本的构造并发程序的方法: 进程:每个逻辑控制流是个一个进程,由内核进行调度和维护. I/O多路复用:应用程序在一个进程的上下文中显式地调度他们自己的逻辑流. 线程:运行在单一进程上下文中的逻辑流,由内核进行调度. 12.1 基于进程的并发编程 构造并发程序最简单的方法就是用进程. 使用大家都很熟悉的函数例如: fork exec waitpid 关于在父.子进程间共享状态信息:共享文件表,但不共享用户地址空间. 进程又独立的地址空间

第十二章 并发编程

第十二章 并发编程 三种基本的构造并发程序 进程:每个逻辑控制流是一个进程,由内核进行调度,进程有独立的虚拟地址空间 I/O多路复用:逻辑流被模型化为状态机,所有流共享同一个地址空间 线程:运行在单一进程上下文中的逻辑流,由内核进行调度,共享同一个虚拟地址空间 常用函数: fork exec waitpid 基于I/O多路复用的并发事件驱动服务器 事件驱动程序:将逻辑流模型化为状态机. 状态机: 状态 输入事件 转移 对于状态机的理解,参考EDA课程中学习的状态转换图的画法和状态机. 整体的流程

深入理解计算机系统 第十二章 并发编程

如果逻辑控制流在时间上重叠,那么它们就是并发的(concurrent) 这种常见的现象称为并发(concurrency),出现在计算机系统的许多不同层面上. 并发不仅仅局限于内核,它也可以在应用程序中扮演重要角色. 应用级并发在以下情况中都是很有用的: 1.访问慢速 I/O 设备 当一个应用正在等待来自慢速 I/O 设备(例如磁盘)的数据到达时,内核会运行其它进程,使 CPU 保持繁忙.每个应用都可以按照类似的方式,通过交替执行 I/O 请求和其他有用的工作来利用并发. 2.与人交互 和计算机交

深入理解计算机系统 第十二章 并发编程 (1)

现代操作系统提供了三种基本的构造并发程序的方法: 进程.用这种方法,每个逻辑控制流都是一个进程,由内核来调度和维护,因为进程有独立的虚拟地址空间,想要和其他流通信,控制流必须使用某种显式的进程间通信(interprocess communication,IPC)机制. I/O多路复用.在这种形式的并发编程中,应用程序在一个进程的上下文中显式的调度它们自己的逻辑流.逻辑流被模型化为状态机,数据到达文件描述符后,主程序显式的从一个状态转换到另一个状态.因为程序是一个单独的进程,所以所有的流都共享同一

深入理解计算机系统 第十二章 并发编程 part1 第二遍

三种构造并发程序的方法及其优缺点 1.进程 用这种方法,每个逻辑控制流都是一个进程,由内核来调度和维护.因为进程有独立的虚拟地址空间,想要和其他流通信,控制流必须使用某种显式的进程间通信机制. 优点: 由于进程有独立的地址空间,所以一个进程不可能不小心覆盖另一个进程的虚拟内存,这就消除了许多令人迷惑的错误 缺点: (1)还是由于进程有独立的地址空间,使得进程共享状态信息变得更加困难.为了共享信息,它们必须使用显式的 IPC(进程间通信)机制. (2)由于进程控制和 IPC 的开销很高,所以这种方

C++primer第十五章. 面向对象编程

面向对象编程基于三个基本概念:数据抽象.继承和动态绑定. 15.1. 面向对象编程:概述 面向对象编程的关键思想是多态性(polymorphism). 之所以称通过继承而相关联的类型为多态类型,是因为在许多情况下可以互换地使用派生类型或基类型的“许多形态”.正如我们将看到的,在 C++ 中,多态性仅用于通过继承而相关联的类型的引用或指针. 继承 派生类(derived class)能够继承基类(baseclass)定义的成员,派生类可以无须改变而使用那些与派生类型具体特性不相关的操作,派生类可以

Flask 学习笔记-第十五章-应用编程接口

(Rich Internet Application,RIA)的架构. 在RIA中,服务器的主要功能(有时是唯一功能)是为客户端提供数据存取服务. 在这种模式中,服务器变成了Web服务或应用编程接口(Application Programming Interface,API). 表现层状态转移(Representational State Transfer,REST)架构崭 露头角,成为Web程序的新宠,因为这种架构建立在大家熟识的万维网 基础之上. Web服务的REST架构方式,并列出了6个符

C Primer Plus (第五版) 第十五章 位操作 编程练习

1.编写一个将二进制字符串转化为数字值的函数.也就是说,如果您有以下语句: char * pbin = "01001001"; 那么您可以将pbin作为一个参数传送给该函数,使该函数返回一个int的值25 #include <stdio.h> int bitoi(char *); int main(void) { char * pbin = "00011001"; printf("二进制:%s 等于十进制止:%d\n", pbin,