数据库编程 SQLITE3 Linux环境

永久存储程序数据有两种方式:

  1. 用文件存储
  2. 用数据库存储

对于多条记录的存储而言,采用文件时,插入、删除、查找的效率都会很差,为了提高这些操作的效率,有计算机科学家设计出了数据库存储方式


一、数据库

用来管理数据库的软件被称数据库管理系统

一个数据库管理系统管理着多个数据库

一个数据库中可以包含很多张表

一张表中拥有很多记录(行)

一条记录拥有很多字段(列)

每条记录的每个字段存放不同类型的数据

因此,数据库本质上是表的集合

数据库按数据的组织形式分为:

  1. 关系型数据库 ----- 本章内容
  2. 非关系型数据库

数据库管理系统软件按是否支持远程分为:

  1. 网络版 ---- MySql Oracle SQlServer
  2. 单机版 ---- sqlite

网络版的数据管理系统的整体框架:

数据库管理系统发展初期,各家开发此类软件的公司采用的通信协议是不同的,这给应用客户端开发造成很大的麻烦

因此,经过一段时间的发展,全球几家著名的数据库管理系统开发公司制定了统一的通信协议,这个统一的通信协议被称为SQL(Structure Query Language)

随着关系型数据库的不断发展,SQL成为所有数据库管理系统的统一协议

每个数据库管理系统都会提供一个命令行界面的简易客户端,应用程序员可以使用这个简易客户端学习、练习SQL语句以及辅助开发

每一条SQL语句就是一个操作请求


二、SQLite

一个单机版的数据库管理系统

所有操作请求也遵循SQL标准

开源、精悍

1.安装SQLite3
命令行下输入:sudo apt-get install sqlite3

2.安装SQLite3编译需要的工具包
命令行下输入: sudo apt-get install libsqlite3-dev

如出现问题尝试:
sudo dpkg --purge --force-depends libsqlite3-0
sudo apt-get install libsqlite3-0
sudo apt-get install -f
sudo apt-get install libsqlite3-dev
sudo apt-get install sqlite3

支持三种字段数据类型:

INTEGER或INT 值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。
REAL 值是一个浮点值,存储为 8 字节的 IEEE 浮点数字。
TEXT 值是一个文本字符串,单引号或双引号括起的字符串

使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储


三、sqlite3简易客户端的使用

1. 运行

Linux>sqlite3 ------ 只是进入sqlite3的命令行界面,不创建打开任何数据库

Linux>sqlite3 路径/数据库文件名 ----- 先创建打开指定的数据库,然后进入sqlite3的命令行界面

sqlite3管理的一个数据库,在Linux系统下用一个文件表示它,习惯上将这个文件命名为xxx.db

2. 两种命令

  1. .开头的命令:简易客户端的内部命令
  2. 以;结尾的命令:;前的内容为SQL语句,;是简易客户端要求的结尾符

3. 常用内部命令

创建打开一个指定的数据库
sqlite> .open  路径/xxx.db 
sqlite> .help

查看正在使用的数据库
sqlite> .databases

SQL语句操作结果按列对齐  ----- 重要
sqlite> .mode column 

显示某表时是否显示表头 ----- 重要
sqlite> .headers on/off

显示数据中的表 ------ 重要
sqlite> .tables

退出sqlite命令行 ---- 重要
sqlite> .quit


四、常用SQL语句

SQL语句组成:关键字 + 运算符 + 字段名或表名 + 常量

SQL语句的关键字可以全大写、也全小写、甚至可以大小混合,一般建议采用全大写

字段名或表名的大小是区分的,aaa、Aaa、AAA认为是不同的字段名或表名,自建表建议字段名或表名全小写

1. 建表
CREATE TABLE [IF NOT EXISTS] table_name(
   column_name1 datatype[(size)]  [PRIMARY KEY] [AUTOINCREMENT] [NOT NULL],
   column_name2 datatype,
   column_name3 datatype,
   .....
   column_nameN datatype,
);
[]:表示可选,选用时不带[]
[AUTOINCREMENT]:只能用于INTEGER 表示如果插入新记录时没有指定该字段的值,则其值为前一条记录同字段值+1
[PRIMARY KEY]:主键,唯一标识表中的记录  主键:表中每条记录的该字段值不会重复,也即该字段值可以唯一标识一条记录
[IF NOT EXISTS]:如果表不存在则建表,如果存在则什么都不做
[NOT NULL]:表示字段内容不能为空


