目标:通过网上下载的OpenStreetMap.xml数据格式,将该文件的格式进行统计,清洗,并导出成CSV格式的文件,最后倒入到SQLite中

本案例中所需的包

import csv
import codecs
import pprint
import re
import xml.etree.cElementTree as ET
from collections import defaultdict
import cerberus
import schema

1.统计文件中每一个标签出现的次数

思路:将xml文件使用sax解析,将每一个节点的的标签值设为字典的key,次数为value,初始化为0,

   循环文件,如果可以找到key,那么value的值+1,否则不变

def count_tags(filename):
#1.读文件
osm = ET.ElementTree(file=filename)
#2.获取根节点
root = osm.getroot()
#3.获取根节点的标签,创建一个字典来存放标签名和次数
tags_count_dic = {root.tag:0}
#4.循环文件
for _,ele in ET.iterparse(filename,events=('start',)):
#5.如果有元素的tag在字典中,则value的值+1,否则表示该标签只出现一次
if ele.tag in tags_count_dic:
tags_count_dic[ele.tag] += 1
else:
tags_count_dic[ele.tag] = 1
return tags_count_dic
def test():
#测试函数的断言不出错,表示结果正确
tags = count_tags('example.osm')
pprint.pprint(tags)
assert tags == {'bounds': 1,
'member': 3,
'nd': 4,
'node': 20,
'osm': 1,
'relation': 1,
'tag': 7,
'way': 1} if __name__ == "__main__":
test()

2.根据正则表达式,确定各种标签类型的数量

思路:获取根据传入的element,来获取tag,获取到tag即可获取到k的值,在根据正则表达式进行匹配,将匹配成功的值放入到不同的字典中

lower = re.compile(r'^([a-z]|_)*$') #仅包含小写字母且有效的标记
lower_colon = re.compile(r'^([a-z]|_)*:([a-z]|_)*$') #名称中有冒号的其他有效标记
problemchars = re.compile(r'[=\+/&<>;\'"\?%#$@\,\. \t\r\n]') #字符存在问题的标记 def key_type(element,keys):
#1.找到需要处理的标签进行处理
if element.tag == 'tag':
#2.获取带匹配的字符串
key = element.attrib['k']
#逐次匹配,并将匹配成功的结果放到keys中,并返回
if lower.search(key):
keys['lower'] += 1
elif lower_colon.search(key):
keys['lower_colon'] += 1
elif problemchars.search(key):
keys['problemchars'] += 1
else:
keys['other'] += 1
return keys def process_map(filename):
keys = {"lower": 0, "lower_colon": 0, "problemchars": 0, "other": 0}
for _, element in ET.iterparse(filename):
keys = key_type(element, keys) return keys
def test():
#测试函数的断言不报错,代码正确
keys = process_map('example.osm')
pprint.pprint(keys)
assert keys == {'lower': 5, 'lower_colon': 0, 'other': 1, 'problemchars': 1} if __name__ == "__main__":
test()

3.搜索用户,返回一组唯一的用户ID

思路:找到uid所对应的tag,循环xml文件,如果标签存在uid,就加入到set中返回

def get_user(element):
#如果标签中包含'uid'这一属性,则返回该属性的值
if 'uid' in element.attrib:
return element.attrib['uid'] def process_map(filename):
users = set()
#循环xml文件,如果每行的元素中有'uid'这一标签,则其值取出加入到set中,返回
for _, element in ET.iterparse(filename):
if get_user(element):
users.add(get_user(element))
return users
def test():
#断言不出错,程序正确
users = process_map('example.osm')
pprint.pprint(users)
assert len(users) == 6 if __name__ == "__main__":
test()

4.完善街道名,将街道中的一些不合法的值去除

思路:循环街道的字典,名称在mapping,则进行替换,返回替换后的字符串

