获得徽章 0
day23

程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放
通过文件可以将数据持久化

C++中对文件操作需要包含头文件 < fstream >



C++中文件类型分为两种:
文本文件 - 文件以文本的ASCII码形式存储在计算机中
二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们


操作文件的三大类(这些类都属于标准模板库):
ofstream(output):写入文件操作
ifstream(input): 读取数据操作
fstream : 读写操作。一般使用这个类进行文本操作
展开
评论
day22

平年的2月份有28天;闰年的2月份有29天;其他月份天数一样
平年一共365天,闰年一共366天
平年与闰年的计算方法是:“四年一闰,百年不闰,四百年又闰”
公元年数可被4整除并且不能被100整除为闰年,但是整百(个位和十位均为0)的年数必须是可以被400整除的才是闰年。其他都是平年


判断是否为闰年的代码
// 判断是否为闰年
bool isLeap(int year){
if((year%4==0&&year%100!=0)||(year%400==0)){
return true;
}
else return false;
}
展开
评论
day21

. 破坏不剥夺条件
  当一个已保持了某些不可剥夺资源的进程请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺,或从而破坏了不剥夺条件。

  该策略实现起来比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如CPU的寄存器及内存资源,一般不能用于打印机之类的资源。

破坏不剥夺条件:
  方案一:当某个进程请求新的资源得不到满足时,它必须立即释放保持的所有资源,待以后需要时再重新申请。也就是说,即使某些资源尚未使用完,也需要主动释放,从而破坏了不可剥夺条件。

  方案二:当某个进程需要的资源被其他进程所占有的时候,可以由操作系统协助,将想要的资源强行剥夺。这种方式一般需要考虑各进程的优先级(比如:剥夺调度方式,就是将处理机资源强行剥夺给优先级更高的进程使用)
展开
评论
day20

1) 系统资源的竞争
  通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局,如磁带机、打印机等。只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。

(2) 进程推进顺序非法
  进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程P1,P2,分别保持了资源R1,R2,而进程P1申请资源R2、进程P,2申请资源R1,时,两者都会因为所需资源被占用而阻塞,于是导致死锁。

  信号量使用不当也会造成死锁。进程间彼此相互等待对方发来的消息,也会使得这些进程间无法继续向前推进。例如,进程A等待进程B发的消息,进程B又在等待进程A发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源导致死锁。

(3) 死锁产生的必要条件
产生死锁必须同时满足以下4个条件,只要其中任意一个条件不成立,死锁就不会发生。
展开
评论
day19
由于磁盘有移动部件且容错能力弱,因此容易导致一个或多个扇区损坏。部分磁盘甚至在出厂时就有坏块。根据所用的磁盘和控制器,对这些块有多种处理方式。

  对于简单磁盘,如采用IDE控制器的磁盘,坏块可手动处理,如MS-DOS的Format命令执行逻辑格式化时会扫描磁盘以检查坏块。坏块在FAT表上会标明,因此程序不会使用它们。

  对于复杂的磁盘,控制器维护磁盘内的坏块列表。这个列表在出厂低级格式化时就已初始化并在磁盘的使用过程中不断更新。低级格式化将一些块保留作为备用,操作系统看不到这些块。控制器可以采用备用块来逻辑地替代坏块,这种方案称为扇区备用。

  对坏块的处理实质上就是用某种机制使系统不去使用坏块。

坏了、无法正常使用的扇区就是“坏块”。这属于硬件故障,操作系统是无法修复的。应该将坏块标记出来,以免错误地使用到它

对于简单的磁盘,可以在逻辑格式化时(建立文件系统时)对整个磁盘进行坏块检查,标明哪些扇区是坏扇区,比如:在 FAT 表上标明。(在这种方式中,坏块对操作系统不透明,操纵系统可见)

对于复杂的磁盘,磁盘控制器(磁盘设备内部的一个硬件部件)会维护一个坏块链表。

在磁盘出厂前进行低级格式化(物理格式化)时就将坏块链进行初始化。