示例:
sqlite>  CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
   ...>  name TEXT,sex TEXT(1),score REAL); 


2. 删表
DROP TABLE 表名;

示例:
sqlite> CREATE TABLE ttt(xxx TEXT,yyy TEXT);
sqlite> DROP TABLE ttt;

3. 插入新记录
通用:
INSERT INTO table_name(column1, column2,...columnN)  VALUES(value1, value2,...valueN);

不缺字段时:
INSERT INTO table_name  VALUES(value1,value2,...valueN); 


4. 查询记录
SELECT column1, column2, columnN FROM table_name [WHERE condition];
SELECT * FROM table_name [WHERE condition];
*表示查询结果显示所有字段
无WHERE子句则查询所有记录

5. where子句
所谓子句就是不能成为独立的SQL语句,只能成为一条SQL语句的一部分

WHERE子句用来为一些操作指定条件
WHERE condition

condition可以是单个条件或由AND、OR连接的多个条件

比较运算符支持:
=   !=   >   <    >=    <=  用法:字段名 运算符 值

IN()用法:字段名 IN(值1,值2,...,值n)   表示字段值为值1或值2或....

NOT IN()用法:字段名 NOT IN(值1,值2,...,值n)  表示字段值不为值1也不为值2也不为....

LIKE用法:字段名 LIKE 模式字串    模式字串中可以用%号表示任意多个字符,用_表示单个字符,默认不区分大小写

GLOB用法:字段名 GLOB 模式字串    模式字串中可以用*号表示任意多个字符,用?表示单个字符,区分大小写

IS NOT NULL用法:字段名 IS NOT NULL  判断字段值是否为空

IS NULL用法:字段名 IS NULL  判断字段值是否为空

BETWEEN AND用法:字段名 BETWEEN 值1 AND 值2   字段值>=值1 且 字段值<=值2

NOT反条件用法:字段名 NOT  其它条件

6. 修改记录
UPDATE table_name SET column1 = value1, column2 = value2...., columnN = valueN WHERE [condition];
无WHERE子句则对所有记录进行修改


7. 删除记录
DELETE FROM table_name WHERE [condition];
无WHERE子句则删除所有记录


8. Sort子句
ORDER BY 字段名 ASC 或 DESC
ASC升序
DESC降序


9. SQL语句中的函数
datetime('now','localtime') ---- 产生当前日期时间的字符串

使用示例:
INSERT INTO Table_name VALUES(datetime('now','localtime'));

count(*) 对查询结果求记录数
使用示例:
SELECT count(*) FROM student;

五、sqlite3函数库

SQL按执行完毕后是否有记录结果分为两种:

  1. 一种SQL语句的执行只论是否成功。例如:建表、删表、插入记录、修改记录、删除记录
  1. 另一种SQL语句执行完毕产生多条记录结果。例如:查询

sqlite3_open参照图:

sqlite3_exec及其回调函数的参考图:

sqlite3_get_table函数参考图1:

//头文件包含
#include <sqlite3.h>

/*链接选项
	-lsqlite3
*/

//1、打开/创建一个数据库
int sqlite3_open(const char *filename,  sqlite3 **ppDb );
/*
功能:打开指定的数据库,如果数据库并存在则创建并打开指定的数据库,并创建一个后续操作该数据库的引擎
参数:
	filename:带路径的数据库文件名
	ppdb:指向sqlite句柄的指针,调用前定义一个sqlite3 *指针变量,取该指针变量的地址
返回:成功  SQLITE_OK (值为0),否则返回其他值。
*/

//2、如果打开数据库失败,open函数只是返回错误码,如果想要错误原因的字符串描述则调用该函数
const  char  *sqlite3_errmsg(sqlite3 *db);
/*  
	返回值:返回错误信息
*/