OSMFILE = "example1.osm"
street_type_re = re.compile(r'\b\S+\.?$', re.IGNORECASE) expected = ["Street", "Avenue", "Boulevard", "Drive", "Court", "Place", "Square", "Lane", "Road",
"Trail", "Parkway", "Commons"] # UPDATE THIS VARIABLE
#题目这里的字符串需要更改,否则结果错误
mapping = { "Rd.": "Road",
"St.": "Street",
"Ave": "Avenue"
} def audit_street_type(street_types,street_name):
m = street_type_re.search(street_name)
if m:
street_type = m.group()
if street_type not in expected:
street_types[street_type].add(street_name) def is_street_name(elem):
return (elem.attrib['k'] == 'addr:street') def audit(osmfile):
osm_file = open(osmfile,'r')
street_types = defaultdict(set)
for event,ele in ET.iterparse(osmfile,events=('start',)):
if ele.tag == 'tag' or ele.tag == 'way':
for tag in ele.iter('tag'):
if is_street_name(tag):
audit_street_type(street_types,tag.attrib['v'])
osm_file.close()
return street_types def update_name(name, mapping):
#获取需要修改的key
changewords = mapping.keys()
#如果名称相同,则替换字符,并返回
for word in changewords:
if word in name:
name = name.replace(word,mapping.get(word))
return name
def test():
#断言不出错,则结果正确
st_types = audit(OSMFILE)
assert len(st_types) == 3
pprint.pprint(dict(st_types))
for st_type, ways in st_types.iteritems():
for name in ways:
better_name = update_name(name, mapping)
print name, "=>", better_name
if name == "West Lexington St.":
assert better_name == "West Lexington Street"
if name == "Baldwin Rd.":
assert better_name == "Baldwin Road" if __name__ == "__main__":
test()

5.数据清洗

目标数据的结构

node节点需要[id,user,uid,version,lat,lon,timestamp,changeset]

node节点下的tags子节点需要[id,key,value,type]

{'node': {'id': 757860928,
'user': 'uboot',
'uid': 26299,
'version': '',
'lat': 41.9747374,
'lon': -87.6920102,
'timestamp': '2010-07-22T16:16:51Z',
'changeset': 5288876},
'node_tags': [{'id': 757860928,
'key': 'amenity',
'value': 'fast_food',
'type': 'regular'},
{'id': 757860928,
'key': 'cuisine',
'value': 'sausage',
'type': 'regular'},
{'id': 757860928,
'key': 'name',
'value': "Shelly's Tasty Freeze",
'type': 'regular'}]}

way节点需要[id,user,uid,version,timestamp,changeset]

way节点下的nodes子节点需要[id,node_id,position]

way节点下的tag子节点需要[id,key,value,type]

{'way': {'id': 209809850,
'user': 'chicago-buildings',
'uid': 674454,
'version': '',
'timestamp': '2013-03-13T15:58:04Z',
'changeset': 15353317},
'way_nodes': [{'id': 209809850, 'node_id': 2199822281, 'position': 0},
{'id': 209809850, 'node_id': 2199822390, 'position': 1},
{'id': 209809850, 'node_id': 2199822392, 'position': 2},
{'id': 209809850, 'node_id': 2199822369, 'position': 3},
{'id': 209809850, 'node_id': 2199822370, 'position': 4},
{'id': 209809850, 'node_id': 2199822284, 'position': 5},
{'id': 209809850, 'node_id': 2199822281, 'position': 6}],
'way_tags': [{'id': 209809850,
'key': 'housenumber',
'type': 'addr',
'value': ''},
{'id': 209809850,
'key': 'street',
'type': 'addr',
'value': 'West Lexington St.'},
{'id': 209809850,
'key': 'street:name',
'type': 'addr',
'value': 'Lexington'},
{'id': '',
'key': 'street:prefix',
'type': 'addr',
'value': 'West'},
{'id': 209809850,
'key': 'street:type',
'type': 'addr',
'value': 'Street'},
{'id': 209809850,
'key': 'building',
'type': 'regular',
'value': 'yes'},
{'id': 209809850,
'key': 'levels',
'type': 'building',
'value': ''},
{'id': 209809850,
'key': 'building_id',
'type': 'chicago',
'value': ''}]}

