Json文件解析(下)
Json文件解析(下)
代码地址:https://github.com/nlohmann/json
从STL容器转换
任何序列容器(std::array,std::vector,std::deque,std::forward_list,std::list),其值可以被用于构建JSON值(例如,整数,浮点数,布尔值,字符串类型,或者再次在本节中描述STL容器)可被用于创建JSON阵列。这同样适用于类似的关联容器(std::set,std::multiset,std::unordered_set,std::unordered_multiset),但是在这些情况下,数组中的元素的顺序取决于元素是如何在各个STL容器排序。
std ::矢量< INT > c_vector { 1,2,3,4 };
json j_vec(c_vector);
// [1、2、3、4]
std ::双端队列< 双 > c_deque { 1.2,2.3,3.4,5.6 };
json j_deque(c_deque);
// [1.2、2.3、3.4、5.6]
std :: list < bool > c_list { true,true,false,true };
json j_list(c_list);
// [true,true,false,true]
std ::修饰符Modifiers < 的int64_t > c_flist { 12345678909876,23456789098765,34567890987654,45678909876543 };
json j_flist(c_flist);
// [12345678909876、23456789098765、34567890987654、45678909876543]
std ::阵列< 无符号 长,4 > c_array {{ 1,2,3,4 }};
json j_array(c_array);
// [1、2、3、4]
std :: set <std :: string> c_set { “一个”,“两个”,“三个”,“四个”,“一个” };
json j_set(c_set); //仅使用“一个”的一个条目
// // [“四个”,“一个”,“三个”,“两个”]
std :: unordered_set <std :: string> c_uset { “一”,“二”,“三”,“四”,“一” };
json j_uset(c_uset); //仅使用“一个”的一个条目
// //可能是[“两个”,“三个”,“四个”,“一个”]
std :: multiset <std :: string> c_mset { “一个”,“两个”,“一个”,“四个” };
json j_mset(c_mset); //使用两个用于“一个”的条目
//也许[[一个”,“两个”,“一个”,“四个”]
std :: unordered_multiset <std :: string> c_umset { “一”,“二”,“一”,“四” };
json j_umset(c_umset); //使用两个用于“一个”的条目
//也许[[一个”,“两个”,“一个”,“四个”]
同样,任何缔键值容器(std::map,std::multimap,std::unordered_map,std::unordered_multimap),其键可以构造一个std::string,并且其值可以被用于构建JSON值(见上文实施例)可用于创建一个JSON对象。请注意,在使用多图的情况下,JSON对象中仅使用一个键,并且该值取决于STL容器的内部顺序。
std :: map <std :: string,int > c_map {{ “一个”,1 },{ “两个”,2 },{ “三个”,3 }};
json j_map(c_map);
// {“一个”:1,“三个”:3,“两个”:2}
std :: unordered_map < const char *,double > c_umap {{ “一个”,1.2 },{ “两个”,2.3 },{ “三个”,3.4 }};
json j_umap(c_umap);
// {“一个”:1.2,“两个”:2.3,“三个”:3.4}
std :: multimap <std :: string,bool > c_mmap {{ “一个”,true },{ “两个”,true },{ “三个”,false },{ “三个”,true }};
json j_mmap(c_mmap); //仅使用键“三”的一个条目
// //也许{“一个”:true,“两个”:true,“三个”:true}
std :: unordered_multimap <std :: string,bool > c_ummap {{ “一”,true },{ “二”,true },{ “三”,false },{ “三”,true }};
json j_ummap(c_ummap); //仅使用键“三”的一个条目
// //也许{“一个”:true,“两个”:true,“三个”:true}
JSON指针和JSON补丁
该库支持JSON指针(RFC 6901)作为解决结构化值的替代方法。除此之外,JSON Patch(RFC 6902)允许描述两个JSON值之间的差异-有效地允许Unix已知的patch和diff操作。
// JSON值
json j_original = R“( {{
” baz“:[” one“,” two“,” three“],
” foo“:” bar“
} )” _json;
//使用JSON指针(RFC 6901)访问成员
j_original [ “ / baz / 1 ” _json_pointer];
// “两个”
//一个JSON修补程序(RFC 6902)
json j_patch = R“( [[
{” op“:” replace“,” path“:” / baz“,” value“:” boo“},
{” op“:” add “,” path“:” / hello“,” value“:[” world“]},
{” op“:” remove“,” path“:” / foo“}
] )” _json;
//应用补丁
json j_result = j_original.patch(j_patch);
// {
// “ baz”:“ boo”,
// “ hello”:[“ world”]
// }
//根据两个JSON值计算JSON补丁
json :: diff(j_result,j_original);
// [
// {“ op”:“ replace”,“ path”:“ / baz”,“ value”:[“ one”,“ Two”,“ three”]},
// {“ op”:“ remove“,” path“:” / hello“},
// {” op“:” add“,” path“:” / foo“,” value“:” bar“}
// ]
JSON合并补丁
该库支持JSON合并补丁(RFC 7386)作为补丁格式。没有使用JSON指针(请参见上文)来指定要操作的值,而是使用一种语法来描述更改,该语法与拟修改的文档非常相似。
// JSON值
json j_document = R“( {
” a“:” b“,
” c“:{
” d“:” e“,
” f“:” g“
}
}} )” _json;
//补丁
json j_patch = R“( {
” a“:” z“,
” c“:{
” f“:null
}
} )” _json;
//应用补丁
j_document.merge_patch(j_patch);
// {
// “ a”:“ z”,
// “ c”:{
// “ d”:“ e”
// }
// }
隐式转换
支持的类型可以隐式转换为JSON值。
建议不要使用隐式转换从一个JSON值。可以在此处找到有关此建议的更多详细信息。
//字符串
std :: string s1 = “世界好!” ;
json js = s1;
自动 s2 = js.get <std :: string>();
//不推荐
std :: string s3 = js;
std :: string s4;
s4 = js;
//布尔
值bool b1 = true ;
json jb = b1;
自动 b2 = jb.get < bool >();
//不推荐
bool b3 = jb;
布尔 b4;
b4 = jb;
//数字
int i = 42 ;
json jn = i;
自动 f = jn.get < double >();
//不推荐使用
double f2 = jb;
双 f3;
f3 = jb;
//等
请注意,char类型不会自动转换为JSON字符串,而是自动转换为整数。必须明确指定转换为字符串:
char ch = ' A ' ; // ASCII值65
json j_default = ch; //存储整数65
json j_string = std :: string(1,ch); //存储字符串“ A”
任意类型转换
每种类型都可以用JSON序列化,而不仅仅是STL容器和标量类型。通常,会按照以下方式进行操作:
名称空间 ns {
// //一个简单的结构,用于对人员进行建模
struct person {
std :: string名称;
std :: string地址;
INT年龄;
};
}
ns :: person p = { “ Ned Flanders ”,“ 744 Evergreen Terrace ”,60 };
//转换为JSON:将每个值复制到JSON对象中
json j;
j [ “ name ” ] = p.name;
j [ “ address ” ] = p.address;
j [ “ age ” ] = p.age;
// ...
//从JSON转换:复制JSON对象中的每个值
ns :: person p {
j [ “ name ” ]。得到 <std :: string>(),
j [ “ address ” ]。得到 <std :: string>(),
j [ “年龄” ]。获取 < int >()
};
可以工作,但是有很多样板...幸运的是,有更好的方法:
//创建一个人
ns :: person p { “ Ned Flanders ”, “ 744 Evergreen Terrace ”, 60 };
//转换:person-> json
json j = p;
std :: cout << j << std :: endl;
// {“地址”:“ 744 Evergreen Terrace”,“年龄”:60,“名称”:“ Ned Flanders”}
//转换:
json- > person auto p2 = j.get <ns :: person>();
//就是
断言(p == p2);
基本用法
要使与一种类型一起使用,只需提供两个功能:
使用 nlohmann :: json;
命名空间 ns {
void to_json(json&j,const person&p){
j = json {{ “ name ”,p。名称 },{ “地址”,第 地址 },{ “年龄”,第 年龄 }};
}
无效 from_json(const json&j,person&p){
j。在(“名称”)。get_to(第名);
j。在(“地址”)。get_to(第地址);
j。在(“年龄”)。get_to(第年龄);
}
} //名称空间ns
就这样!当json使用类型调用构造函数时,自定义to_json方法将被自动调用。同样,在调用get<your_type>()或时get_to(your_type&),from_json将调用该方法。
一些重要的事情:
- 这些方法必须位于类型的名称空间(可以是全局名称空间)中,否则库将无法找到(在本示例中,位于定义的名称空间ns中person)。
- 在使用这些转换的任何地方,这些方法都必须可用(例如,必须包含适当的标头)。请查看问题1108,了解否则可能发生的错误。
- 使用时get<your_type>(),your_type 必须为DefaultConstructible。(有一种绕过此要求的方法,将在后面介绍。)
- 在函数中from_json,使用函数at()访问对象值而不是operator[]。万一键不存在,at将引发可以处理的异常,而operator[]表现出未定义的行为。
- 无需为STL类型添加序列化器或反序列化器,例如std::vector:该库已经实现了这些。
使用宏简化生活
如果只想对一些结构进行序列化/反序列化,则to_json/ from_json函数可能会很多。
只要(1)想要将JSON对象用作序列化和(2)要将成员变量名称用作该对象中的对象键,就有两个宏可以使生活更轻松:
- NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...) 将在要为其创建代码的类/结构的名称空间内定义。
- NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)在要为其创建代码的类/结构中定义。该宏还可以访问私有成员。
在两个宏中,第一个参数是类/结构的名称,其余所有参数都为成员命名。
例子
上面结构的to_json/ from_json函数person可以通过以下方式创建:
命名空间 ns {
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(人,姓名,地址,年龄)
}
这是一个NLOHMANN_DEFINE_TYPE_INTRUSIVE需要私人成员的示例:
命名空间 ns {
类 地址 {
私有:
std :: string street;
INT housenumber;
INT邮编;
公开:
NLOHMANN_DEFINE_TYPE_INTRUSIVE(地址,街道,门牌号,邮政编码)
};
}
如何转换第三方类型?
这需要更高级的技术。但首先,让看看这种转换机制是如何工作的:
该库使用JSON序列化器将类型转换为json。默认的序列化器nlohmann::json为nlohmann::adl_serializer(ADL表示参数依赖查找)。
这样实现(简化):
template < typename T>
struct adl_serializer {
static void to_json(json&j,const T&value){
//在T的命名空间中调用“ to_json”方法
}
static void from_json(const json&j,T&value){
//相同,但使用“ from_json”方法
}
};
当可以控制类型的名称空间时,此序列化程序可以正常工作。但是,关于boost::optional或std::filesystem::path(C ++ 17)呢?劫持boost名称空间是非常糟糕的,并且向模板添加模板专业化以外的内容是非法的std。
为了解决这个问题,需要adl_serializer在nlohmann名称空间中添加的特殊化,这是一个示例:
//部分专业化(也可以完全专业化)
名称空间 nlohmann {
模板 <类型名 T>
struct adl_serializer <boost :: optional <T >> {
静态 void to_json(json&j, const boost :: optional <T>&opt){
如果(opt == boost :: none){
j = nullptr ;
} 其 {
j = * opt; //这将调用adl_serializer <T> :: to_json将
//发现T的命名空间中的自由函数to_json!
}
}
静态 无效 from_json(const json&j,boost :: optional <T>&opt){
if(j。is_null()){
opt = boost :: none;
} 其 {
选择= j。得到 <T>(); //与上述相同,但
//使用 adl_serializer <T> :: from_json
}
}
};
}
如何get()用于非默认的可构造/不可复制类型?
如果类型为MoveConstructible,则有一种方法。还需要专门化adl_serializer,但要有一个特殊的from_json重载:
struct move_only_type {
move_only_type()= 删除 ;
move_only_type(int ii):i(ii){}
move_only_type(const move_only_type&)= delete ;
move_only_type(move_only_type &&)= 默认值;
诠释 I;
};
名称空间 nlohmann {
template <>
struct adl_serializer <move_only_type> {
//注意:返回类型不再是'void',该方法仅
//使用一个参数
static move_only_type from_json(const json&j){
return {j。get < int >()};
}
//这就是陷阱!必须提供to_json方法!否则
//
将//无法将move_only_type转换为json,因为完全//对该类型的adl_serializer进行了专门化//
static void to_json(json&j,move_only_type t){
j = t ;
}
};
}
可以编写自己的序列化器吗?(高级使用)
是。可能需要看一下unit-udt.cpp测试套件,以查看一些示例。
如果编写自己的序列化器,则需要做一些事情:
- 使用不同的basic_json别名nlohmann::json(的最后一个模板参数basic_json是JSONSerializer)
- basic_json在所有to_json/ from_json方法中使用别名(或模板参数)
- 使用nlohmann::to_json以及nlohmann::from_json何时需要ADL
这是一个示例,没有简化,仅接受大小<= 32的类型,并使用ADL。
// //应该使用void作为第二个模板参数
// //如果不需要对T
template < typename T, typename SFINAE = typename std :: enable_if < sizeof(T)<= 32 > :: type进行编译时检查 >
struct less_than_32_serializer {
模板 <类型名称BasicJsonType>
静态 void to_json(BasicJsonType&j,T值){
//要使用ADL,并
使用 nlohmann :: to_json调用正确的to_json重载;//这个方法由adl_serializer调用,
//这就是
to_json(j,value)发生魔术的地方;
}
template < typename BasicJsonType>
静态 无效 from_json(const BasicJsonType&j,T&value){
//
使用 nlohmann :: from_json进行相同操作;
from_json(j,值);
}
};
重新实现序列化器时要非常小心,如果不注意,可能会导致堆栈溢出:
模板 < 类型名 T,无效 >
结构 bad_serializer
{
template < typename BasicJsonType>
static void to_json(BasicJsonType&j,const T&value){
//这将调用BasicJsonType :: json_serializer <T> :: to_json(j,value);
//如果BasicJsonType :: json_serializer == bad_serializer ...糟糕!
j =值;
}
template < typename BasicJsonType>
static void to_json(const BasicJsonType&j,T&value){
//这将调用BasicJsonType :: json_serializer <T> :: from_json(j,value);
//如果BasicJsonType :: json_serializer == bad_serializer ...糟糕!
值= j。模板 获取 <T>(); //哎呀!
}
};
专门进行枚举转换
默认情况下,枚举值以整数形式序列化为JSON。在某些情况下,这可能会导致不良行为。如果在将数据序列化为JSON之后对枚举进行了修改或重新排序,则较晚的反序列化JSON数据可能是未定义的或与原始预期值不同的枚举值。
可以更精确地指定给定枚举如何映射到JSON和从JSON映射,如下所示:
//示例枚举类型声明
枚举 TaskState {
TS_STOPPED,
TS_RUNNING,
TS_COMPLETED,
TS_INVALID = -1,
};
//将TaskState值作为字符串
NLOHMANN_JSON_SERIALIZE_ENUM 映射到JSON(TaskState,{
{TS_INVALID,nullptr },
{TS_STOPPED,“已停止” },
{TS_RUNNING,“正在运行” },
{TS_COMPLETED,“已完成”),
})
的NLOHMANN_JSON_SERIALIZE_ENUM()宏声明一组to_json()/ from_json()功能型TaskState,同时避免重复和样板序列化代码。
用法:
//以字符串形式枚举JSON
json j = TS_STOPPED;
断言(j == “ stopped ”);
//枚举的json字符串
json j3 = “正在运行”;
断言(j3.get <TaskState>()== TS_RUNNING);
//要枚举的未定义json值(其中,上面的第一个地图项是默认值)
json jPi = 3.14 ;
断言(jPi.get <TaskState>()== TS_INVALID);
就像上面的任意类型转换一样,
- NLOHMANN_JSON_SERIALIZE_ENUM() 必须在枚举类型的名称空间(可以是全局名称空间)中声明,否则库将无法找到,并且将默认为整数序列化。
- 使用转换的任何地方都必须可用(例如,必须包含适当的标题)。
其要点:
- 使用时get<ENUM_TYPE>(),未定义的JSON值将默认为地图中指定的第一对。仔细选择该默认对。
- 如果在地图中多次指定枚举或JSON值,则在与JSON进行相互转换时,将从地图顶部的第一个匹配项返回。
二进制格式(BSON,CBOR,MessagePack和UBJSON)
尽管JSON是一种无处不在的数据格式,但不是一种非常紧凑的格式,适合通过网络进行数据交换。因此,该库支持 BSON(二进制JSON),CBOR(简明二进制对象表示形式),MessagePack和UBJSON(通用二进制JSON规范),以将JSON值有效地编码为字节向量并对该向量进行解码。
//创建一个JSON值
json j = R“( {” compact“:true,” schema“:0} )” _json;
//序列化为BSON
std :: vector <std :: uint8_t > v_bson = json :: to_bson(j);
// 0x1B,0x00、0x00、0x00、0x08、0x63、0x6F,0x6D,0x70、0x61、0x63、0x74、0x00、0x01、0x10、0x73、0x63、0x68、0x65、0x6D,0x61、0x00、0x00 0x00、0x00、0x00
//往返
json j_from_bson = json :: from_bson(v_bson);
//序列化为CBOR
std :: vector <std :: uint8_t > v_cbor = json :: to_cbor(j);
// 0xA2、0x67、0x63、0x6F,0x6D,0x70、0x61、0x63、0x74、0xF5、0x66、0x73、0x63、0x68、0x65、0x6D,0x61、0x00
//往返
json j_from_cbor = json :: from_cbor(v_cbor);
//序列化为MessagePack
std :: vector <std :: uint8_t > v_msgpack = json :: to_msgpack(j);
// 0x82、0xA7、0x63、0x6F,0x6D,0x70、0x61、0x63、0x74、0xC3、0xA6、0x73、0x63、0x68、0x65、0x6D,0x61、0x00
//往返
json j_from_msgpack = json :: from_msgpack(v_msgpack);
//序列化为UBJSON
std :: vector <std :: uint8_t > v_ubjson = json :: to_ubjson(j);
// 0x7B,0x69、0x07、0x63、0x6F,0x6D,0x70、0x61、0x63、0x74、0x54、0x69、0x06、0x73、0x63、0x68、0x65、0x6D,0x61、0x69、0x00、0x7D
//往返
json j_from_ubjson = json :: from_ubjson(v_ubjson);
该库还支持BSON,CBOR(字节字符串)和MessagePack(bin,ext,fixext)的二进制类型。默认存储std::vector<std::uint8_t>为在库外部进行处理。
// CBOR字节串与有效载荷为0xCAFE
的std ::矢量<性病:: uint8_t > V = {的0x42, 0xCA, 0xFE的 };
//读取值
json j = json :: from_cbor(v);
// JSON值的类型为binary
j.is_binary(); //正确
//获取对存储的二进制值的引用
auto&binary = j.get_binary();
//二进制值没有子类型(CBOR没有二进制子类型)
binary.has_subtype(); //错误
//访问std :: vector <std :: uint8_t>成员函数
binary.size(); // 2
binary [ 0 ]; // 0xCA
binary [ 1 ]; // 0xFE
//将子类型设置为0x10
二进制。set_subtype( 0x10);
//序列化为MessagePack
auto cbor = json :: to_msgpack(j); // 0xD5(fixext2),0x10、0xCA,0xFE
支持的编译器
尽管已经是2020年,但对C ++ 11的支持仍然很少。当前,已知以下编译器可以工作:
- GCC 4.8-10.1(可能以后)
- 铛3.4-10.0(可能以后)
- Apple Clang 9.1-12.0(可能更高)
- 英特尔C ++编译器17.0.2(可能更高)
- Microsoft Visual C ++ 2015 /构建工具14.0.25123.0(以及更高版本)
- Microsoft Visual C ++ 2017 /生成工具15.5.180.51428(以及更高版本)
- Microsoft Visual C ++ 2019 /生成工具16.3.1 + 1def00d3d(以及更高版本)
很乐意了解其编译器/版本。
请注意:
- GCC 4.8有一个错误57824):多行原始字符串不能作为宏的参数。不要使用此编译器直接在宏中使用多行原始字符串。
- Android默认使用非常老的编译器和C ++库。要解决此问题,请将以下内容添加到中Application.mk。这将切换到LLVM C ++库,Clang编译器,并启用C ++ 11和其默认禁用的功能。
- APP_STL := c++_shared
- NDK_TOOLCHAIN_VERSION := clang3.6
- APP_CPPFLAGS += -frtti -fexceptions
该代码可使用Android NDK,修订版9-11(以及更高版本)和CrystaX的Android NDK版本10 成功编译。
- 对于在MinGW或Android SDK上运行的GCC 'to_string' is not a member of 'std',可能会发生错误(或类似的for strtod或strtof)。注意,这不是代码问题,而是编译器本身的问题。在Android上,请参见上文以使用较新的环境进行构建。对于MinGW,请参考此站点和此讨论以获取有关如何修复此错误的信息。对于Android NDK的使用APP_STL := gnustl_static,请参考此讨论。
- #error指令拒绝不支持的GCC和Clang版本。可以通过定义关闭JSON_SKIP_UNSUPPORTED_COMPILER_CHECK。请注意,在这种情况下,不希望获得任何支持。
Travis,AppVeyor,GitHub Actions和CircleCI当前在持续集成中使用编译器
Json文件解析(下)的更多相关文章
- Json文件解析(上)
Json文件解析(上) 代码地址:https://github.com/nlohmann/json 自述文件 alt=GitHub赞助商 data-canonical-src="https: ...
- Golang Json文件解析为结构体工具-json2go
代码地址如下:http://www.demodashi.com/demo/14946.html 概述 json2go是一个基于Golang开发的轻量json文件解析.转换命令行工具,目前支持转换输出到 ...
- PHP JSON文件解析并获取key、value,判断key是否存在
/****************************************************************************** * PHP JSON文件解析并获取key ...
- 【微信】微信小程序 微信开发工具中新创建的json文件,编译报错VM1781:2 pages/module/module.json 文件解析错误 SyntaxError: Unexpected end of JSON input
如果新创建报错:编译报错VM1781:2 pages/module/module.json 文件解析错误 SyntaxError: Unexpected end of JSON input 解决方法 ...
- NPOI+Json文件解析Excel
记点笔记,加深印象!最近有个导入Excel工能需要完成,Excel列名是中文的,导入Excel我用的NPOI插件,如果不对Excel做解析,列名有可能会给我带来一些字符方面的麻烦,于是想到了一个比较l ...
- Twaver的mono-desiner导出的json文件解析
以画的交换机为例,其他大概都差不多. 利用Twaver做出交换机模型如图1所示,其中,每一个端口都是一个单独的对象.具体Twaver操作流程参见网址:http://twaver.servasoft.c ...
- json 文件解析与应用
第一步:首先弄一个 json 文件 我这里成为 config.json 内容如下 { ": { , "desc":"中华人民共和国" }, &qu ...
- vue之package.json文件解析
1.package.json是什么? 什么是Node.js的模块(Module)?在Node.js中,模块是一个库或框架,也是一个Node.js项目.Node.js项目遵循模块化的架构,当我们创建了一 ...
- json文件解析
场景 读取json文件,读取子域名扫描结果 实现 >>> import json >>> with open("C:\\Users\\Windows32\ ...
随机推荐
- Windows之磁盘管理
0x01 磁盘管理概述 磁盘管理是一项计算机使用时的常规任务,它是以一组磁盘管理应用程序的形式提供给用户的,他们位于计算机管理控制台中,它包括查错程序和磁盘碎片整理程序以及磁盘整理程序.(来源百度 ...
- Python脚本爬取网站美女照片
上次无意之中看到一个网站,里面全是美女的照片,我就心想,哪天有时间了得把这网站的所有美女照片都得爬下来.今天有时间,写了点代码,爬去了网站的所有照片.附上战果!图片实在是太多了,爬半个多小时 先附上所 ...
- UVA11549计算器谜题
题意: 有一个计算机只能保留数字的前n位,你有一个数字k(k<=9),反复平方后在计算机上显示的最大数字是多少. 思路: 显然这个题目是有循环节的,为什么有循环节?首先 ...
- CTF密码学常见加解密总结
CTF密码学常见加解密总结 2018年03月10日 19:35:06 adversity` 本文链接:https://blog.csdn.net/qq_40836553/article/details ...
- IO异步,读写压缩文件,监控文件系统
这节结尾IO,讲一下异步操作文件,读写压缩文件,监控文件系统这三个知识点. 异步操作文件: 说到异步,必然要了解的是async和await这两个关键字(异步详情点击基于任务的异步编程(Task ...
- Python 之父爆料:明年至少令 Python 提速 1 倍!
大概在半年前,我偶然看到一篇文章,有人提出了给 Python 提速 5 倍的计划,并在寻找经费赞助.当时并没有在意,此后也没有看到这方面的消息. 但是,就在 5 月 13 日"2021 年 ...
- Convert character array to string in MATLAB
Matlab提取特征值是经常要读取多个图片文件,把文件名保存在数组中后再读取会出错.从stackoverflow中找到如下解决方法: I've a M by N matrix, each cell c ...
- 【BUAA软工】第一次团队作业——团队介绍
项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:团队介绍与采访往届团队 团队作业-团队介绍和采访 Part I 团队成员介绍 有图有真(jia)相 大名 个人介绍 角色意向 李PX 来 ...
- 每天一个linux命令(49):at命令 atrm删除作业,由作业号标识。
atq命令 例如:从现在起三天后的下午四点运行作业at 4pm + 3 days:在July 31上午十点运行作业at 10am July 31:明天上午一点运行作业at 1am tomorrow. ...
- 030. Python装饰器
一 装饰器 1.1 装饰器介绍 扩展函数新功能的@定义:替换旧函数,返回新函数,在不改变原有代码的前提下,为该函数扩展新功能;语法:@ (语法糖) 1.2 装饰器的原型 def show(func) ...