Node.js JSON Schema Ajv依赖库逐步介绍验证类型和中文错误提示

在这里插入图片描述

在构建应用程序时,数据的有效性是至关重要的。为了确保传入的数据符合预期的格式和规范,我们可以使用 Ajv(Another JSON Schema Validator)进行验证。在这篇博文中,我们将从头开始学习 Ajv,逐步介绍验证类型和中文错误提示。

1. 什么是 Ajv?

Ajv 是一个用于验证 JSON 数据的库,它支持 JSON Schema 规范。通过定义 JSON Schema,我们可以描述数据的结构、类型和约束,然后使用 Ajv 来验证数据是否符合这些规范。

2. 安装 Ajv

首先,我们需要安装 Ajv 和一些相关的插件,打开终端并执行以下命令:

npm install ajv ajv-errors ajv-formats ajv-i18n koa @koa/router koa-bodyparser

这些插件包括错误处理插件 ajv-errors、格式验证插件 ajv-formats、中文错误提示插件 ajv-i18n 以及用于构建 Koa 应用的 koa@koa/routerkoa-bodyparser

3. 编写验证规范

我们将使用 Ajv 验证一个包含各种数据类型的 JSON 对象。以下是我们要验证的 JSON Schema:
为了添加中文注释,我们可以在 JSON Schema 的每个属性的注释中添加相关的中文描述。以下是带有中文注释的 JSON Schema:

const schema = {
  type: 'object',
  properties: {
    // 姓名,长度在3到20之间
    name: { type: 'string', minLength: 3, maxLength: 20, description: '姓名,长度在3到20之间' },
    
    // 年龄,必须是整数且不小于18
    age: { type: 'integer', minimum: 18, description: '年龄,必须是整数且不小于18' },
    
   	//余额,可以是浮点数
    balance: {
        type: "number",
        not: { type: "null" }
   	},
    // 爱好,是一个字符串数组
    hobbies: {
      type: 'array',
      items: { type: 'string' },
      description: '爱好,是一个字符串数组',
    },
    
    // 电子邮箱,必须符合邮箱格式
    email: { type: 'string', format: 'email', description: '电子邮箱,必须符合邮箱格式' },
    
    // 生日,必须符合日期格式
    birthday: { type: 'string', format: 'date', description: '生日,必须符合日期格式' },
    
    // 值,是一个包含数字和字符串的数组,且不能超过两个元素
    values: {
      type: 'array',
      items: [
        { type: 'integer', description: '第一个值是数字' },
        { type: 'string', description: '第二个值是字符串' },
      ],
      additionalItems: false, // 防止数组包含超过两个元素
      description: '值,是一个包含数字和字符串的数组,且不能超过两个元素',
    },
  
    // 地址列表,是一个包含城市和邮政编码的对象数组
    addresses: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          // 城市
          city: { type: 'string', description: '城市' },
          
          // 邮政编码
          zipCode: { type: 'string', description: '邮政编码' },
        },
        required: ['city', 'zipCode'],
      },
      description: '地址列表,是一个包含城市和邮政编码的对象数组',
    },
  },
  required: ['name', 'age', 'values', 'addresses', 'birthday', 'email'],
};

在这个例子中,我在每个属性的 description 中添加了中文注释,以描述该属性的含义和约束。这将有助于其他开发人员理解和维护这个 JSON Schema。

这个 JSON Schema 定义了一个对象,其中包含了字符串、整数、数组、邮箱、日期等各种类型的属性,并设置了一些约束条件。
如字符串、整数、数组、对象等。然而,还有一些其他可能用到的验证类型,具体取决于你的应用需求。以下是一些可能有用的额外验证类型和示例:

  1. Boolean 类型:

    const schemaWithBoolean = {
      type: 'object',
      properties: {
        isActive: { type: 'boolean' },
      },
      required: ['isActive'],
    };
    
  2. Null 类型:

    const schemaWithNull = {
      type: 'object',
      properties: {
        description: { type: 'null' },
      },
      required: ['description'],
    };
    
  3. 数字范围:

    const schemaWithNumberRange = {
      type: 'object',
      properties: {
        quantity: { type: 'integer', minimum: 0, maximum: 100 },
      },
      required: ['quantity'],
    };
    
  4. 字符串模式:

    const schemaWithStringPattern = {
      type: 'object',
      properties: {
        code: { type: 'string', pattern: '^ABC\\d{3}$' }, // 匹配以"ABC"开头,后跟三个数字的字符串
      },
      required: ['code'],
    };
    
  5. 枚举值:

    const schemaWithEnum = {
      type: 'object',
      properties: {
        gender: { type: 'string', enum: ['male', 'female', 'other'] },
      },
      required: ['gender'],
    };
    
  6. 数组长度:

    const schemaWithArrayLength = {
      type: 'object',
      properties: {
        tags: { type: 'array', minItems: 1, maxItems: 5 },
      },
      required: ['tags'],
    };
    