会保留一些“备用扇区”,用于替换坏块(替换这个操作由硬件完成)。这种方案称为扇区备用。且这种处理方式中,坏块对操作系统透明,操作系统不可见。
展开
评论
day18

产生饥饿的主要原因是:在一个动态系统中,对于每类系统资源,操作系统需要确定一个分配策略,当多个进程同时申请某类资源时,由分配策略确定资源分配给进程的次序。有时资源分配策略可能是不公平的,即不能保证等待时间上界的存在。在这种情况下,即使系统没有发生死锁,某些进程也可能会长时间等待。当等待时间给进程推进和响应带来明显影响时,称发生了进程“饥饿”,当“饥饿”到一定程度的进程所赋予的任务即使完成也不再具有实际意义时,称该进程被“饿死”。
展开
评论
day17

动态扩展:

并不是在原空间之后续接新空间,而是找更大的内存空间(STL中有专门的算法去找这个内存空间),然后将原数据拷贝新空间,释放原空间




vector容器前端封闭,一般都是在尾部插入数据:push_back和删除数据:pop_back
v.rend():这个迭代器指向第一个元素的前以为
v.begin():常用的vector迭代器,指向第一个第一个元素
v.end():常用的vector迭代器,指向最后一个元素的后一位
v.rbegint():这个迭代器指向最后一个元素
vector容器的迭代器支持随机访问,可以一下跳好几个元素
展开
评论
day16

  在多道程序系统中,由于多个进程的并发执行,改善了系统资源的利用率并提高了系统的处理能力。然而,多个进程的并发执行也带来了新的问题—死锁。所谓死锁,是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。

  下面通过一些实例来说明死锁现象。

  先看生活中的一个实例。在一条河上有一座桥,桥面很窄,只能容纳一辆汽车通行。若有两辆汽车分别从桥的左右两端驶上该桥,则会出现下述冲突情况:此时,左边的汽车占有桥面左边的一段,要想过桥还需等待右边的汽车让出桥面右边的一段;右边的汽车占有桥面右边的一段,要想过桥还需等待左边的汽车让出桥面左边的一段。此时,若左右两边的汽车都只能向前行驶,则两辆汽车都无法过桥。

  在计算机系统中也存在类似的情况。例如,某计算机系统中只有一台打印机和一台输入设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用的输入设备。这样,两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。
展开
评论
day15

一次性:作业必须一次性全部装入内存后才能开始运行。这会造成两个问题:①作业很大时,不能全部装入内存,导致大作业无法运行;②当大量作业要求运行时,由于内存无法容纳所有作业,因此只有少量作业能运行,导致多道程序并发度下降。

驻留性:一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。事实上,在一个时间段内,只需要访问作业的一小部分数据即可正常运行,这就导致了内存中会驻留大量的、暂时用不到的数据,浪费了宝贵的内存资源。
展开
评论
day14

程序接口由一组系统调用 (也称广义指令) 组成。用户通过在程序中使用这些系统调用来请
求操作系统为其提供服务,如使用各种外部设备、 申请分配和回收内存及其他各种要求。
当前最为流行的是图形用户界面 (GUI),即图形接口。GUI最终是通过调用程序接口实现的;
用户通过鼠标和键盘在图形界面上单击或使用快捷键,就能很方便地使用操作系统。严格来说图形接口不是操作系统的一 部分,但图形接口所调用的系统调用命令是操作系统的一部分。
展开
评论
day13

进程是程序的一次执行过程。
进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
  引入进程实体的概念后,我们可以把传统操作系统中的进程定义为:“进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
展开
评论
day12

在多道程序环境下,允许多个程序并发执行,此时它们将失去封闭性,并具有间断性及不可再现性的特征。为此引入了进程(Process)的概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性(最基本的两个特性)。
  为了使参与并发执行的每个程序(含数据)都能独立地运行,必须为之配置一个专门的数据结构,称为进程控制块(Process Control Block,PCB)。系统利用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。相应地,由程序段、相关数据段和PCB三部分构成了进程实体(又称进程映像)。所谓创建进程,实质上是创建进程实体中的PCB;而撤销进程,实质上是撤销进程的PCB。值得注意的是,进程映像是静态的,进程则是动态的(或者说:进程实体是进程在动态执行过程中某一时刻的快照,进程实体反应了进程在某一时刻的状态)。