//3、回调函数执行sql语句
//更加适用于sql语句执行没有记录结果的情况(此时第3、4参数填NULL)或对需要依次对每条操作结果记录进行处理的情况
int sqlite3_exec(sqlite3* pDB, const char *sql, sqlite_callback callback, void*para, char** errMsg);
 /*
功能:执行SQL语句,查询的结果返回给回调函数callback,多个结果的操作,每个结果都会调用一次callback
参数:
	pDB:数据库引擎的句柄。
	sql:待执行的SQL 语句字符串,以’\0’结尾,不以';'结尾。
	callback:回调函数,用来处理查询结果,如果不需要回调(比如做insert 或者delete 操作时),可以置NULL。
	para:要传入回调函数的指针参数,没有可以置为NULL。
	errMsg:一级指向空间存放着一个char *类型的元素,该元素指向空间(二级指向空间)存放着一个字符串,该字符串内容描述出错原因,
            因此:1. 调用前定义一个char *类型的指针变量,传该指针变量的地址给该形参。
	             2. 由于其二级指向空间是动态分配的,因此使用完后需要调用sqlite3_free函数进行释放;
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/

//4、回调函数
typedef int (*sqlite_callback)(void* para,  int columnCount,  char** columnValue,char** columnName);
/*
功能:由用户处理查询的结果,每找到一条记录自动执行一次回调函数
参数:
	para:从sqlite3_exec()传入的参数指针;
	columnCount:查询到的这一条记录有多少个字段(即这条记录有多少列);
	columnValue:查询出来的数据都保存在这里,它实际上是个1 维数组(不要以为是2 维数组),每一个元素都是一个char * 值,是一个字段内容(用字符串来表示,以‘\0’结尾)
	columnName:与columnValue 是对应的,表示这个字段的字段名称。
返回值:执行成功返回SQLITE_OK,否则返回其他值
*/

//5、关闭
int sqlite3_close(sqlite3 *ppDb);
/*
功能:关闭sqlite数据库。
参数:ppdb:数据库句柄。
返回值:成功返回0,失败返回错误码
*/

//6、释放   
void sqlite3_free(void * errMsg );
/*
功能:释放存放错误信息的内存空间
参数:errMsg: 返回错误信息
*/

//7、非回调来执行sql语句
//更加适用于SQL语句执行后有一条或多条记录结果,且程序期望对所有记录结果的整体进行处理的情况
int sqlite3_get_table(
      sqlite3 *db,          /* An open database */
      const char *zSql,     /* SQL to be evaluated */
      char ***pazResult,    /* Results of the query */
      int *pnRow,           /* Number of result rows written here */
      int *pnColumn,        /* Number of result columns written here */
      char **pzErrmsg       /* Error msg written here */
    );
 /*
功能:非回调来执行sql语句
参数:
	db:数据库句柄
	zSql:要执行的SQL语句
	pazResult:查询结果,一维数组,定义一个char **的二级指针变量,调用函数时传该二级指针变量的地址,不使用应立即调用
	           sqlite3_free_table(result)进行释放
	pnRow:查询出多少条记录(查出多少行) 不包括字段名所在行
	pnColumn:多少个字段(查出多少列)
	pzErrmsg:错误信息
返回值:执行成功返回SQLITE_OK,否则返回其他值
注:pazResult的字段值是连续的,是一维数组不是二维数组,从第0索引到第 pnColumn- 1索引都是字段名称,
                                                 从第 pnColumn索引开始,后面都是字段值。
*/

//8、释放pazResult查询结果   
void sqlite3_free_table(char **pazResult);
/*
	参数:pazResult:指向空间存放着查询结果,指向空间为元素类型是char *的一维数组
*/

#include <stdio.h>
#include <sqlite3.h>

int handle_a_record(void *para,int cols,char **ppval,char **ppname);

