《The C Programming Language》读书笔记 说明
作为笔记而言,完全是一种自写自看的行为,本来是没有必要写这篇东西的。但是作为一个生活在网络时代的学

生来说,想学好一样东西最好的办法把自己理解的东西放出去,让人讨论,从而,错误得到及时的更正,正确的

思想得到肯定,进一步激发深入学习的激情,另外,还可以避免因为成天面对机器而忘记人话是咋说的(还真的差

点忘了),恩,好处多多,何乐不为?

为什么要学习c语言?对于今天这个惟利是图的世界来说,恐怕初学者第一要问的就这个问题,他们中的很多人都

会说在拥有c++,java,c#这些高级语言的今天,c能做什么呢?在网络中,得到的回答往往是:c无所不能,然

后是一些语重心长的说教,呵呵,对于一个对编程知道不多的人来说这样的回答没有任何意义,因此我对这样的

问题的回答是:那些高级语言的出现并不能结束c三十年的长盛不衰,c语言没有被任何一种语言所代替,而和c同

时代的那些东西。恐怕今天的人连名字都忘了,而在这个世界的每个角落都有无数的编程爱好者和从业人士对c有

着无以伦比的狂热。这是事实,这是真理,它证明了一切。无须多言了。

毫无疑问没有人能比K&R对c更有发言权了,用他们亲笔所写的《The C Programming Language》来入门是再合适

不过了,尽管现在市场上关于c的教材到处都是,但是大半都是以这本书为根基的,严格来说关于c的一切疑问都

可以在这本书中得到解释,我的笔记也将以此为本,另外会引入另一本巨作《c专家编程》的观点(强烈向各位有

一定c基础的人。推荐此书),为了灵活,这里不作任何约定,在每篇笔记开头会标明笔记内容。

另外,必须声明:本人绝对拥有此笔记的版权,任何不经本人同意,就自行修改盗窃,我保留起诉的权利,

注:本笔记以《The C Programming Language》第二版中译本为准。

笔记范围:《The C Programming Language》第一章

应该说,算上这次,我应该是第四次读这本书了,每次重读都收获不少。都引起我新的思考,很难想象这本一本

技术小书给人留下的感觉是如此深刻,如此令人回味,本章的内容是很容易理解的概念,对于编程学习者是最起

码的知识,但是有些东西还是被初学者忽视。以至于在各个技术社区的初学者问题中层出不断。其实这些东西,

在第一章就得到了比较完整的解释,下面只是把他们提出来强调一下,

第一.关于循环终止。在很多书籍中都存在这样的循环语句:

while ( getchar() != EOF )  {….}

很多人不明白这个EOF为何物?具体如何操作?以至于让上面的语句变成了无限循环,呵呵,其实EOF。是文件结

束符(end of file),在第七章有说明。其为系统常量。值为-1,当然你在终端输入-1,循环并未结束,why?

how to do?恩,你在《c专家编程》里会了解到,c的第一批使用者都是系统设计者和编译器设计者。在他们的理

念里,信息往往以文件为单位的。这个标志只是文件结束的状态,一般不由用户提供。而键盘等输入端在os中是

个极其特殊的文件。需要用户显式标志文件结束。说是系统常量当然有着系统依赖性,因此不同的系统标志方式

就完全不同。Windows下是ctrl+z。linux下是ctrl+D.另外EOF其实不用显式说明。上面的代码与此完全等价:

while( getchar() ) {……}

第二.声明和定义。尽管这个问题地球人都知道,但是真正说的清楚的人并不多。有人认为变量的声明和定义没

有什么区别。有人认为这个与初始化有关系(我曾经就这样白痴,汗~~~),对于后者那就是根本就不明白这

两个概念,声明只是给编译器一个提示,有这么个名字存在于程序中,和运行环境毫无关系。可以重复出现,定

义是具体分配内存空间和指定了变量的位子(左值),在同一域中只能出现一次;对于前者的观点。在单文件程