思路: 1.使用iterparse便利xml中每一个顶层标签

2.使用自定义函数将每个元素变成多个数据结构

3.利用架构和验证库保证数据格式的正确

4.将每个数据结构写入相应的csv文件

OSM_PATH = "example1.osm"

NODES_PATH = "nodes.csv"  #node标签生成的文件名
NODE_TAGS_PATH = "nodes_tags.csv" #node下的tag标签生成的文件名
WAYS_PATH = "ways.csv" #way标签生成的文件名
WAY_NODES_PATH = "ways_nodes.csv" #way标签下的node生成的文件名
WAY_TAGS_PATH = "ways_tags.csv" #way标签下的tag生成的文件名 LOWER_COLON = re.compile(r'^([a-z]|_)+:([a-z]|_)+') #字符串中有冒号和小写字母的标记
PROBLEMCHARS = re.compile(r'[=\+/&<>;\'"\?%#$@\,\. \t\r\n]')#字符存在问题的标记
SCHEMA = schema.schema #模板文件 # Make sure the fields order in the csvs matches the column order in the sql table schema
#每一个生成的文件的表头
NODE_FIELDS = ['id', 'lat', 'lon', 'user', 'uid', 'version', 'changeset', 'timestamp']
NODE_TAGS_FIELDS = ['id', 'key', 'value', 'type']
WAY_FIELDS = ['id', 'user', 'uid', 'version', 'changeset', 'timestamp']
WAY_TAGS_FIELDS = ['id', 'key', 'value', 'type']
WAY_NODES_FIELDS = ['id', 'node_id', 'position'] def shape_element(element, node_attr_fields=NODE_FIELDS, way_attr_fields=WAY_FIELDS,
problem_chars=PROBLEMCHARS, default_tag_type='regular'):
"""Clean and shape node or way XML element to Python dict""" node_attribs = {} #存放生成node的key和value,key作表头,value作内容
way_attribs = {} #存放生成way的key和value,key作表头,value作内容
way_nodes = [] #存放生成way标签下的nd子标签的值,[{...},{...}]
tags = [] #存放node和way下的tag子标签的值 ,[{...},{...},]# Handle secondary tags the same way for both node and way elements # YOUR CODE HERE
#先提取node字段
if element.tag == 'node':
#1.循环node_field表头,如果element中有key所对应的属性,则放入到node_attribs字典中
for key in NODE_FIELDS:
node_attribs[key] = element.attrib[key]
#2.循环子节点,获取tags元素的值
for child in element:
Node_Tags = {}
#匹配字母和冒号
colon = re.match(LOWER_COLON,child.attrib['k'])
#匹配异常字符
problem = re.match(PROBLEMCHARS,child.attrib['k'])
#异常字符直接跳过,进行下一次查找
if problem:
continue
#如果tag是包含字母和冒号<tag k="addr:housenumber" v="1412"/>需要解析成{'id': 12345, 'key': 'housenumber', 'value': '1412', 'type': 'addr'}
elif colon:
#从父节点获取id属性的值
Node_Tags['id'] = element.attrib['id']
#获取k="addr:housenumber"的值,以:拆分,第一个值为type的值
type_value = child.attrib['k'].split(':',1)[0]
Node_Tags['type'] = type_value
#获取k="addr:housenumber"的值,以:拆分,第二个值为key的值
Node_Tags['key'] = child.attrib['k'].split(':',1)[1]
#获取v=1412的值,为value的值
Node_Tags['value'] = child.attrib['v']
#将处理后的数据加入到字典中
tags.append(Node_Tags)
#tag不包含冒号<tag k="building" v="yes"/>
else:
#从父节点获取id属性的值
Node_Tags['id'] = element.attrib['id']
#type的值是 regular
Node_Tags['type'] = 'regular'
#获取k=building的值,为key的值
Node_Tags['key'] = child.attrib['k']
#获取v=yes的值,为value的值
Node_Tags['value'] = child.attrib['v']
#将处理后的数据加入到字典中
tags.append(Node_Tags)
#返回node处理之后的结果
return {'node': node_attribs, 'node_tags': tags}
#在提取way字段
elif element.tag == 'way':
1.循环way_field表头,如果element中有key所对应的属性,则放入到way_attribs字典中
for key in WAY_FIELDS:
way_attribs[key] = element.attrib[key]
counter = 0 #计数,用于填充way下面nd子标签的position的值
#循环父节点下的子节点
for child in element:
Way_Nodes = {} #存放nd子标签
Way_Tags = {} #存放tag子标签
#处理nd子标签
if child.tag == 'nd':
#从父节点获取id属性的值
Way_Nodes['id'] = element.attrib['id']
#从自身的ref,来获取该属性的值
Way_Nodes['node_id'] = child.attrib['ref']
#获取position的值,每循环一次nd,counter + 1
Way_Nodes['position'] = counter
counter += 1
将处理后的nd子节点数据加入到字典中
way_nodes.append(Way_Nodes)
#处理tag子标签
elif child.tag == 'tag':
#同处理node下的tag子节点
colon = re.match(LOWER_COLON,child.attrib['k'])
problem = re.match(PROBLEMCHARS,child.attrib['k'])
if problem:
continue
elif colon:
Way_Tags['id'] = element.attrib['id']
type_value = child.attrib['k'].split(':',1)[0]
Way_Tags['key'] = child.attrib['k'].split(':',1)[1]
Way_Tags['type'] = type_value
Way_Tags['value'] = child.attrib['v']
tags.append(Way_Tags)
else:
Way_Tags['id'] = element.attrib['id']
Way_Tags['key'] = child.attrib['k']
Way_Tags['type'] = 'regular'
Way_Tags['value'] = child.attrib['v']
tags.append(Way_Tags)
return {'way': way_attribs, 'way_nodes': way_nodes, 'way_tags': tags} def get_element(osm_file, tags=('node', 'way', 'relation')):
"""Yield element if it is the right type of tag"""
"""如果是正确的类型时,返回标签中的tag"""
context = ET.iterparse(osm_file, events=('start', 'end'))
_, root = next(context)
for event, elem in context:
if event == 'end' and elem.tag in tags:
yield elem
root.clear() def validate_element(element, validator, schema=SCHEMA):
"""Raise ValidationError if element does not match schema"""
"""当和schema的数据格式不匹配时,抛出异常"""
if validator.validate(element, schema) is not True:
field, errors = next(validator.errors.iteritems())
message_string = "\nElement of type '{0}' has the following errors:\n{1}"
error_string = pprint.pformat(errors) raise Exception(message_string.format(field, error_string)) class UnicodeDictWriter(csv.DictWriter, object):
"""Extend csv.DictWriter to handle Unicode input"""
"""扩展csv下的DictWriter方法的去支持Unicode输入"""
def writerow(self, row):
super(UnicodeDictWriter, self).writerow({
k: (v.encode('utf-8') if isinstance(v, unicode) else v) for k, v in row.iteritems()
}) def writerows(self, rows):
for row in rows:
self.writerow(row) def process_map(file_in, validate):
"""Iteratively process each XML element and write to csv(s)"""
"""将处理好的xml文件写入到csv中"""
with codecs.open(NODES_PATH, 'w') as nodes_file, \
codecs.open(NODE_TAGS_PATH, 'w') as nodes_tags_file, \
codecs.open(WAYS_PATH, 'w') as ways_file, \
codecs.open(WAY_NODES_PATH, 'w') as way_nodes_file, \
codecs.open(WAY_TAGS_PATH, 'w') as way_tags_file: nodes_writer = UnicodeDictWriter(nodes_file, NODE_FIELDS)
node_tags_writer = UnicodeDictWriter(nodes_tags_file, NODE_TAGS_FIELDS)
ways_writer = UnicodeDictWriter(ways_file, WAY_FIELDS)
way_nodes_writer = UnicodeDictWriter(way_nodes_file, WAY_NODES_FIELDS)
way_tags_writer = UnicodeDictWriter(way_tags_file, WAY_TAGS_FIELDS) nodes_writer.writeheader()
node_tags_writer.writeheader()
ways_writer.writeheader()
way_nodes_writer.writeheader()
way_tags_writer.writeheader() validator = cerberus.Validator() for element in get_element(file_in, tags=('node', 'way')):
el = shape_element(element)
if el:
if validate is True:
validate_element(el, validator) if element.tag == 'node':
nodes_writer.writerow(el['node'])
node_tags_writer.writerows(el['node_tags'])
elif element.tag == 'way':
ways_writer.writerow(el['way'])
way_nodes_writer.writerows(el['way_nodes'])
way_tags_writer.writerows(el['way_tags'])