int main(){
    sqlite3 *pdb = NULL;
    int ret = 0;
    ret = sqlite3_open("./test.db",&pdb); // open
    if(ret != SQLITE_OK){
        printf("sqlite3 not open,because %s\n",sqlite3_errmsg(pdb));
        sqlite3_close(pdb);
        pdb = NULL;
        return 1;
    }

    {
        char sql[80] = "";
        char *perr = NULL;
        sprintf(sql,"SELECT * FROM stu"); // write instruction
        ret = sqlite3_exec(pdb,sql,handle_a_record,NULL,&perr); // exec()
        if(ret != SQLITE_OK){ // error
            printf("exec %s failed,because %s\n",sql,perr);

            sqlite3_free(perr); // sqlite3_free()
            perr = NULL;
        }
    }

    {
        char sql[80] = "";
        char *perr = NULL;
        char **ppret = NULL;
        int rows = 0;int cols = 0;int i = 0;int j = 0;

        sprintf(sql,"SELECT * FROM stu"); // write instruction
        ret = sqlite3_get_table(pdb,sql,&ppret,&rows,&cols,&perr); // exec()
        if(ret != SQLITE_OK){ // error
            printf("exec %s failed,because %s\n",sql,perr);

            sqlite3_free(perr); // sqlite3_free()
           perr = NULL;
        }
        else{
            for(j = 0;j < cols;j++){
                printf("%-20s ",*(ppret + j));
            }
            printf("\n");
        }
        for(i = 1;i <= rows;i++){
            for(j = 0;j < cols;j++)     printf("%-20s ",*(ppret + i * cols + j));
            printf("\n");
        }
        sqlite3_free_table(ppret);
        ppret = NULL;
}
        sqlite3_close(pdb); // sqlite3_close()
        pdb = NULL;

        return 0;

}
 
int handle_a_record(void *para,int cols,char **ppval,char **ppname){
    int i = 0;
    for(i = 0;i < cols;i++){
        printf("%s | ",*(ppval + i));
    }
    printf("\n");

    return SQLITE_OK;
}

输出:


六、sqlite3函数库的并发模式

  1. 单线程模式 ----- 无锁模式
  2. 串行模式 ------ 默认模式,非阻塞互斥锁实现
  3. 读者写者模式 ------ 读写锁实现

配置sqlite3函数库的并发模式可以通过:1. 重新编译sqlite3函数库的源码 2.调用相关的接口函数进行配置

实际项目中大部分情况采用其默认模式

串行模式时,需要对sqlite3_exec、sqlite3_get_table函数进行如下形式的二次封装:

int my_sqlite3_exec(sqlite3* pdb, const char *sql, sqlite_callback callback, void*para, char** errmsg)
{
	int ret = 0;  
	do 
	{
		ret = sqlite3_exec( pdb , sql, callback , para , errmsg );  
    	if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED)
    	{
			usleep(30 * 1000);
        	continue;
    	}
    	else
    	{
        	break;
    	}
	} while(1);  
    return ret;
}

int my_sqlite3_get_table(
      sqlite3 *db,          /* An open database */
      const char *zSql,     /* SQL to be evaluated */
      char ***pazResult,    /* Results of the query */
      int *pnRow,           /* Number of result rows written here */
      int *pnColumn,        /* Number of result columns written here */
      char **pzErrmsg       /* Error msg written here */
    )
{
	int ret = 0;
	do 
	{
		ret = sqlite3_get_table(db,zSql,pazResult,pnRow,pnColumn,pzErrmsg);  
    	if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED)
    	{
			usleep(30 * 1000);
        	continue;
    	}
    	else
    	{
        	break;
    	}
	} while(1);  
    return ret;
}

七、二次封装

实际项目代码中,直接调用sqlite3函数库中的函数实现相关功能,会很不方便,往往会将项目中可能用到的所有数据库操作代码单独作为一个模块,该模块又按表分为几个子模块(一般命名为xxxhelper),由这个模块及其子模块向其它项目代码提供需要的数据库操作接口。

public子模块:不隶属于任何一个helper子模块的操作函数,归于本子模块

一般项目中建议采用如下方案:

/*一、public子模块 -------- 项目名_db_public.c*/
/*1. 函数功能:创建打开数据库,然后带IF NOT EXISTS关键字去建表*/
sqlite3 *create_db_engine(const char *pdbfile)
{
	1. 调用sqlite3_open

	2. 建表1
	3. 建表2
	。。。。
	n+1. 建表n

	成功返回引擎地址,失败返回NULL
}

/*2. 对sqllite3_exec的二次封装 ------ 见上一节*/

/*3. 对sqllite3_get_table的二次封装 ------ 见上一节*/

/*4. destroy_db_engine*/
void destroy_db_engine(sqlite3 *pdb)
{
	sqlite3_close(pdb);
}


/*二、对表1的各种操作函数封装  表1名helper.c*/
int insert_new_record_into_表名(sqlite3 *pdb,.........)
{
	组织sql语句
	调用my_sqlite3_exec 或 my_sqlite3_get_table函数执行sql语句
	。。。。。。
}

......