序中。几乎找不到错误。但如果你把这样的句子放人头文件,int a;一旦这个头文件被重复包涵。必然出现链接

错误。其实这样:
extern int a;//声明
int a;//定义

第三.字符数组和字符串。有人认为这两个是同一概念,是这样吗?不,完全不是,前者为容器(数据结构),后

者为数据。这样说也许太理论化,好,我们来改写下那个hello world

#include <stdio.h>

#include <stdlib.h>

int main()

{
    printf( "/0hello world " );

system("pause");

return 0;

}
      呵呵,什么也没有?是的。还记得字符串是怎么结束的吗?/0 "/0hello world "是个常量数组。但是字符

串却是“”。字符数组和字符长度是不一样的,

这章尽管非常简单,但是每个例子都经典之作,你能从代码中学到文字中不能学到的东西。建议你每个都抄一遍

《The C Programming Language》读书笔记2
第二章:(本文首载于第二书店本人的暑假系列笔记)

本章的内容是学习编程中最基础东西,任何一门语言都会告诉你他支持那些数据类型、那些运算、有那些特点、

以及有那些不完善的东西。学习这些东西相对来说是单调了点,麻烦了点,但是只有通过了这座迷宫,你才能就

进入c这个神奇的领域。因此初学者的成功至少有一半来自“耐心”。呵呵,准备好了吗?

本章的内容还是非常简单的,但是作者的字里行间隐藏了很多重要的信息,不加注意就会从我们的眼皮低下溜了

去,下面将一一列出以示强调。

第一.变量和常量。很多人对于他们的区别很模糊,个人认为他们的主要区别在于是否分配内存空间,换句话说

,就是是否存在左值。左值是什么?在第二章的从头到尾好像没找到这个名词,呵呵,你可以在附录中关于变量

的条目中找到他,其实就是变量的地址,变量一旦被定义,左值就被确定了,一直到他的生存期结束。我们通常

说的变量的值是指变量的右值。这才是我们能操作的对象。根据这个理论,那么就不难知道其实被const修饰的对

象不是常量,他有左值,但是这里有个小麻烦,在本章的开头写明了被const修饰的是常量(本章第二段有个()

说明),我查看了原版,并没有这个补充说明,看来应该是译者的理解,在《c专家编程》中的一个例子证明了我

的想法是正确的,例子如下:

#include “stdio.h”

#include “stdlib.h”

#define one 1

const int two = 2;

int main()

{

int ix = 1;

switch( ix )

{

case one: printf( "this is 1" );/*ok*/

break;

case two: printf( "this is 2" );/*error*/

}

system( "pause" );

return 0;

}

大家都知道,case后面只能跟常量表达式,因此被const修饰的变量不是常量,只是变量的右值一般不能改变罢了

。另外你也可以从上面感觉出#define和const的区别。

第二.关于换码序列。这个更多地方叫转义字符,他们大多数是有一些特殊的功能的字符,在上篇笔记中你已经

看到了他的一点威力,下面我们再看一段代码:

#include "stdio.h"

#include "string.h"

#include "stdlib.h"

int main()

{

int ix;

ix = strlen( "/0abc" );

printf( "this is %d/n", ix );

ix = strlen( "/007abc" );

printf( "this is %d/n", ix );

system( "pause" );

return 0;

}

你会发现,两个差不多的字符串长度完全不一样,什么回事呢?第一个我们可以理解:/0是字符串结束符,因此

其后的任何东西都不能算字符串的内容,因此长度为0。但是第二个呢?我们查了换码序列表就知道‘/007’这个

为一个字符,因此长度为4。这个时候问题来了,编译器为什么没把‘/007’理解为‘/0’‘0’‘7’呢?如果这

样的话长度也将为0,我们又没人为的加分割符号,呵呵,显然这个和编译器的具体实现相关,凭我们现有知识无

法弄明白这点,姑且留着,等待“悟“的一天吧,相信我,这绝对是一种享受。