第二种方法

高阶解法

def shape_tag(el, tag): 
#tag标签返回的格式(el是父节点标签指的是node标签,tag是子节点指的是tag标签)
tag = {
'id' : el.attrib['id'],
'key' : tag.attrib['k'],
'value': tag.attrib['v'],
'type' : 'regular'
} if LOWER_COLON.match(tag['key']):
#如果tag的key中出现冒号<tag k="addr:housenumber" v="1412"/>,则根据:进行拆分,获取type和key
tag['type'], _, tag['key'] = tag['key'].partition(':')
return tag def shape_way_node(el, i, nd):
#way下的nd标签返回的格式(el是父节点标签指的是way标签,nd是子节点指的是nd标签)
return {
'id' : el.attrib['id'],
'node_id' : nd.attrib['ref'],
'position' : i
} def shape_element(element, node_attr_fields=NODE_FIELDS, way_attr_fields=WAY_FIELDS,
problem_chars=PROBLEMCHARS, default_tag_type='regular'):
"""Clean and shape node or way XML element to Python dict""" node_attribs = {}
way_attribs = {}
way_nodes = []
#直接获取所有的tag子标签
tags = [shape_tag(element, t) for t in element.iter('tag')] # Handle secondary tags the same way for both node and way elements # YOUR CODE HERE
if element.tag == 'node':
node_attribs = {f: element.attrib[f] for f in node_attr_fields}
return {'node': node_attribs, 'node_tags': tags}
elif element.tag == 'way':
way_attribs = {f: element.attrib[f] for f in way_attr_fields}
#获取way标签下nd标签的各个值
way_nodes = [shape_way_node(element, i, nd)
for i, nd
in enumerate(element.iter('nd'))]
return {'way': way_attribs, 'way_nodes': way_nodes, 'way_tags': tags}