???? xxxxx(sqlite3 *pdb,.......)
{
	通过多次执行sql语句组合完成本函数功能
}


/*三、对表2的各种操作函数封装  表2名helper.c*/

。。。。。。。。。。。。。。。

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

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

相关文章

【Android】多渠道打包配置

目录 简介打包配置签名配置渠道配置配置打包出来的App名称正式包与测试包配置 打包方式开发工具打包命令行打包 优缺点 简介 多渠道打包 是指在打包一个 Android 应用时&#xff0c;一次编译生成多个 APK 文件&#xff0c;每个 APK 文件针对一个特定的渠道。不同的渠道可能代表…

Prompt提示词设计:如何让你的AI对话更智能?

Prompt设计&#xff1a;如何让你的AI对话更智能&#xff1f; 在人工智能的世界里&#xff0c;Prompt&#xff08;提示词&#xff09;就像是一把钥匙&#xff0c;能够解锁AI的潜力&#xff0c;让它更好地理解和响应你的需求。今天&#xff0c;我们就来聊聊如何通过精心设计的Pr…

厂房区域人员进出人数统计-实施方案

1.1 现状分析 传统的人流量统计方法往往依赖于人工计数或简单的视频监控系统&#xff0c;这些方法不仅效率低下&#xff0c;而且容易出错&#xff0c;无法满足现代仓库管理的需求。因此&#xff0c;我厂区决定引入先进的智能监控系统&#xff0c;通过集成高清摄像头、GPU服务器…

【Unity】仓库逻辑:拾取物体进仓库和扔掉物品

需求说明 目标&#xff1a;实现玩家移动过程中&#xff0c;拾取物体&#xff0c;物体被放入仓库&#xff1b;点击仓库中物体&#xff0c;重新扔回3D场景中逻辑。 逻辑分析&#xff1a; 需要玩家可以移动&#xff1b;需要检测玩家和物体的碰撞&#xff0c;并摧毁物体&#xf…

css知识点梳理2

1. 选择器拓展 在 CSS 中&#xff0c;可以根据选择器的类型把选择器分为基础选择器和复合选择器&#xff0c;复合选择器是建立在基础选择器之上&#xff0c;对基本选择器进行组合形成的。 ​ 复合选择器是由两个或多个基础选择器&#xff0c;通过不同的方式组合而成的&#xf…

【Flask】一、安装与第一个测试程序

目录 Flask简介 安装Flask 安装pip&#xff08;Python包管理器&#xff09; 使用pip安装Flask 验证安装 创建Flask程序 创建应用 运行 访问测试 Flask简介 Flask是一个用Python编写的轻量级Web应用框架。它被设计为易于使用和扩展&#xff0c;使其成为构建简单网站或复…