第三,关于++运算符,在很多教材上都有个看起来很经典的题目,其代码如下:

#include "stdio.h"

#include "stdlib.h"

int main()

{

int ix, iy;

iy = 1;

ix = ( iy++ ) + ( iy++ ) + ( iy++ );

printf( "this is %d/n", ix );

iy = 1;

ix = ( ++iy ) + ( iy++ ) + ( iy++ );

printf( "this is %d/n", ix );

iy = 1;

ix = ( ++iy ) + ( ++iy ) + ( iy++ ) ;

printf( "this is %d/n", ix );

iy = 1;

ix = ( ++iy ) + ( ++iy ) + ( ++iy ) ;

printf( "this is %d/n", ix );

system( "pause" );

return 0;

}

呵呵,是不是很晕?这个本来无非为了说明先加后加的问题,这个地球人都知道,这里不加说明了,但是这样的

程序本身就有很大的问题,编译器的运算并非一定是从左到右的(有些是按树的遍历来算的),因此你会发现不

同的编译器结果会不一样,关于这个本章的结尾有很完整的解释,我就不再多说了,总之,这个测试本身就违背

了语言的特性。

《The C Programming Language》读书笔记3
第三章:当好机器的老板

无论什么时候我们都不该忘记我们是在学一门语言,而学语言的基本要求是:准确无误的用它来表示自己的意

图,不仅要让机器读懂,也要让别人(只要他会c语言)读懂你的意思。记住,语言是用来交流的,不论是编程语

言还是自然语言。现在让我们对这两个交流的对象分别作个分析,如何才能让他们明白你想干什么,打算怎么干

对于机器来说,我们要做的相对要简单点,编程语言的语法比自然语言要简单的多了,一切都由顺序、选择、

循环三种结构复合而成,初学者要做的只是走一个“抄写-改写-模仿-习惯”的过程而已。等这些语句成了你

的习惯那就太好了,就像你说汉语的时候不会去考虑你用的是陈述句还是感叹句,呵呵,(这个让我想起了我糟

糕的英语,汗~~~)。当然我们对机器要做的远远不止这些,让机器读懂这只是第一步而已,如何让机器按照

我们的意思运行的更好、更快才是我们要追求的境界,当然,这个境界没有止境。得在经验中慢慢积累,下面只

是提出几个个人的建议而已:

第一.    尽量使用局部变量。因为c语言有个特点,在同个域中的变量必须定义在所有处理语句之前(分程序

[o1] 除外),这意味着在程序开始的时候就必须分配好所有的静态空间,而很多数据在程序中用很少,因此我们

需要减少这些不必要的开销,灵活运用分程序可以将这些对象进一步局部化,比较下面两段代码:

Code1:

#include "stdio.h"

#include "stdlib.h"

int main()

{

int ix;

char c;

scanf( "%c", &c );

if( c == 'y')

{

ix = 100;

printf( "this is %d! /n", ix );

}

system( "pause" );

return 0;

}

Code2

#include "stdio.h"

#include "stdlib.h"

int main()

{

char c;

scanf( "%c", &c );

if( c == 'y')

{

int ix = 100;

printf( "this is %d! /n", ix );

}

system( "pause" );

return 0;

}

你会发现如果我们不输入‘y’系统就没有必要为ix分配空间。

第二,注意和正视一些看起来像bug的语言特性,比如switch语句,可以说从c语言建立的那天起对他的争论就没

有停止过,它的向下穿越给我们带来了不少麻烦。以至于在《c专家编程》的第二章中把它说成是“多做之过“,

但是我们发现有时候它的功能还是不可代替的,比如判断一个数是否属于某个离散集合:

#include "stdio.h"

#include "stdlib.h"

int main()

{

int i;

while( scanf( "%d", &i ) != EOF )

{

switch( i )

{

case 1: case 2:

case 3: case 5:

case 8: case 13:

printf( "yes!/n" );

break;

default :

printf( "no!/n" );

break;

}

}

system( "pause" );

return 0;

}

