GCN解读并附数据处理代码

news2024/11/16 13:26:27

此文GCN不是之前提到的lightGCN,而是真正的GCN图卷积,这个问题源于paper分类,同样是GAT所用的数据,其中paper之前的引用关系构成了图的边信息,之所以称之为半监督,并不是因为部分paper没有label及embedding信息,而是部分paper并没有他们的引用数据(只是出现在其他paper的引用中,如下的cite_paper,这句话是可议的,此文是逐渐明了的过程),如下释疑:q Group 277356808

1,证明paper个数总和为2708及有引用信息的paper个数(1565)Cora数据

dirs="~/cora"
    print(os.listdir(dirs))
    df=pd.read_csv(os.path.join(dirs,"cora.cites"),sep="\t",header=None)
    print(df.head())
    df.columns=["paper","cite_paper"]
    lbe=LabelEncoder()
    df["encoder"]=lbe.fit_transform(df["paper"])
    a=lbe.classes_.tolist()
    lbe = LabelEncoder()
    lbe.fit(df["cite_paper"])
    b=lbe.classes_.tolist()
    total=list(set(a+b))
    print("total papers %d"%len(total))
    new=list(set(total).difference(a))
    print("a %d, new %d"%(len(a),len(new)))

附encoder编码代码:

dct=dict(zip(a,range(len(a))))
    dct.update(dict(zip(new,range(len(a),len(a)+len(new)))))
    df["paper"]=df["paper"].apply(lambda x:dct[x])
    df["cite_paper"]=df["cite_paper"].apply(lambda x:dct[x])
    df=df.groupby("paper")["cite_paper"].agg(list).reset_index()
    print(df.shape)
    print(df.head(2))

2,读取label及embedding信息,证实所有的paper均有label及embedding

df = pd.read_csv(os.path.join(dirs, "cora.content"), sep="\t", header=None)
    df.columns=["paper"]+["emb_"+str(i) for i in range(1433)]+["label"]
    print(df.shape)
    print(len(df["paper"].unique()))
    not_in_total=list(set(total).difference(set(df["paper"].unique())))
    print(not_in_total)#[]
    not_have_label=list(set(df["paper"].unique()).difference(set(total)))
    print(not_have_label)#[]#q Group 277356808

总体来说还是有监督的学习,算不上严格的半监督,参考无监督学习,就是没有label的学习,半监督至少应该是有部分数据没有label,GCNpaper里面用的数据实际并不是如此,而仅仅是上述。那么paper中的表格label rate指的是啥呢?

 Label rate denotes the number of labeled nodes that are used for training divided by the total number of nodes in each dataset

难道说尽管实际数据是有label的,但并没有在训练中使用这部分数据,因为仅仅训练了140个,这个确实是的,so 140/2708=0.0516恰好与上面表格中的label rate对应,因此GCN paper的半监督算是严格意义的半监督

GCN是啥结构呢?

 简式如下:这是两层的GCN,通用式子就是A'*X*W ,这是一层的,其中参数如下

 

A是链接矩阵Adj,In是节点到节点自己的边信息,Dii是对角矩阵(因为是Adj,其值都是大于等于0的),因此D'求-1/2就是对单个数值进行-1/2,总体上来说是一种归一化,如下示例:python举例

>>> A34p
array([[3.2493546 , 4.1898723 , 4.0304203 , 3.9739053 ],
       [2.699943  , 1.0808966 , 3.0756474 , 4.500847  ],
       [1.6436101 , 2.258556  , 2.6459615 , 3.0535398 ],
       [1.8343056 , 0.4629674 , 3.2731762 , 0.97009325]], dtype=float32)
>>> D33=A34p.sum(axis=-1)#277356808 QQ group
>>> D33
array([15.443553 , 11.357334 ,  9.601667 ,  6.5405426], dtype=float32)
>>> D33p=np.sqrt(D33)
>>> D33p
array([3.9298286, 3.3700645, 3.0986557, 2.5574484], dtype=float32)
>>> 1/D33p
array([0.25446403, 0.29673022, 0.3227206 , 0.39101472], dtype=float32)
>>> D33p=1/D33p#q Group 277356808
>>> np.mat(np.diag(D33p))*A34p*np.mat(np.diag(D33p))
matrix([[0.21040203, 0.3163654 , 0.33098125, 0.39540032],
        [0.20386505, 0.09517168, 0.29452693, 0.5222148 ],
        [0.13497454, 0.21628146, 0.27557313, 0.38532162],
        [0.18251191, 0.0537162 , 0.4130372 , 0.14831999]], dtype=float32)