ajv-formats 是 Ajv 的一个插件,它提供了一些常见的格式校验,使得我们可以更方便地验证数据是否符合特定的格式要求。以下是该插件提供的一些格式校验以及它们的用法示例:

  1. date-time: 校验日期时间格式。
const schema = {
  type: 'string',
  format: 'date-time',
};

// 示例数据
const validDateTime = '2022-02-14T10:30:00Z';
  1. time: 校验时间格式。
const schema = {
  type: 'string',
  format: 'time',
};

// 示例数据
const validTime = '10:30:00';
  1. date: 校验日期格式。
const schema = {
  type: 'string',
  format: 'date',
};

// 示例数据
const validDate = '2022-02-14';
  1. email: 校验邮箱格式。
const schema = {
  type: 'string',
  format: 'email',
};

// 示例数据
const validEmail = 'example@email.com';
  1. hostname: 校验主机名格式。
const schema = {
  type: 'string',
  format: 'hostname',
};

// 示例数据
const validHostname = 'www.example.com';
  1. ipv4: 校验 IPv4 地址格式。
const schema = {
  type: 'string',
  format: 'ipv4',
};

// 示例数据
const validIPv4 = '192.168.0.1';
  1. ipv6: 校验 IPv6 地址格式。
const schema = {
  type: 'string',
  format: 'ipv6',
};

// 示例数据
const validIPv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
  1. uri: 校验 URI 格式。
const schema = {
  type: 'string',
  format: 'uri',
};

// 示例数据
const validURI = 'https://www.example.com';
  1. uri-reference: 校验 URI 引用格式。
const schema = {
  type: 'string',
  format: 'uri-reference',
};

// 示例数据
const validURIReference = '/path/to/resource';
  1. uri-template: 校验 URI 模板格式。
const schema = {
  type: 'string',
  format: 'uri-template',
};

// 示例数据
const validURITemplate = '/users/{id}';
  1. json-pointer: 校验 JSON 指针格式。
const schema = {
  type: 'string',
  format: 'json-pointer',
};

// 示例数据
const validJSONPointer = '/path/to/property';
  1. relative-json-pointer: 校验相对 JSON 指针格式。
const schema = {
  type: 'string',
  format: 'relative-json-pointer',
};

// 示例数据
const validRelativeJSONPointer = '1/child';
  1. regex: 校验正则表达式。
const schema = {
  type: 'string',
  format: 'regex',
  pattern: '^\\d{3}-\\d{2}-\\d{4}$', // 正则表达式
};

// 示例数据
const validRegex = '123-45-6789';

这些格式校验使得我们在验证数据时更加灵活,能够直接使用预定义的格式进行验证,提高了数据验证的准确性和可读性。
这些是一些可能有用的验证类型和约束。根据你的具体需求,你可能需要进一步了解 JSON Schema 的其他验证选项。 JSON Schema 支持丰富的验证功能,以满足各种数据模型的需求。

4. 中间件:验证请求数据

接下来,我们将创建一个 Koa 中间件来验证请求数据是否符合上述定义的 JSON Schema。在中间件中,我们使用 Ajv 编译 JSON Schema 并验证请求数据:

const Ajv = require('ajv');
const localize = require('ajv-i18n');
const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
require('ajv-formats')(ajv);

// 中间件:校验请求数据
const validateMiddleware = async (ctx, next) => {
  const data = ctx.request.body;

  // 编译 JSON Schema
  const validate = ajv.compile(schema);

  // 验证数据是否符合 JSON Schema
  const isValid = validate(data);

  if (!isValid) {
    // 指定语言为中文
    localize.zh(validate.errors);
    // 设置 errorsText 选项为中文
    const errorText = ajv.errorsText(validate.errors, { separator: '\n', dataVar: 'data' });

    ctx.status = 400;
    ctx.body = {
      error: 'Invalid data',
      details: errorText,
    };
    return;
  }

  await next();
};

在这个中间件中,我们使用 ajv.errorsText 来生成错误文本,同时将 dataVar 选项设置为 'data',以确保在错误消息中使用中文。如果数据验证不通过,中间件将返回包含中文错误信息的 400 错误响应。