6.数据清洗(准备数据库 MonogoDB版本)

处理数据并将数据形状变成我们之前提到的模型。输出应该是字典列表,如下所示

{
"id": "",
"type: "node",
"visible":"true",
"created": {
"version":"",
"changeset":"",
"timestamp":"2013-08-03T16:43:42Z",
"user":"linuxUser16",
"uid":""
},
"pos": [41.9757030, -87.6921867],
"address": {
"housenumber": "",
"postcode": "",
"street": "North Lincoln Ave"
},
"amenity": "restaurant",
"cuisine": "mexican",
"name": "La Cabana De Don Luis",
"phone": "1 (773)-271-5176"
}

要求:

1.node下的tag子标签处理如下

<tag k="addr:housenumber" v=""/>
<tag k="addr:street" v="North Lincoln Avenue"/>
<tag k="addr:street:name" v="Lincoln"/>
<tag k="addr:street:prefix" v="North"/>
<tag k="addr:street:type" v="Avenue"/>
<tag k="amenity" v="pharmacy"/> 应该改写为: {...
"address": {
"housenumber": 5158,
"street": "North Lincoln Avenue"
}
"amenity": "pharmacy",
...
}

2.way标签下的子标签的处理应该改为

<nd ref=""/>
<nd ref=""/>
应该改为
"node_refs": ["", ""]
lower = re.compile(r'^([a-z]|_)*$')
lower_colon = re.compile(r'^([a-z]|_)*:([a-z]|_)*$')
problemchars = re.compile(r'[=\+/&<>;\'"\?%#$@\,\. \t\r\n]') CREATED = [ "version", "changeset", "timestamp", "user", "uid"] def shape_element(element):
node = {}
if element.tag == "node" or element.tag == "way" :
# YOUR CODE HERE #1.获取非父子节点的key和value
node = {tag.attrib['k']:tag.attrib['v']
for tag in element.iter('tag')
if not tag.attrib['k'].startswith('addr:')
and not problemchars.search(tag.attrib['k'])}
#2.获取address节点的key和value
#例:<tag k="addr:street:name" v="Lincoln"/>
#1)将addr:后面的字符作为key,v的值作为value
#2)如果标签中的key值以addr:开头,且:的数量等于1
#3)且没有特殊字符的存在
node['address'] = {tag.attrib['k'][5:]: tag.attrib['v']
for tag in element.iter('tag')
if tag.attrib['k'].startswith('addr:')
and tag.attrib['k'].count(':') == 1
and not problemchars.search(tag.attrib['k'])}
#3.获取element节点的属性
     attr = element.attrib