但这种归一化与L2归一化不一样,从第一行的数值大小对比就能看出来,A34p 第一行第2个最大,而这种归一化后结果则是最后一个最大,如果值相差不大,那么最后的(也就是最近的)值可能会成为关键值,当然这个A的优化点可以尝试下L2norm。归一化的方式很多,不见得有啥效果。如下证实我的L2norm计算正确,

>>> A34p/np.tile(np.linalg.norm(A34p,ord=2,axis=-1,keepdims=True),[1,4])
array([[0.41896808, 0.54023737, 0.5196778 , 0.5123908 ],
       [0.43698207, 0.17494163, 0.49778926, 0.72845584],
       [0.33461118, 0.4598037 , 0.5386729 , 0.62164897],
       [0.46996757, 0.11861691, 0.83862066, 0.24854766]], dtype=float32)
>>> from sklearn.preprocessing import Normalizer
>>> L2norm=Normalizer(norm="l2")
>>> L2norm.fit_transform(A34p)
array([[0.41896808, 0.54023737, 0.5196778 , 0.5123908 ],
       [0.43698207, 0.17494163, 0.49778926, 0.72845584],
       [0.33461118, 0.4598037 , 0.5386729 , 0.62164897],
       [0.46996757, 0.11861691, 0.83862066, 0.24854766]], dtype=float32)

因此综上:GCN总体上来说是对链接矩阵A做的优化,然后加入了DNN的思想,可以视为输入的X(节点embedding)与A相乘(视为线性转换)后再过DNN,这一步与SRGNN中将Adj视为权重w,然后再与节点embedding相乘后再过GRU是一样的,没有啥特别的。 因此GCN中“图”的概念也仅仅体现在adj,这与SRGNN是一样的。

顺便看下GCN代码, 我的处理结果与人家的对比是一致的(对adj的处理):官方代码是稀疏表示

>>> adj
array([[0., 0., 1., 0., 0., 0.],
       [1., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 1.],
       [0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0., 0.]])
>>> transAdj(adj+np.diag([1,1,1,1,1,1]))#代码上面已提及
matrix([[0.5       , 0.        , 0.5       , 0.        , 0.        ,
         0.        ],
        [0.5       , 0.5       , 0.        , 0.        , 0.        ,
         0.        ],
        [0.        , 0.5       , 0.5       , 0.        , 0.        ,
         0.        ],
        [0.        , 0.        , 0.40824829, 0.33333333, 0.        ,
         0.57735027],
        [0.        , 0.        , 0.        , 0.40824829, 0.5       ,
         0.        ],
        [0.        , 0.        , 0.        , 0.        , 0.        ,
         1.        ]])
preprocess_adj(adj)#q Group 277356808
(array([[0, 0],
       [2, 0],
       [0, 1],
       [1, 1],
       [1, 2],
       [2, 2],
       [2, 3],
       [3, 3],
       [5, 3],
       [3, 4],
       [4, 4],
       [5, 5]], dtype=int32), array([0.5       , 0.5       , 0.5       , 0.5       , 0.5       ,
       0.5       , 0.40824829, 0.33333333, 0.57735027, 0.40824829,
       0.5       , 1.        ]), (6, 6))

这一步正确了其他的dnn也无需啥操作,其实总体来说我也没有看到有明细的CNN操作,因为名字是图“卷积”,这个卷积应该体现在对adj的处理中,算是一种卷积滤波操作。

gcn原代码的操作也是matmul这种,或者dot,还是矩阵乘积,也就是W*X,W是随机初始化的,与我所述一致,dgl中的densegraphconv反而好看懂一些。

下面是本文的重点,数据的预处理方式,上一篇文章中没有完整给出adj的构建方式,有了网络结构没有数据处理方法,对于菜鸟来说还是不能拿来直接用。

注意:不是所有的分类任务都能用gcn,需要有图的结构才可以,我发现有提MNIST咋用GCN啊。。。一言难尽啊。当然可以强行构建图的关系,比如1,后面是2,2后面是3,这种可以自行尝试,不再赘述。