5. 应用 Koa 路由

最后,我们将创建一个 Koa 应用,使用上述中间件处理 /api/data 路由的 POST 请求:

const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');

const app = new Koa();
const router = new Router();

// 使用中间件
app.use(bodyParser());

// 路由处理
router.post('/api/data', validateMiddleware, async (ctx) => {
  ctx.body = { message: 'Data is valid!' };
});

// 添加路由
app.use(router.routes());
app.use(router.allowedMethods());

// 启动应用
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

现在,我们的 Koa 应用已经可以验证请求数据,并返回相应的中文错误信息了。

通过这篇博文,我们逐步学习了如何使用 Ajv 验证不同类型的数据,并在 Koa 应用中实现中文错误提示。这为构建健壮的应用程序提供了强大的数据验证工具。

完整验证接口数据示例代码

const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const Ajv = require('ajv');
const localize = require("ajv-i18n");

const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
require('ajv-formats')(ajv);

const app = new Koa();
const router = new Router();

// 定义 JSON Schema
const schema = {
    type: 'object',
    properties: {
        // 姓名,长度在3到20之间
        name: { type: 'string', minLength: 3, maxLength: 20, description: '姓名,长度在3到20之间' },

        // 年龄,必须是整数且不小于18
        age: { type: 'integer', minimum: 18, description: '年龄,必须是整数且不小于18' },

        // 爱好,是一个字符串数组
        hobbies: {
            type: 'array',
            items: { type: 'string' },
            description: '爱好,是一个字符串数组',
        },

        // 电子邮箱,必须符合邮箱格式
        email: { type: 'string', format: 'email', description: '电子邮箱,必须符合邮箱格式' },

        // 生日,必须符合日期格式
        birthday: { type: 'string', format: 'date', description: '生日,必须符合日期格式' },

        // 值,是一个包含数字和字符串的数组,且不能超过两个元素
        values: {
            type: 'array',
            items: [
                { type: 'integer', description: '第一个值是数字' },
                { type: 'string', description: '第二个值是字符串' },
            ],
            additionalItems: false, // 防止数组包含超过两个元素
            description: '值,是一个包含数字和字符串的数组,且不能超过两个元素',
        },

        // 地址列表,是一个包含城市和邮政编码的对象数组
        addresses: {
            type: 'array',
            items: {
                type: 'object',
                properties: {
                    // 城市
                    city: { type: 'string', description: '城市' },

                    // 邮政编码
                    zipCode: { type: 'string', description: '邮政编码' },
                },
                required: ['city', 'zipCode'],
            },
            description: '地址列表,是一个包含城市和邮政编码的对象数组',
        },
    },
    required: ['name', 'age', 'values', 'addresses', 'birthday', 'email'],
};
// 中间件:校验请求数据
const validateMiddleware = async (ctx, next) => {
    const data = ctx.request.body;

    // 编译 JSON Schema
    const validate = ajv.compile(schema);

    // 验证数据是否符合 JSON Schema
    const isValid = validate(data);

    if (!isValid) {
        // 指定语言为中文
        localize.zh(validate.errors);
        // 设置 errorsText 选项为中文
        const errorText = ajv.errorsText(validate.errors, { separator: '\n', dataVar: 'data' });

        ctx.status = 400;
        ctx.body = {
            error: 'Invalid data',
            details:errorText,
        };
        return;
    }

    await next();
};

// 使用中间件
app.use(bodyParser());

// 路由处理
router.post('/api/data', validateMiddleware, async (ctx) => {
    ctx.body = { message: '数据验证通过' };
});

// 添加路由
app.use(router.routes());
app.use(router.allowedMethods());

// 启动应用
const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

HTTP 请求示例数据

POST /api/data HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json
Content-Length: 313

{
  "name":"xiongmingcai",
   "email":"xiongmingcai(#)gmail.com",
  "age":30,
  "birthday":"1990-05-15",
  "hobbies":["唱跳","RAP","打篮球"],
    "values":[1,"字符串"],
    "addresses":[{
        "city":"北京",
        "zipCode":"000000"
    },{
        "city":"长沙",
        "zipCode":"000000"
    }
    ]
}

进阶用法 使用 $ref 引用其他 JSON Schema

const mainSchema = {
  $id: 'mainSchema',
  type: 'object',
  properties: {
    person: { $ref: 'personSchema' },
    address: { $ref: 'addressSchema' },
  },
};