展开
评论
day11

如果x为一个切片,sizeof返回的大小是切片的描述符,而不是切片所指向的内存的大小。

那么这里如果换成一个数组呢?而不是一个切片

arr := [...]int{1,2,3,4,5}
fmt.Println(unsafe.Sizeof(arr)) //40
arr2 := [...]int{1,2,3,4,5,6}
fmt.Println(unsafe.Sizeof(arr)) //48
1
2
3
4
可以看到sizeof(arr)的值是在随着arr的元素的个数的增加而增加

这是为啥?

sizeof总是在编译期就进行求值,而不是在运行时,这意味着,sizeof的返回值可以赋值给常量

在编译期求值,还意味着可以获得数组所占的内存大小,因为数组总是在编译期就指明自己的容量,并且在以后都是不可变的

展开
评论
day10

C语言中,可以使用sizeof()计算变量或类型占用的内存大小。在Go语言中,也提供了类似的功能,不过只能查看变量占用空间的大小。具体使用举例如下。

package main

import (
"fmt"
"unsafe"

)

type Man struct {
Name string
Age int
}

func main() {

m := Man{Name:"John", Age:20}


fmt.Println("man size:", unsafe.Sizeof(m))
fmt.Println("name size:", unsafe.Sizeof(m.Name))
fmt.Println("age size:", unsafe.Sizeof(m.Age))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
output:

man size: 24
name size: 16
age size: 8
展开
评论
day09

strconv 包转换错误处理
先来看一下 strconv 中是如何对错误进行处理的:
在 strconv 的包中包含着两种 error 类型的变量:ErrRange 和 ErrSyntax。
ErrRange 表示的是值超过了类型能表示的最大范围。
ErrSyntax 表示的是语法错误。
而我们返回的错误并不是一个简单的 Error,返回的错误是一个 NumError 的类型的 error 对象。具体结构定义如下:

// A NumError records a failed conversion.
type NumError struct {
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
Num string // the input
Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}
展开
评论
day08

一次性:作业必须一次性全部装入内存后才能开始运行。这会造成两个问题:①作业很大时,不能全部装入内存,导致大作业无法运行;②当大量作业要求运行时,由于内存无法容纳所有作业,因此只有少量作业能运行,导致多道程序并发度下降。

驻留性:一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。事实上,在一个时间段内,只需要访问作业的一小部分数据即可正常运行,这就导致了内存中会驻留大量的、暂时用不到的数据,浪费了宝贵的内存资源。
展开
评论
day07

切片(Slice)与数组一样,也是可以容纳若干类型相同的元素的容器。

与数组不同的是,无法通过切片类型来确定其值的长度。

每个切片值都会将数组作为其底层数据结构。

我们也把这样的数组称为切片的底层数组。

切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型。

这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内(左闭右开的区间)。
展开
评论
day06

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。

因为数组的长度是固定的,所以在Go语言中很少直接使用数组。

Go语言数组的声明:

var 数组变量名 [元素数量]Type
1
数组变量名:数组声明及使用时的变量名。
元素数量:数组的元素数量,可以是一个表达式,但最终通过编译期计算的结果必须是整型数值,元素数量不能含有到运行时才能确认大小的数值。
Type:可以是任意基本类型,包括数组本身,类型为数组本身时,可以实现多维数组
展开
评论
day05


标识符

标识符是指Go语言对各种变量、方法、函数等命名时使用的字符序列,标识符由若干个字母、下划线_、和数字组成,且第一个字符必须是字母。

下划线_是一个特殊的标识符,称为空白标识符

标识符的命名需要遵守以下规则:

由 26 个英文字母、0~9、_组成;
不能以数字开头,例如 var 1num int 是错误的;
Go语言中严格区分大小写;
标识符不能包含空格;
不能以系统保留关键字作为标识符,比如 break,if 等等。
展开
评论
下一页