先来看如下数据hasItem.cfacts(部分,完整加群问我):为方便看出其中处理方法,先对第二列feat1编码,第三列视为feat2

hasItem	s_10000008_16	close_analogue
hasItem	s_10000008_12	thioguanine
...
hasItem	s_10000047_24	liver_toxicity
....
hasItem	s_10000112_20	solid_tumors
hasItem	s_10000112_20	hodgkins_lymphoma
hasItem	s_1000013_9	tamoxifen
hasItem	s_1000013_2	summary
....

读取后结果:

def read_cites(filename):
    print ('reading cites')
    cites, s_graph = [], dd(list)
    for i, line in enumerate(open(filename)):
        if i % 100000 == 0:
            print ('reading cites {}'.format(i))
        inputs = line.strip().split()
        cites.append((inputs[1], inputs[2]))
        s_graph[inputs[2]].append(inputs[1])
        s_graph[inputs[1]].append(inputs[2])
    return cites, s_graph

s_graph
defaultdict(<class 'list'>, {'close_analogue': ['2'], '2': ['close_analogue'], 'thioguanine': ['1', '16', '23', '70'], '1': ['thioguanine'], 'cross-resistance': ['0'],。。。。。。

cites没啥好说的,s_graph就是其中的feat1和feat2相互做key-value而已,并且key一样时值为list,也就是key的value合并在一起。

读取list_features.txt

head -n 4 list_features1k.txt 
s_10000008_16 1135 31 532789 1 145 13 1015 8 9325 16172 305 35709 5 338 1 120911 7 16227 6 0 193998 2575 141 2238 417099 170 14629 43 53015 5599 37410 14 14015 69 12998 33703 1563 202 5077 3999 1694 7208 3155 27235
s_10000008_12 1135 31 532789 1 145 13 1015 8 9325 16172 305 5 338 3383 12076 1 120911 7 16227 6 0 254 10937 1951 88301 20566 8469 45633 41911 3517 3072 117 5599 69 14 37410 87838 3003 113 15708 4235
s_10000008_10 1135 31 532789 1 145 13 1015 8 9325 305 35709 5 338 3383 12076 1 120911 7 16227 6 0 65 8469 100 12899 117964 117837 362082 3072 3058 5599 37410 14 30 69 33982 7141 317 8701 769
s_10000008_20 1135 31 532789 1 145 13 1015 8 9325 16172 305 35709 5 338 3383 12076 1 120911 7 6 0 376 370545 172 33 75 101 365182 379 42 5599 13940 69 14 37410 42043 11621 113 15305 1440
def read_features(filename):#277356808 QQ group
    print ('reading features')
    features, f_num = {}, 0
    for line in open(filename):
        inputs = line.strip().split()
        features[inputs[0]] = []
        try :
            for t in inputs[1:]:
                tt = int(t)
                f_num = max(f_num, tt + 1)
                features[inputs[0]].append(tt)
        except Exception as error:
            print(error)
    return features, f_num

features是字典,key是上面的第一个字符串,values是list,就是每行除了第一个字符串后的整数,f_num是values中最大值+1,表示节点个数,此值与稀疏矩阵shape大小有关。

上述的s_graph似乎么有用,下面又重新编码整了一个,

def add_index(index, cnt, key):#277356808 QQ group
    if key in index: return cnt
    index[key] = cnt
    return cnt + 1

def construct_graph(train_id, test_id, cites):
    id2index, cnt = {}, 0
    for id in train_id:
        cnt = add_index(id2index, cnt, id)
    for id in test_id:
        cnt = add_index(id2index, cnt, id)
    graph = dd(list)
    for id1, id2 in cites:
        cnt = add_index(id2index, cnt, id1)
        cnt = add_index(id2index, cnt, id2)
        i, j = id2index[id1], id2index[id2]
        graph[i].append(j)
        graph[j].append(i)
    return graph

构建x,tx,y,ty,t表示测试集,在下面的文件中的是训练集(也就是不带t的)

CATS = ['disease', 'drug', 'ingredient', 'symptom']

这是类别,也就是4类。下面是读取上面文件的,也就是只读第3列

def read_train_labels(filename):
    ret = []
    for line in open(filename):
        inputs = line.strip().split()
        ret.append(inputs[2])
    return ret
    train_list, in_labels = set(), dd(set)
    for cat in CATS:#277356808 QQ group
        print ("processing {}".format(cat))
        train_item = read_train_labels("{}/{}/{}_devel_50p_proppr_seed_forTrainList".format(dir, run_num, cat))
        print("train_item",train_item)
        for item in train_item:
            for l in s_graph[item]:
                train_list.add(l)
                in_labels[cat].add(l)
    print("train_list",train_list)

 

train_list是features中的key, 是hasItem.cfacts中的feat1

下面是train_list获得x,y的方法,tx,ty则是由test_list获取的,同样的函数

def construct_x_y(train_list, in_labels, features, f_num):
    row, col = [], []
    for i, ent in enumerate(train_list):
        try:
            for f_ind in features[train_list]:
                row.append(i)
                col.append(f_ind)
        except:
            pass
    data = np.ones(len(row), dtype = np.float32)
    x = sparse.coo_matrix((data, (row, col)), shape = (len(train_list), f_num), dtype = np.float32).tocsr()
    y = np.zeros((len(train_list), len(CATS)), dtype = np.int32)
    for i, ent in enumerate(train_list):
        for j, cat in enumerate(CATS):
            if ent in in_labels[cat]:
                y[i, j] = 1
    return x, y
        x, y = construct_x_y(train_list, in_labels, features, f_num)

最终的graph则是由上述的train_list,test_list以及cites构成,上面已经提及此函数

construct_graph

但此codes并没有ind.cora.test.index 类似的文件,看了下其中是test文件的索引吧,也不是有序的

2692
2532
2050
1715
2362
2609
2622
1975

下面读取cora的文件,如下:

#cora.x#稀疏表示,pickle读取
print(data.shape,data[21].shape,data[12])
(140, 1433) (1, 1433)   

(0, 51)	1.0
  (0, 1005)	1.0
  (0, 1175)	1.0
  (0, 1216)	1.0
#元组第一个元素都是0,第二个元素最大为1432(?)

#cora.y
(140, 7) (7,) [0 0 0 0 1 0 0]#one-hot编码

#cora.tx
(1000, 1433) (1, 1433)   
(0, 19)	1.0
  (0, 217)	1.0
  (0, 1209)	1.0
  (0, 1218)	1.0
...
  (0, 1291)	1.0
  (0, 1361)	1.0

#cora.ty
(1000, 7) (7,) [0 0 0 1 0 0 0]

#cora.allx
(1708, 1433) (1, 1433)  
  (0, 51)	1.0
  (0, 1005)	1.0
  (0, 1175)	1.0
  (0, 1216)	1.0

#cora.ally
(1708, 7) (7,) [0 0 0 0 1 0 0]

#graph
defaultdict(<class 'list'>, {0: [633, 1862, 2582], 1: [2, 652, 654], 2: [1986, 332, 1666, 1, 1454], 3: [2544], 4: [2176, 1016, 2176, 1761, 1256, 2175], 5: [1629, ... 2702: [186, 1536], 2703: [1298], 2704: [641], 2705: [287], 2706: [165, 2707, 1473, 169], 2707: [598, 165, 1473, 2706]})

adj = nx.adjacency_matrix(nx.from_dict_of_lists(graph))
                print(adj)
(0, 633)	1
  (0, 1862)	1
  (0, 2582)	1
  (1, 2)	1
  (1, 652)	1
  (1, 654)	1
  (2, 1)	1
  (2, 332)	1
  (2, 1454)	1
  (2, 1666)	1
  (2, 1986)	1
..
  (2706, 2707)	1
  (2707, 165)	1
  (2707, 598)	1
  (2707, 1473)	1
  (2707, 2706)	1

 读取新存储的数据(diel数据,下面脚本处理的数据):

#x #QQ group 277356808
(27, 1229796) (1, 1229796) 
#y
(27, 4) (4,) [0 0 0 1]
#tx
(1767, 1229796) (1, 1229796) 
#ty
(1767, 4) (4,) [0 0 0 0]
#graph
defaultdict(<class 'list'>, {157: [1794], 1794: [157], 1091: [1795], 1795: [1091, 252, 995, 328, 73, 1154, 1155, 1694, 815, 63, 482, 1329, 173, 763, 1658, 1283, 。。。 967: [2902], 2902: [967], 1163: [2903], 2903: [1163], 674: [2904], 2904: [674], 447: [2881], 688: [2881], 681: [2905], 2905: [681], 406: [2881], 1512: [1807], 41: [2557]})
#adj
  (0, 1)	1
  (1, 0)	1
  (2, 3)	1
  (3, 2)	1
  (3, 41)	1
..
  (2901, 2902)	1
  (2902, 2901)	1
  (2903, 2818)	1
  (2904, 24)	1
  (2905, 1942)	1

数据中x的维度有问题,不符合cora中的维度,这种维度太大了,这个应该不会出现在实际问题中,因为它是输入数据的embedding,其他数据都是相符的。拜拜

愿我们终有重逢之时,而你还记得我们曾经讨论的话题 

本文数据预处理脚本在此

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nacos--命名空间、分组、ID的概念及用法

原文网址&#xff1a;Nacos--命名空间、分组、ID的概念及用法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Nacos的命名空间、分组、ID的概念及用法。 Nacos通过命名空间&#xff08;Namespace&#xff09;分组&#xff08;Group&#xff09;应用&#xff08;Data ID或Name&#…

在Maix duino开发板上实现LED闪烁

文章目录简单介绍编程实现效果展示后简单介绍 如果你还不知道如何点亮LED&#xff0c;请看&#xff1a;点亮LED 今天开始上手在开发板上运行程序了&#xff0c;学习点亮LED灯就像是学习编程语言的Hello,worldHello, worldHello,world。学会电亮一盏LED灯之后&#xff0c;我便…

深度学习中计算量和参数量介绍、实现代码、例子

计算量 参数量 模型内存前言1 计算量和参数量2 统计计算量、参数量和模型内存3 源码分享3.1 thop实现3.2 ptflops实现pytorch_model_summary实现各层参数量统计4 总结前言 理清FLOPS和FLOPs&#xff0c;大写S代表的是显卡的运算性能&#xff0c;小写s代表的是模型的运算次数&a…

异构混排在vivo互联网的技术实践

作者&#xff1a;vivo 互联网算法团队- Shen Jiyi 本文根据沈技毅老师在“2022 vivo开发者大会"现场演讲内容整理而成。 混排层负责将多个异构队列的结果如广告、游戏、自然量等进行融合&#xff0c;需要在上下游和业务多重限制下取得最优解&#xff0c;相对复杂和难以控制…

基于外业移动端GIS+CAD在工程行业中的应用

摘要&#xff1a; 本文以广东九建某某高校施工项目前期准备和施工验证工作为依托&#xff0c;以图新地球精准导入CAD为研究对象&#xff0c;总结了一套相对成熟且完善的应用技术。该应用技术能在实际地形和现状数据中迅速找到施工点的大致位置&#xff0c;为前期工程勘测争取足…

【云原生消息中间件】RocketMQ消费者启动(consumer start)流程

目录 一、前言 二、消费者启动(consumer start)流程 1、RocketMQPushConsumer初始化 1.1、InitializingBean的afterPropertiesSet() 实现 1.2、RocketMQPushConsumer初始化 2、DefaultMQPushConsumer#start()逻辑 3、defaultMQPushConsumerImpl.start()逻辑 3.1、预设置…

哈希表题目:“气球”的最大数量

文章目录题目标题和出处难度题目描述要求示例数据范围解法思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;“气球”的最大数量 出处&#xff1a;1189. “气球”的最大数量 难度 2 级 题目描述 要求 给你一个字符串 text\texttt{text}text&#xff0c;你需要…

无线通信信号传输模型

1. 概述 在移动通信网的规划阶段和网络优化期间&#xff0c;最重要的传播问题是路径损耗&#xff0c;它代表大尺度传播特性&#xff0c;具有幂定律的传播特征。路径损耗是移动通信系统规划设计的一个重要依据&#xff0c;对蜂窝设计中的覆盖范围、信噪比、远近效应都有影响。因…

css色彩主题适配思路

网站主题&#xff0c;之前一直考虑的是通过替换css文件来实现&#xff0c;这种方式虽然可以&#xff0c;但不够方便。毕竟要写两套css主题&#xff0c;需要花费足够多的时间来适配。 后来琢磨出了一点东西出来&#xff0c;发现通过修改root里的css变量来实现&#xff0c;比较优…

计算机研究生就业方向之去银行券商信息技术部门

我一直跟学生们说你考计算机的研究生之前一定要想好你想干什么&#xff0c;如果你只是转码&#xff0c;那么你不一定要考研&#xff0c;至少以下几个职位研究生是没有啥优势的&#xff1a; 1&#xff0c;软件测试工程师&#xff08;培训一下就行&#xff09; 2&#xff0c;前…

NR HARQ(一)概述

HARQ是MAC层的快速重传机制&#xff0c;5G部分HARQ相关内容分布在38.331,38.321,38.213,38.214,38.212,38.211等spec中&#xff0c;这篇仅仅针对NR HARQ 进行简单的概括梳理。 NR中上下行HARQ均为异步HARQ&#xff1b;NR中每个HARQ反馈信息可以针对一个上/下行 TB块&#xff0c…

PDF文件怎么打印?分享两种打印方法

如何将PDF文件打印出来呢&#xff1f;大家在使用PDF文件的时候&#xff0c;在确定一份文件没有问题的时候&#xff0c;会选择将文件打印出来使用&#xff0c;有很多小伙伴身边有打印设备&#xff0c;但是不知道怎么打印&#xff0c;今天小编给大家分享两种打印方法&#xff0c;…

Resolution-robust Large Mask Inpainting with Fourier Convolutions 阅读笔记

基于傅里叶卷积的鲁棒分辨率大Mask修补 WACV 2022 论文链接 代码链接 图1&#xff1a;本文提出的方法可成功修复大区域&#xff0c;并很好处理具有复杂重复结构的图像。该方法在256256低分辨率下训练也能泛化到高分辨率图像上。 摘要&#xff1a; 现代图像修复技术主要受阻于大…

基于intel平台车载M12网管交换机方案,13路网口,支持bypass功能

概述&#xff1a;XM-5130是二层网管型以太网交换机&#xff0c;该产品前面板提供13路100M自适应以太网接口、4路车辆间带链路聚合及bypass功能的以太网接口&#xff0c;接口通过M12端子形式提供。该产品适用于振动、温度、湿度、电源波动变化大、电磁干扰复杂的恶劣工作环境。设…

传统大型国企云原生转型,如何解决弹性、运维和团队协同等问题?

作者&#xff1a;王彬、杏祉尧、黄枫 项目背景 贵州酒店集团有限公司于 2019 年 2 月 28 日注册成立&#xff0c;是经贵州省人民政府批准并授权省国资委履行出资人职责的省管大一型企业&#xff0c;全资及控股子企业 23 家&#xff0c;自营及委管酒店&#xff08;项目&#x…

Nacos的持久化和集群部署

###目前网络模式为&#xff1a;bridge 1.docker mysql:5.7的持久化存储及远程连接 1.下拉镜像 docker pull mysql/mysql-server:5.7 注&#xff1a;后面的mysql标签是版本号&#xff0c;可选择&#xff0c;有&#xff1a;5.5/5.6/5.7/8.0 2.在宿主机中相关目录&#…

单片机内部组成

目录 中央处理器&#xff08;CPU&#xff09; 内部数据存储器&#xff08;128B RAM&#xff09; 内部程序存储器&#xff08;4KB ROM&#xff09; 定时/计数器 可编程I/O口 串行接口 中断控制系统 时钟电路 中央处理器&#xff08;CPU&#xff09; 中央处理器是单片机的…

测试工作干了7年,却被实习生代替,是实习生太牛了,还是我们太弱了?

前几天有个朋友向我哭诉&#xff0c;说她在公司工作&#xff08;软件测试&#xff09;了7年了&#xff0c;却被一个实习生代替了&#xff0c;该何去何从&#xff1f; 这是一个值得深思的问题&#xff0c;作为职场人员&#xff0c;我们确实该思考&#xff0c;我们的工作会被实习…

详解文件篇(待更)

目录前言一、背景知识1.文件的真面目2.对文件进行的操作3.所谓的打开文件究竟是在干啥&#xff1f;4.文件可能存在的位置&#xff1f;5.文件操作的幕后主使者二、复习C语言中的相关文件操作1. 源代码&#xff1a;形成一个file.txt的文件2. 以"r"的方式打开文件3. 以&…

C++异常详解

文章目录前言一、C语言传统的处理错误的方式二、C异常概念三、异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范四、C标准库的异常体系五、自定义异常体系六、异常的优缺点C异常的优点C异常的缺点总结前言 正文开始&#xff01; 一、C语言传统的处理…