呵呵,这个数列大家都熟悉,但是除了switch语句你能找到比他更简洁的表示方法吗?但这正是运用了语句的向

下穿越性啊。goto语句也有类似的情况,只要我们仔细研究,这些看起来很麻烦的东西都会变得非常美好。

好了,对机器的交流我们就说到这儿吧。在下次笔记中我们将谈谈和人的交流-程序的风格问题。

--------------------------------------------------------------------------------

[o1]也叫复合语句

(本文首载于第二是书店)

《The C Programming Language》读书笔记4
程序设计初步

到现在为止,我们已经对语言的基本元素有了个比较完整的了解了,但是总是停留在表达式等细节方面,我们

很难写出程序来,在今天任何一个程序都是个工程,如何组织我们已经掌握的这些基本元素,使得他们变成有一

点功能的有机整体,这个就需要一个整体观念的设计思想,对于c来说第一步该是过程化程序设计思想,换而言之

,就是函数的设计,在上篇文字中我们已经看到了,其核心问题是如何分解要解决的问题,写出各个有独立功能

的函数,然后由进入接口函数(在控制台环境下,通常是main函数)组成完整的程序。但是光是这样,我们能解

决的问题相当有限,因为在实际应用中,我们要处理的不是那么简单的内置类型(int,char等),而是比这些复

杂的多的数据类型,因此第二步该是如何针对具体问题写出抽象模型,即ADT(抽象数据类型),进而实现基于对

象的设计思想,而学习指针和结构就需要带着这样的思想去探索,下面将通过一个简单list(链表)的设计来简

要的说明一下该如何建立一个完整的程序。

第一步,建立一个空项目,最好不要选择“控制台程序”模板,这样能使得你的设计思路清楚明白,记住你现

在在学习,方便快速不是你该追求的东西。

第二步,静下心来好好想一想。你的链表要提供那些接口、那些可以给用户修改的部分(如具体的数据类型)

,这些放在用户可见的list.h文件中。在本文中假设我们提供初始化、销毁、增加节点、删除节点、 插入节点、

查找、和打印输出几项功能。那么在上面的工程里加入一个叫llst.h的文件,输入代码如下:

#ifndef LIST_H

#define LIST_H

/*定义函数状态*/

#ifndef ERR

#define ERR -1

#define OK 1

#endif

typedef int status;

typedef void type;     /*用户可以根据具体需要更改此类型*/

typedef struct listitem {

type           date;      /*节点数据*/

struct listitem *next;    /*指向下个节点*/

} list_node;//链表节点

typedef struct {

struct listitem  *ptr;    /*链表头指针*/

int              size;    /*链表长度*/

} list;//链表

list* list_init ( void );     /*初始化*/

status list_destroy( list* ); /*销毁*/

status add_node( list*, const type );  /*加入一个节点*/

status delete_all( list* );//清空

status delete_node( list*, list_node* ); /*删除一个节点*/

status insert_node( list*, const type ); /*插入一个节点*/

list_node* find_node( const list*, const type ); /*查找*/

status list_print( const list* );    /*打印*/

#endif

第三步,在工程中加入list.c文件。Include了上面刚刚建立的头文件,并实现每个极口,由于在通常情况下此文

件并不是用户可见(这里把维护等问题除外),所以笔者没加什么注释。当然这个不是什么好习惯,这里过于简

单,注释就显得有些多余。

首先是include需要的头文件:

#include "stdio.h"

#include "stdlib.h"

/*严格来说上面该用尖括号,由于网页显示不得已为之*/

#include "list.h"

接下来是初始化和销毁的实现

list* list_init ( void )

{

list *p = ( list* )malloc( sizeof( list ) );

if( p == 0 )

return 0;

p->ptr = 0;

p->size = 0;

return p;

}

status list_destroy( list *pev )

{

if( pev == 0 )

return ERR;

delete_all( pev );

free( pev );

return OK;

}