node['id'] = attr['id'] #获取id
node['type'] = element.tag #获取类型type
node['visible'] = attr.get('visible') #获取visible      #4.获取created节点中的key和value
node['created'] = {c:attr[c] for c in CREATED}
#5.如果标签的类型是way,则从该标签获取ref的值封装到node_refs中,否则直接从node中获取lat,lon的值填充到pos中
if element.tag == 'way':
node['node_refs'] = [nd.attrib['ref'] for nd in element.iter('nd')]
else:
node['pos'] = [float(attr['lat']),float(attr['lon'])]
return node
else:
return None def process_map(file_in, pretty = False):
# You do not need to change this file
file_out = "{0}.json".format(file_in)
data = []
with codecs.open(file_out, "w") as fo:
for _, element in ET.iterparse(file_in):
el = shape_element(element)
if el:
data.append(el)
if pretty:
fo.write(json.dumps(el, indent=2)+"\n")
else:
fo.write(json.dumps(el) + "\n")
return data
def test():
#如果测试代码不出错,则结果正确
correct_first_elem = {
"id": "",
"visible": "true",
"type": "node",
"pos": [41.9730791, -87.6866303],
"created": {
"changeset": "",
"user": "bbmiller",
"version": "",
"uid": "",
"timestamp": "2012-03-28T18:31:23Z"
}
}
assert data[0] == correct_first_elem
assert data[-1]["address"] == {
"street": "West Lexington St.",
"housenumber": ""
}
assert data[-1]["node_refs"] == [ "", "", "", "",
"", "", ""] if __name__ == "__main__":
test()