const personSchema = {
  $id: 'personSchema',
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'integer' },
  },
  required: ['name', 'age'],
};

const addressSchema = {
  $id: 'addressSchema',
  type: 'object',
  properties: {
    city: { type: 'string' },
    zipCode: { type: 'string' },
  },
  required: ['city', 'zipCode'],
};

const ajv = new Ajv();
ajv.addSchema([mainSchema, personSchema, addressSchema]);

const validateMain = ajv.getSchema('mainSchema');
const data = {
  person: { name: 'John', age: 25 },
  address: { city: 'New York', zipCode: '10001' },
};

const isValid = validateMain(data);

if (isValid) {
  console.log('Data is valid!');
} else {
  console.error('Data is invalid!');
  console.error(validateMain.errors);
}

组合关键字(AJV allOf、anyOf、oneOf、not)

AJV 提供了一些组合关键字,如 allOfanyOfoneOfnot,用于在 JSON Schema 中表示更复杂的逻辑关系。以下是这些关键字的使用示例:

1. allOf:所有条件都必须匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 allOf
const schema = {
  allOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John', age: 25 };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

2. anyOf:至少一个条件匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 anyOf
const schema = {
  anyOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John' };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

3. oneOf:只有一个条件匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 oneOf
const schema = {
  oneOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John' };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

4. not:条件不能匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 not
const schema = {
  not: {
    type: 'object',
    properties: { age: { type: 'number' } },
  },
};

// 示例数据
const invalidData = { age: 25 };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(invalidData);

console.log(isValid); // 输出 false

这些关键字允许你构建更复杂的验证规则,以满足特定的数据结构和逻辑需求。在实际应用中,可以根据具体情况组合使用这些关键字。。

如何设置自定义AJV关键字?( custom AJV keyword)

Ajv 允许你定义自己的 JSON Schema 关键字,以扩展验证功能。
在 TypeScript 环境下,你可以使用以下方式使用自定义关键字:

import Ajv, { AnySchemaObject } from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 自定义关键字定义
let kwdOrDef: FuncKeywordDefinition = {
  keyword: 'eachPropIsTrue',       // 关键字的名称
  type: 'object',                  // 关键字适用的 JSON 数据类型
  schemaType: 'boolean',           // 关键字的 schema 类型
  compile: (schema: boolean, parentSchema: AnySchemaObject) => {
    // 编译函数,用于生成验证函数
    return (data: Record<string, any>) => {
      // 验证函数逻辑
      return Object.values(data).every((value) => !!value);
    };
  },
};

// 添加自定义关键字到 Ajv 实例中
ajv.addKeyword(kwdOrDef);

// 定义 JSON Schema
const schema = {
  type: 'object',
  eachPropIsTrue: true,
};

// 示例数据
const validData = {
  prop1: true,
  prop2: false,
  prop3: true,
};

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 false,因为 prop2 是 false

在上述示例中:

  1. 引入 Ajv 并使用 AnySchemaObject 接口。
  2. 使用 ajv.addKeyword 添加自定义关键字。
  3. 在 JSON Schema 中使用自定义关键字 eachPropIsTrue
  4. 编译 JSON Schema 并验证数据是否符合。

这样,你就可以在 TypeScript 环境下使用自定义关键字了。确保在编写 TypeScript 代码时,按照 TypeScript 的语法规范进行书写。

自定义格式(custom AJV format)

要在 Ajv 中添加自定义格式来验证身份证号码,你需要使用 ajv.addFormat 方法并提供一个验证函数。以下是一个简单的示例,演示了如何验证身份证号码的基本格式:

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 添加身份证号码格式验证
ajv.addFormat('idNumber', (data) => {
  // 简单示例:验证身份证号码为18位数字
  const regex = /^[0-9]{18}$/;
  return regex.test(data);
});

// 定义 JSON Schema
const schema = {
  type: 'string',
  format: 'idNumber',
};

// 示例数据
const validIdNumber = '123456789012345678';
const invalidIdNumber = '1234567890'; // 不符合格式

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);

console.log(validate(validIdNumber)); // 输出 true
console.log(validate(invalidIdNumber)); // 输出 false

在这个示例中,ajv.addFormat 方法添加了一个名为 'idNumber' 的自定义格式,它使用了一个简单的正则表达式来验证身份证号码是否为18位数字。你可以根据实际需求更改验证逻辑,例如验证生日、地区等详细信息。

请注意,身份证号码的验证逻辑因国家而异,这里只是一个简单的示例。在实际应用中,你可能需要使用更复杂的验证规则来确保身份证号码的准确性和合法性。

异步验证:(Ajv compileAsync)

对于异步操作,Ajv 提供了 compileAsync 方法来编译异步的 JSON Schema。
https://ajv.js.org/guide/async-validation.html
官网示例代码 没研究明白

const ajv = new Ajv()

ajv.addKeyword({
  keyword: "idExists",
  async: true,
  type: "number",
  validate: checkIdExists,
})

async function checkIdExists(schema, data) {
  // this is just an example, you would want to avoid SQL injection in your code
  const rows = await sql(`SELECT id FROM ${schema.table} WHERE id = ${data}`)
  return !!rows.length // true if record is found
}

const schema = {
  $async: true,
  properties: {
    userId: {
      type: "integer",
      idExists: {table: "users"},
    },
    postId: {
      type: "integer",
      idExists: {table: "posts"},
    },
  },
}

const validate = ajv.compile(schema)

validate({userId: 1, postId: 19})
  .then(function (data) {
    console.log("Data is valid", data) // { userId: 1, postId: 19 }
  })
  .catch(function (err) {
    if (!(err instanceof Ajv.ValidationError)) throw err
    // data is invalid
    console.log("Validation errors:", err.errors)
  })

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/373687.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第7节、双电机直线运动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;前面章节主要介绍单个电机控制&#xff0c;本节内容介绍两个电机完成Bresenham直线运动 一、Bresenham直线算法介绍 Bresenham直线算法由Jack Elton Bresenham于1962年在IBM开发&#xff0c;最初用于计…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-16-处理模态对话框弹窗

1.简介 我们在日常工作中&#xff0c;会经常遇到弹出警告框的问题&#xff0c;弹框无法绕过&#xff0c;必须处理才可以执行后续的测试&#xff0c;所以弹框处理也是我们必须掌握的一个知识。宏哥在javaselenium系列文章中介绍过这部分内容。那么&#xff0c;playwright对于弹…

第2节、让电机转起来【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍用简单的方式&#xff0c;让步进电机转起来。其目的之一是对电机转动有直观的感受&#xff0c;二是熟悉整个开发流程。本系列教程必要的51单片机基础包括IO口操作、中断、定时器三个部分&#…

6、基于机器学习的预测

应用机器学习的任何预测任务与这四个策略。 文章目录 1、简介1.1定义预测任务1.2准备预测数据1.3多步预测策略1.3.1多输出模型1.3.2直接策略1.3.3递归策略1.3.4DirRec 策略2、流感趋势示例2.1多输出模型2.2直接策略1、简介 在第二课和第三课中,我们将预测视为一个简单的回归问…

jquery写表格 手动合并单元格

<!DOCTYPE html> <html><head><style>.special-row th:first-child,.special-row th:nth-child(2) {background-color: yellow;text-align: center;}</style> </head><body><div id"tableWrapper"> <!-- 添加包裹…

TreeSet 集合

TreeSet 集合 1. 概述2. 方法3. 遍历方式4. 两种排序方式4.1 默认排序规则/自然排序4.1.1 概述4.1.2 compareTo()方法4.1.3 代码示例14.1.4 代码示例2 4.2 比较器排序4.2.1 概述4.2.2 compare()方法4.2.3 代码示例14.2.4 代码示例2 4.3 排序方式的对比 5. 注意事项 文章中的部分…

<.Net>使用visual Studio 2022在VB.net中新添自定义画图函数(优化版)

前言 这是基于我之前的一篇博文&#xff1a; 使用visual Studio 2019在VB.net中新添自定义画图函数 在此基础上&#xff0c;我优化了一下&#xff0c;改进了UI&#xff0c;添加了示例功能&#xff0c;即以画圆函数为基础&#xff0c;添加了走马灯功能。 先看一下最终效果&#…

JavaEE作业-实验一

目录 1 实验内容 2 思路 3 核心代码 &#xff08;1&#xff09;前端核心代码&#xff1a; &#xff08;2&#xff09;后端核心代码&#xff1a; 4 实验结果 1 实验内容 用Servlet JSP JavaBean实现登录功能 2 思路 ①建好web项目,创建数据库 ②建立两个简单的前端页…

Day 3. Linux高级编程之函数接口和流的定位

gets和fgets区别&#xff1a; 1&#xff09;gets没有给定最多读取字符的个数&#xff0c;有越界风险\n\n fgets需要给定最多读取的字符个数&#xff0c;没有越界的风险\n\n 2&#xff09;gets会去掉从终端接收的/n&#xff0c;换成/0\n\n fgets则会保留并在末尾加上/0\…

最小生成树超详细介绍

目录 一.最小生成树的介绍 1.最小生成树的简介 2.最小生成树的应用 3.最小生成树的得出方法 二.Kruskal算法 1.基本思想&#xff1a; 2.步骤&#xff1a; 3.实现细节&#xff1a; 4.样例分析&#xff1a; 5.Kruskal算法代码实现&#xff1a; 三.Prim算法 1.基本思想…

【华为 ICT HCIA eNSP 习题汇总】——题目集12

1、企业网络内部常常采用私有 IP 地址进行通信&#xff0c;以下哪个地址属于私有 IP 地址&#xff1f; A、0.1.1.1 B、127.5.4.3 C、128.0.0.5 D、172.24.35.36 考点&#xff1a;网络层 解析&#xff1a;&#xff08;D&#xff09; A类 IP 地址中&#xff0c;10.0.0.0 ~ 10.255…

SpringSecurity(18)——OAuth2授权码管理

AuthorizationCodeServices public interface AuthorizationCodeServices {//为指定的身份验证创建授权代码。String createAuthorizationCode(OAuth2Authentication authentication);//使用授权码。OAuth2Authentication consumeAuthorizationCode(String code)throws Invali…

ACM训练题:Raising Modulo Numbers

主要意思就是上面的式子&#xff0c;求幂的和的模&#xff0c;求幂自然是快速幂&#xff0c;这里都带上模&#xff0c;求和的模也可以分开取模。 AC代码&#xff1a; #include <iostream> using namespace std; long long Z,M,H,a,b; long long quick_mi(long long x,l…

【数据结构与算法】(11)基础数据结构 之 二叉树 二叉树的存储与遍历及相关示例 详细代码讲解

目录 2.10 二叉树1) 存储2) 遍历广度优先深度优先递归实现非递归实现 习题E01. 前序遍历二叉树-Leetcode 144E02. 中序遍历二叉树-Leetcode 94E03. 后序遍历二叉树-Leetcode 145E04. 对称二叉树-Leetcode 101E05. 二叉树最大深度-Leetcode 104E06. 二叉树最小深度-Leetcode 111…

R语言:箱线图绘制(添加平均值趋势线)

箱线图绘制 1. 写在前面2.箱线图绘制2.1 相关R包导入2.2 数据导入及格式转换2.3 ggplot绘图 1. 写在前面 今天有时间把之前使用过的一些代码和大家分享&#xff0c;其中箱线图绘制我认为是非常有用的一个部分。之前我是比较喜欢使用origin进行绘图&#xff0c;但是绘制的图不太…

C++杂选

#include <iostream> #include <regex>using namespace std;int main() { //它声明了一个 string 类型的变量 input&#xff0c;用于存储输入的字符串。然后使用 getline() 函数从标准输入中读取一行输入&#xff0c;并将其存储在 input 变量中。string input;getl…

PAT-Apat甲级题1008(python和c++实现)

PTA | 1008 Elevator 1008 Elevator 作者 CHEN, Yue 单位 浙江大学 The highest building in our city has only one elevator. A request list is made up with N positive numbers. The numbers denote at which floors the elevator will stop, in specified order. It …

c#读取csv文件中的某一列的数据

chat8 (chat779.com) 上面试GPT-3.5,很好的浏览网站&#xff0c;输入问题&#xff0c;可得到答案。 问题1&#xff1a;c#如何在csv中读取某一列数据 解答方案&#xff1a;在 C#中&#xff0c;你可以使用File.ReadAllLines来读取CSV中的所有行&#xff0c;然后逐行解析每一行…

机器学习---概率图模型(隐马尔可夫模型、马尔可夫随机场、条件随机场)

1. 隐马尔可夫模型 机器学习最重要的任务是根据已观察到的证据&#xff08;例如训练样本&#xff09;对感兴趣的未知变量&#xff08;例如类别标 记&#xff09;进行估计和推测。概率模型&#xff08;probabilistic model&#xff09;提供了一种描述框架&#xff0c;将描述任…

网络选择流程分析(首选网络类型切换流程)

首先是界面,我在此平台的界面如下: 对应的入口源码位置在Settings的UniEnabledNetworkModePreferenceController中,当然其他平台可能在PreferredNetworkModePreferenceController中,流程上都是大同小异 然后点击切换按钮会调用到UniEnabledNetworkModePreferenceControlle…