按理说,函数不能返回指针,呵呵,这里有个很多初学者都误会的问题,返回局部对象的左值和局部对象的引用(

后者是c++中的说法)被返回的确不可以,因为局部对象在函数的活动记录(即函数调用栈中)分配,函数一旦结

束局部对象被回收,返回的将是无效地址。因此象下面这样的函数是错误的,

int* f()

{

int *p, a;

p = &a;

return p;

}

但是由malloc分配的是堆上分配的,他不会随着函数的结束而被回收。但是这样用要相当小心,必须防止内存泄

漏。程序结束前必须free掉该空间。

下面就是完整的list.c

#include "stdio.h"

#include "stdlib.h"

/*严格来说此处处该用尖括号,由于网页显示不得已为之*/

#include "list.h"

list* list_init ( void )

{

list *p = ( list* )malloc( sizeof( list ) );

if( p == 0 )

return 0;

p->ptr = 0;

p->size = 0;

return p;

}

status list_destroy( list *pev )

{

if( pev == 0 )

return ERR;

delete_all( pev );

free( pev );

return OK;

}

status add_node( list *p, const type date )

{

list_node *pev =

( list_node* )malloc( sizeof( list_node ) );

if( pev == 0 )

return ERR;

pev->date = date;

pev->next = p->ptr;

p->ptr = pev;

p->size++;

return OK;

}

status delete_node( list *p, list_node *pev )

{

list_node *temp = pev;

if( pev == 0 )

return ERR;

pev = temp->next;

free( temp );

p->size--;

return OK;

}

status delete_all( list *pev )

{

int ix;

if( pev == 0 )

return ERR;

if( pev->size = 0 )

return ERR;

for( ix = 0; ix < pev->size; ++ix, ++pev->ptr )

delete_node( pev, pev->ptr );

return OK;

}

status insert_node( list *p, const type date )

{

list_node *pev = p->ptr; ;

if( p == 0 )

return ERR;

pev = find_node( p, date );

if( pev == 0 )

{

type ia;

printf( "输入要插入的数/n" );

scanf( "%d", &ia );

add_node( p, ia );

}

else

{

type ia;

list_node *pv =

( list_node* )malloc( sizeof( list_node ) );

if( pev == 0 )

return ERR;

printf( "输入要插入的数/n" );

scanf( "%d", &ia );

pv->date = ia;

pv->next = pev->next;

pev->next = pv;

p->size++;

}

return OK;

}

list_node* find_node( const list *pev , const type date )

{

int ix;

list_node *p = pev->ptr;

for( ix = 0; ix < pev->size; ++ix )

if( p->date == date )

return p;

else

p = p->next;

return 0;

}

status list_print( const list *pev )

{

int ix;

list_node *p = pev->ptr;

if( pev == 0 )

return ERR;

if( pev->size == 0 )

return OK;

for( ix = 0; ix < pev->size; ++ix )

{

printf( "%d/t", p->date );

p = p->next;

}

printf( "/n" );

return OK;

}

第四步,自己写个main函数,由于个人的调试方式不同,这里不给出代码。只要确保每个函数都能正常工作就行

了。

好了,到现在为止我们把一个数据结构的实现走了一遍。当然,为了简单文字。笔者减少了很多list该有的功能

。很多人认为我写太烂,现在再次说明,本文和初学者交流的文字,高手们就不必在这篇文字浪费你的时间了

《The C Programming language》读书笔记5
尽量利用能利用的资源

在上篇文字中,我们设计了一个非常简单的list,在设计的过程运用了在本书第五、六章的知识,这些东西

是c语言中最难的部分,学术方面的讨论随处可见,指针的用法和特性多得让人无法记住,个人认为最好的方法是

多实践,在实践遇到的问题往往就是最常见的、最重要的知识点,至于那些特别的特性,等熟悉了那些常见的后

也就不难理解他们了。