[项目][boost搜索引擎#4] cpp-httplib使用 | log.hpp | 前端 | 测试及总结

目录 编写http_server模块 1. 引入cpp-httplib到项目中 2. cpp-httplib的使用介绍 3. 正式编写http_server 九、添加日志到项目中 十、编写前端模块 十一. 详解传 gitee 十二、项目总结 项目的扩展 写在前面 项目 gitee 已经上传啦 &#xff08;还是决定将学校和个人…

网络编程基础-Reactor线程模型-原理剖析

1、Reactor基本概念 Reactor线程模型其实是一种设计模式&#xff0c;其核心思想就是将输入多路复用和事件派发相结合&#xff0c;从而减少系统中活跃线程的数量。 像我们之前讲到的文章网络编程基础-IO模型深入理解_网络io-CSDN博客提到了其中网络IO模型&#xff08;BIO、NIO…

asp.net core 入口 验证token,但有的接口要跳过验证

asp.net core 入口 验证token,但有的接口要跳过验证 在ASP.NET Core中&#xff0c;你可以使用中间件来验证token&#xff0c;并为特定的接口创建一个属性来标记是否跳过验证。以下是一个简化的例子&#xff1a; 创建一个自定义属性来标记是否跳过验证&#xff1a; public clas…

基于PHP的http字段查询与注册(V1)(持续迭代)

目录 版本说明&#xff1a; 实现环境&#xff08;WAMP&#xff09;&#xff1a; 数据库链接 查询页面 php处理逻辑 字段添加 版本说明&#xff1a; 该查询功能以查询http首部字段为目的实现的字段属性、字段内容的查询&#xff0c;以及对新字段信息的数据注册。 v1实现…

python 制作 发货单 (生成 html, pdf)

起因&#xff0c; 目的: 某个小店&#xff0c;想做个发货单。 过程: 先写一个 html 模板。准备数据&#xff0c; 一般是从数据库读取&#xff0c;也可以是 json 格式&#xff0c;或是 python 字典。总之&#xff0c;是数据内容。使用 jinja2 来渲染模板。最终的结果可以是 h…

多线程进阶——线程池的实现

什么是池化技术 池化技术是一种资源管理策略&#xff0c;它通过重复利用已存在的资源来减少资源的消耗&#xff0c;从而提高系统的性能和效率。在计算机编程中&#xff0c;池化技术通常用于管理线程、连接、数据库连接等资源。 我们会将可能使用的资源预先创建好&#xff0c;…

WPF+MVVM案例实战(七)- 系统初始化界面字体描边效果实现

文章目录 1、案例效果展示2、项目准备3、功能实现1、资源获取2、界面代码3、后台代码 4 源代码获取 1、案例效果展示 2、项目准备 打开项目 Wpf_Examples&#xff0c;新建系统初始化界面 WelcomeWindow.xmal,如下所示&#xff1a; 3、功能实现 1、资源获取 案例中使用的CSD…

Java | Leetcode Java题解之第516题最长回文子序列

题目&#xff1a; 题解&#xff1a; class Solution {public int longestPalindromeSubseq(String s) {int n s.length();int[][] dp new int[n][n];for (int i n - 1; i > 0; i--) {dp[i][i] 1;char c1 s.charAt(i);for (int j i 1; j < n; j) {char c2 s.char…

【Java并发编程】信号量Semaphore详解

一、简介 Semaphore&#xff08;信号量&#xff09;&#xff1a;是用来控制同时访问特定资源的线程数量&#xff0c;它通过协调各个线程&#xff0c;以保证合理的使用公共资源。 Semaphore 一般用于流量的控制&#xff0c;特别是公共资源有限的应用场景。例如数据库的连接&am…

Python | Leetcode Python题解之第516题最长回文子序列

题目&#xff1a; 题解&#xff1a; class Solution:def longestPalindromeSubseq(self, s: str) -> int:n len(s)dp [[0] * n for _ in range(n)]for i in range(n - 1, -1, -1):dp[i][i] 1for j in range(i 1, n):if s[i] s[j]:dp[i][j] dp[i 1][j - 1] 2else:dp…

从病理AI的基础模型发展历程,看未来的医学AI发展趋势|个人观点·24-10-23

小罗碎碎念 在临床相关的人工智能&#xff08;AI&#xff09;模型发展方面&#xff0c;传统上需要大量标注数据集&#xff0c;这使得AI的进步主要围绕大型中心和私营企业展开。所以&#xff0c;在这期推文中&#xff0c;我会介绍一些已经商用的模型&#xff0c;并且为计划进军…

逻辑推理学习笔记

目的 立场辩护整理思绪 基本框架 论题 &#xff08;变化&#xff09; 我要证明&#xff08;讨论对象 变化&#xff09; 论据 &#xff08;变化&#xff09; 拿什么证明&#xff1f;也就是证据呈现。 论证 &#xff08;不变&#xff09; 要如何证明&#xff1f;逻辑框架…

通过conda install -c nvidia cuda=“11.3.0“ 安装低版本的cuda,但是却安装了高版本的12.4.0

问题 直接通过 conda install -c nvidia cuda"11.3.0"安装得到的却是高版本的 不清楚原理 解决方法 不过我们可以分个安装 runtime toolkit 和 nvcc 安装指定版本的 cudatoolkit 和 nvcc conda install -c nvidia cuda-cudart"11.3.58" conda instal…

【Linux系统编程】——Linux入门指南:从零开始掌握操作系统的核心(指令篇)

文章目录 查看 Linux 主机 ip以及登录主机Linux基础文件操作指令man&#xff1a;查看命令的手册页&#xff0c;了解命令的详细用法。pwd&#xff1a;显示当前目录路径。cd&#xff1a;切换目录。ls&#xff1a;列出当前目录下的文件和文件夹。mkdir&#xff1a;创建新目录。 文…