OpenStreetMap数据清洗(SQL&MonogoDB版本)的更多相关文章

  1. 使用的 SQL Server 版本不支持数据类型“datetime2”.

    错误原因,在使用ado.net entity的时候,entity使用的数据库是sqlserver 2008, 但后来实际使用中使用的数据库是sqlserver 2005, 使用的 SQL Server ...

  2. sql server版本、组件和管理工具

    以下信息由何问起收集,希望有帮助. SQL Server 版本 定义 Enterprise 作为高级版本, SQL Server Enterprise 版提供了全面的高端数据中心功能,性能极为快捷.虚 ...

  3. SQL SERVER版本补丁体系及升级

    首先了解几个定义: RTM : 表示 Release to Manufacturing ,这是产品的原始发布版本,当从光盘或 MSDN 下载的默认版本.不过现在下载 SQL Server 版本时,也有 ...

  4. ef SQL Server 版本不支持数据类型“datetime2”

    我遇到这个问题是在用数据库模型的时候.当时我电脑上是sql2008 通过vs2010建立了一个ADO.net数据库模型,之后在项目上线的时候,临时把数据库换成了sql2005,在添加新闻的时候出现了“ ...

  5. PIVOT 和 UNPIVOT 命令的SQL Server版本

    I:使用 PIVOT 和 UNPIVOT 命令的SQL Server版本要求 1.数据库的最低版本要求为 SQL Server 2005 或 更高 2.必须将数据库的兼容级别设置为 90 或 更高 3 ...

  6. C#检验IIS版本、SQL Server版本、SilverLight版本

    之前做一个小项目,使用C#检验这些软件的版本,到处找了一些代码,也能作用,记录一下,以防以后用到. 一.检验IIS版本 public static bool checkIIS(string destV ...

  7. sql server2005版本中,len函数计算了字符串末尾的空格

    sql server2005版本中,len函数计算了字符串末尾的空格的长度,以下是测试脚本: print @@version declare @v varchar(max) set @v = 'hp, ...

  8. PCB MS SQL SERVER版本管控工具source_safe_for_sql_server

    PCB由于业务关系复杂,业务触发一个事件时,可能需与数据库多个表进行关连处理才能拿到数据结果, 而表关连并不是简单的关连,实际是要进行大量数据筛选,逻辑判断,转换等过程...这个过程是复杂的 想一想, ...

  9. [转帖]sql server版本特性简介、版本介绍简介

    sql server版本特性简介.版本介绍简介 https://www.cnblogs.com/gered/p/10986240.html 目录 1.1.sql server的版本信息 1.2.版本重 ...

随机推荐

  1. Vue 环境搭建之Hello World

    建 目录 webpack-vuedemo1 安装依赖组件 : 初始化 npm init npm install --save vue npm install --save-dev babel-core ...

  2. 手机termux上安装msfconsole

    大家可能因为手机没有root而不能通过deploy安装kali 我们使用termux来安装渗透工具 1.下载并安装Termux,更新软件源并升级软件包 apt update apt upgrade a ...

  3. isdigit函数

    isdigit是计算机应用C语言中的一个函数,主要用于检查参数c是否为阿拉伯数字0到9. 相关函数 isdigit 表头文件 #include <ctype.h>(C语言),#includ ...

  4. BZOJ 1012: [JSOI2008]最大数maxnumber【线段树单点更新求最值,单调队列,多解】

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 10374  Solved: 4535[Subm ...

  5. 支付宝当面付开发(java)

    支付宝当面付开发(java) 业务流程:       接入准备:   直接下载demo: https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7 ...

  6. mysql 恢复数据

    前提:保存了需要恢复数据库的文件 .frm 和 .ibd 文件 条件:InnoDB 类型的 恢复表结构1.新建一个数据库--新建一个表,表名和列数和需要恢复数据库相同2.停止mysql服务器 serv ...

  7. 微信小程序模板消息详解

    先放代码 wxml: <form name='pushMsgFm' report-submit bindsubmit='orderSign'> <view> 单号: 0< ...

  8. html日历(1)

    <html> <head> <link rel="stylesheet" type="text/css" href="S ...

  9. CentOS 6.*通过yum安装 MySQL-5.5

    转自https://www.cnblogs.com/wsl222000/p/5445768.html 1.安装mysql-5.5的yum源 rpm -ivh http://repo.mysql.com ...

  10. 宝塔服务器管理助手Linux面版-使用教程

    在顺利安装宝塔服务器linux面板之后,我们打开这个面板,UI界面设计的很简介,所有命令一看就知道是干什么用的,和我们以前用过的虚拟主机管理后台是很像的. 方法/步骤 1 使用方法如下: 面板地址:h ...