本书的第七。八两章所述的内容严格来说是不属于语言本身的东西,是的,我认为该这么说,这个关系到对”

库”的理解,库是什么?是别人已经写好的东西(类型、函数、常量等等),我们的程序可以根据他们提供的接

口调用就可,以节省我们开发的时间和精力,但是必须明白,不是没有库,我们就不能写东西了。第八章的内容

就是告诉我们如何根据具体的os写出类似标准的io库,是的,库必须是系统相关的,当然你可以最大限度的保证

他的可移植性(这正是标准库的成功之处)。

当然,对于大多数程序开发而言,库的运用可能是程序设计水平高低的最重要的指标之一,没有人会笨到放着

的东西不用,而化费大量的时间去自己写一个(当然作为学习研究则正好相反)。有一次,一个网友跟我说标准

c++和c怎么也干不了,当我提出反对意见时,此人气势汹汹的质问:“你不用WIN API写个窗体给我看看!?”。

我无言了,因为要说的太多了, 比如:难道API是凭空出现的吗?难道我写不出API就可以说c++和c无此能力吗?

我无此荣幸,就算有,也不是片刻就可以拿出来给他证明的。因此我选择沉默,人类的任何成功都是建立在前人

的基础上的,这样才有我们引以为傲的效率。

回到正题,标准库非常庞大(别的也小不到那去),os的系统调用也很多,对于这些我的建议是:记住常用的,

别的用到的时候查手册之类的东西即可,比如,以c标准库为例,在本书附录B中提到的大多都需要记住。至于别

的,大家可以去看看《c语言参考手册》。

好了。暑假结束了,本笔记也可以结束了(是的,我听到有人在说:”这个家伙终于闭嘴了”,有自知之明?

呵呵,或许是“他”知之明吧。),写笔记是笔者的一种学习习惯,csdn的编辑也只是为了向大家推荐几本好书

并引起良好的学习讨论,才要求笔者修改一些针对性用词,比如“暑假学习笔记“等等,并转载此处。对于学生

而言,有个交流的平台是件好事,自己的错误可以得到及时的更正。不管作者的水平如何,他写出了自己的想法

,整理了自己的知识,提出了自己善意的建议,这就不是件容易的事情。可是我们看到什么呢?无思考的指错。

没看清楚文字就拿代码发难。无意义的漫骂,大概是为了显示自己的水平吧,更有些人说是某位作者是为D币而来

(我在本站另一书评中所见的评论)。其实稍对本站有些理解的人都知道,得到和他买书化的钱根本就不能相提

并论,这些现象不能不说是个遗憾。

最后的最后,要是有朋友对我还有什么建议的话,可以访问我的blog:http://blog.csdn.net/owl2008/,但是

要首先声明,也许csdn不能拒绝一些自以为是的评论家。但我是绝对不欢迎的,要读我的东西,你先得给我最起

码的尊重。

注:这是在第二书店的系列的结束篇。对第七八两掌的技术心得,我会在本blog站后续笔记中写出

《The C Programming Language》读书笔记 说明相关推荐

  1. mysql数据库权威指南_MySQL_MySQL权威指南读书笔记(三),第二章:MYSQL数据库里面的数 - phpStudy...

    MySQL权威指南读书笔记(三) 第二章:MYSQL数据库里面的数据 用想用好MYSQL,就必须透彻理解MYSQL是如何看待和处理数据的.本章主要讨论了两个问题:一是SQL所能处理的数据值的类型:二是 ...

  2. MongoDB权威指南读书笔记——CRUD

    插入并保存文档 插入是向MongoDB中添加数据的基本方法.可以使用Insert方法向目标集合插入一个文档:db.foo.insert({"bar" : "baz&quo ...

  3. HTTP权威指南读书笔记

    <<HTTP权威指南>>读书笔记 第一部分:Web的基础 第1章:HTTP概述 主要内容 1.什么是HTTP 2.HTTP的基本组件 HTTP HTTP:HTTP(Hypert ...

  4. HTML5权威指南----读书笔记

    <!DOCTYPE html> <html> <head><meta name = 'keywords' content="HTML5权威指南--- ...

  5. 计算机网络和http权威指南 读书笔记

    计算机网络笔记 网络层 网络层向上提供无连接的,尽最大努力交付的数据报服务 网络层不提供数据质量承诺 物理层使用的中间设备叫转发器repeater 数据链路层叫网桥bridge 网络层叫路由器rout ...

  6. MapReduce总结 + 相关Hadoop权威指南读书笔记(未完......欢迎补充,互相学习)

    文章目录 MapReduce概述 MapReduce优缺点 MapReduce核心思想 MapReduce进程 MapReduce编程规范 WordCount 案例实操 本地测试 集群测试 Hadoo ...

  7. android开发读书笔记,android开发权威指南读书笔记

    第17章 Fragment 1.在res目录下增加 layout-sw600dp 目录,用于存放7英寸及以上尺寸屏幕的布局文件.10英寸以上平板用 sw720dp.如果是更小的屏幕,如 480*800 ...

  8. java性能权威指南中文_Java性能权威指南读书笔记--之一

    JIT(即时编译) 解释型代码:程序可移植,相同的代码在任何有适当解释器的机器上,都能运行,但是速度慢. 编译型代码:速度快,电视不同CPU平台的代码无法兼容. java则是使用java的编译器先将其 ...

  9. javascript权威指南读书笔记之二——词法结构

    本章讲述的内容,用通俗的语言来说,就是应该注意的地方,这些也许和我们所学的其他语言类似,也许完全不同,比如一开始就介绍说javascript程序中的每个字符都是用两个字节表示的,但有些程序设计者习惯于 ...

  10. HTTP权威指南读书笔记(一)HTTP概述、URL和资源及报文详解

    一.HTTP概述 1.WEB客户端和服务器. 2.资源:资源可以是各种格式的静态文件,也可以是应用程序. 3.媒体类型 4.URI:统一资源标识符 URL:统一资源定位符. URL的第一部分称为方案: ...

最新文章

  1. 初学者必备的数组相关知识点
  2. 使用Tensorflow实现残差网络ResNet-50
  3. 华南赛区线上比赛安排
  4. Gitlab环境快速部署(RPM包方式安装)
  5. Python Django 通过admin后台创建表数据
  6. Groovy里的绕过getter方法直接访问类属性的办法
  7. sklearn线性回归详解
  8. @RequestBody、@ResponseBody的具体用法和使用时机
  9. 分享一些自己的学习过程和学习方法
  10. android中intent放数据类型,Android Intent传递数据底层分析详细介绍
  11. map-side-join inspark
  12. Golang通过syscall调用windows dll方法
  13. CSS3实践之路(四):文本特效
  14. .NET中获取电脑名、IP地址及用户名方法
  15. 服务器 16路直连 英特尔,Intel 10nm服务器怪咖:八通道+16条内存
  16. SVM多分类算法-一对一
  17. 21年6月阿里巴巴Java暑期实习面经回顾(已上岸)
  18. spring aop 和Transaction一起使用执行顺序问题
  19. 将QT中的单选、复选框从选中状态设置为未选中状态
  20. 【JavaScript】数组方法应用自测例题

热门文章

  1. Mongo之中标麒麟V7环境下安装解压版
  2. babylonjs 分部加载模型_初学WebGL引擎-BabylonJS:第2篇-基础模型体验
  3. vue中使用vuex-persistedstate插件实现数据持久化
  4. JS 实现抛物线运动
  5. 总结 — 键盘输入特殊字符
  6. 给Java程序员的一些中肯建议,你还在虚度光阴吗?(文末福利)
  7. python可视化数据分析-Python数据分析与可视化从入门到精通
  8. Doodle era
  9. 阿里巴巴推动时尚零售智能化 FashionAI展示数字化零售新模式
  10. [转载]巴塞罗那神圣家族教堂