内容简介

1、课程大纲

2、第二部分第四课:
字符串

3、第二部分第五课预告: 预处理


课程大纲

我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案。还会带大家用C语言编写三个游戏。

C语言编程基础知识

  • 什么是编程?

  • 工欲善其事,必先利其器

  • 你的第一个程序

  • 变量的世界

  • 运算那点事

  • 条件表达式

  • 循环语句

  • 实战:第一个C语言小游戏

  • 函数

  • 练习题

  • 习作:完善第一个C语言小游戏

C语言高级技术

  • 模块化编程

  • 进击的指针,C语言王牌

  • 数组

  • 字符串

  • 预处理

  • 创建你自己的变量类型

  • 文件读写

  • 动态分配

  • 实战:“悬挂小人”游戏

  • 安全的文本输入

  • 练习题

  • 习作:用自己的语言解释指针

用基于C语言的SDL库开发2D游戏

  • 安装SDL

  • 创建窗口和画布

  • 显示图像

  • 事件处理

  • 实战:“超级玛丽推箱子”游戏

  • 掌握时间的使用

  • 用SDL_ttf编辑文字

  • 用FMOD控制声音

  • 实战:可视化的声音谱线

  • 练习题

数据结构

  • 链表

  • 堆,栈和队列

  • 哈希表

  • 练习题


第二部分第四课:字符串

好了,这课我不说废话,直接进入主题了。(但又好像不是我的风格...)

《字符串》,这是一个编程的术语,用来描述“一段文字”,很简单。

一个字符串,就是我们可以在内存中以变量的形式储存的“一段文字”。比如,用户名是一个字符串,“程序员联盟”是一个字符串。但是我们之前的课说过,呆萌的电脑兄只认得数字,“众里寻他千百度,电脑就爱穿秋裤”(不是“穿秋裤”,是“认得数”。说好不废话的,小编你这么顽皮你妈妈知道么...)。

所以说电脑实际是不认得字母的,但是“古灵精怪”的计算机先驱们是怎么设计使电脑可以“识别”字母呢?

接下来我们会看到,他们其实还是很聪明的。


字符类型

在这个小部分,我们把注意力先集中在字符类型上。

如果你还记得,之前的课程中我们说过: 有符号字符类型(char)是用来储存范围从-128到127的数的; unsigned char(无符号字符类型)用来储存范围从0到255的数.

注意: 虽然char类型可以用来储存数值,但是在C语言中却鲜少用char来储存一个数. 通常,即使我们要表示的数比较小,我们也会用int类型来储存,当然了,用int来储存比用char来储存在内存上更占空间,但是今天的电脑基本是不缺那点内存的,“有内存任性嘛”.

char类型一般用来储存一个字符,注意,是 一个 字符.

前面的课程也提到了,因为电脑只认得数字,所以计算机先驱们建立了一个表格(比较常见的有ASCII表, 更完整一些的有Unicode表),用来约定字符和数字之间的转换关系,例如字母A(大写)对应的数字是65.

C语言可以很容易地转换字符和其对应的数值. 为了获取到某个字符对应的数值(电脑底层其实都是数值),只需要把该字符用单引号括起来,像这样:

'A'

在编译的时候,'A'会被替换成实际的数值: 65

我们来测试一下:

int main(int argc, char *argv[])

{

   char letter = 'A';



   printf("%d\n", letter);



   return 0;

}

程序输出:

65

所以,我们可以确信大写字母A的对应数值是65. 类似地,大写字母B对应66, C对应67, 以此类推. 如果我们测试小写字母,那你会看到a和A的数值是不一样的,小写字母a的数值是97, 实际上,在大写字母和小写字母之间有一个很简单的转换公式,就是 “小写字母的数值 = 大写字母的数值 + 32”. 所以电脑是区分大小写的. 看似呆萌的电脑兄还是可以的么.

大部分所谓“基础”的字符都被编码成0到127之间的数值了. 在ASCII表(发音【aski】)的官网 www.asciitable.com 上,我们可以看到大部分常用的字符的对应数值. 当然这个表我们也可以在其他网站上找到,比如维基百科,百度百科,等等.

显示字符

要显示一个字符,最常用的还是printf函数啦,这个函数真的很强大,我们会经常用到.

上面的例子中,我们用%d格式,所以显示的是字符对应的数值(%d是整型),如果要显示字符实际的样子,需要用到%c格式(c是英语character[字符]的首字母):

int main(int argc, char *argv[])

{

   char letter = 'A';



   printf("%c\n", letter);



   return 0;

}

程序输出:

A

哇,我们知道如何输出一个字符了,可喜可贺!(小编你也该吃药了...)

当然我们也可以用常见的scanf函数来请求用户输入一个字符,而后用printf函数打印:

int main(int argc, char *argv[])

{

   char letter = 0;



   scanf("%c", &letter);

   printf("%c\n", letter);



   return 0;

}

如果我输入C,那我将看到:

C

C

第一个字母C是我输入给scanf函数的,第二个C是printf函数打印的.

以上就是对于字符类型char我们大致需要知道的,请牢记以下几点:

  1. 有符号字符类型(signed char)是用来储存范围从-128到127的数的; unsigned char(无符号字符类型)用来储存范围从0到255的数. (C语言中,如果你没写signed或unsigned关键字,默认情况下是表示有符号signed)

  2. 计算机先驱们给电脑规定了一个表,电脑可以遵照里面的转换原则来转换字符和数值,一般这个表是ASCII表

  3. char类型只能储存一个字符

  4. 'A'在编译时会被替换成实际的数值:65 。因此,我们使用单引号来获得一个字符的值


字符串其实就是字符的数组

这一部分的内容,就如这个小标题所言.

事实上: 一个字符串就是一个“字符的数组”,仅此而已.

到这里,你是否对字符串有了更直观的理解呢?

如果我们创建一个字符数组:

char string[5];

然后我们在数组的第一个成员上储存‘H’,就是string[0] = 'H',第二个成员上储存'E'(string[1] = 'H'),第三个成员上储存'L'(string[2] = 'L'),第四个成员储存'L' (string[3] = 'L'),第五个成员储存'O'(string[4] = 'O'),那么我们就是构造了一个字符串啦:

下图对于字符串在内存中是怎么存储的,可以给出一个比较直观的印象(注意: 实际的情况比这个图演示的要略微复杂一些,待会会解释):

上图中,我们可以看到一个数组,拥有5个成员,在内存上连续存放,构成一个字符串 "HELLO". 对于每一个储存在内存地址上的字符,我们用了单引号把它括起来,是为了突出实际上储存的是数值,而不是字符. 在内存上,储存的就是此字符对应的数值.

实际上,一个字符串可不是就这样结束了,上面的图示其实不完整. 一个字符串必须在最后包含一个特殊的字符,称为“字符串结束符”,它是'\0',对应的数值是0.

“为什么要在字符串结尾加这么一个多余的字符呢?”

问得好!

那是为了让电脑知道一个字符串到哪里结束. '\0'用于告诉电脑:“停止,字符串到此结束了,不要再读取了,先退下吧”。

因此,为了在内存中存储字符串"HELLO"(5个字符),用5个成员的字符数组是不够的,需要6个!

因此每次创建字符串时,需要记得在字符数组的结尾留一个字符给'\0'。

忘记字符串结束符是C语言中一个常见的错误。

因此,下面才是正确展示我们的字符串"HELLO"在内存中实际存放情况的示意图:

如上图所见,这个字符串包含6个字符,而不是5个。

也多亏了这个字符串结束符'\0',我们就无需记得字符串的长度了,因为它会告诉电脑字符串在哪里结束。因此,我们就可以将我们的字符数组作为参数传递给函数,而不需要传递字符数组的大小了。

这个好处只针对字符数组,你可以在传递给函数时将其写为 char *或者char[]类型。对于其他类型的数组,我们总是要在某处记录下它的长度。

字符串的创建和初始化

如果我们想要用“Hello”来初始化字符数组string,我们可以用以下的方式来实现,当然有点没效率:

char string[6]; // 六个char构成的数组,为了储存: H-e-l-l-o + \0

string[0] = 'H';

string[1] = 'e';

string[2] = 'l';

string[3] = 'l';

string[4] = 'o';

string[5] = '\0';

虽然是笨办法,但至少行得通。

我们用printf函数来测试一下。

要使printf函数能显示字符串格式,我们需要用到%s这个符号(s就是英语string的首字母):

#include <stdio.h>

int main(int argc, char *argv[])

{

char string[6]; // 六个char构成的数组,为了储存: H-e-l-l-o + \0

string[0] = 'H';

string[1] = 'e';

string[2] = 'l';

string[3] = 'l';

string[4] = 'o';

string[5] = '\0';

// 显示字符串内容

printf("%s\n", string);

return 0;

}

程序输出:

Hello

如果我们的字符串内容多起来,上面的方法就更显拙劣了。其实啊,初始化字符串还有更简单的一种方式(小编你好奸诈,不早讲,害我写代码这么辛苦...):

int main(int argc, char *argv[])

{

char string[] = "Hello"; // 字符数组的长度自动计算了

printf("%s\n", string);

return 0;

}

以上程序的第一行,我们写了一个char []类型的变量,其实也可以写成 char * 同样是可以运行的:

char *string = "Hello";

这种方法就比之前一个字符一个字符初始化的方法高大上多了,因为只需要在双引号里输入你想要创建的字符串,C语言的编译器就很智能地为你计算好了字符串的大小,就是说它计算你输入的字符的数目,然后再加上一个'\0'的长度(是1),它就把你的字符串里的字符一个接一个写到内存某个地方,在最后加上'\0'这个字符串结束符,就像我们刚才用第一种方式自己一步步做的。

但是简便也有缺陷,我们会发现,对于字符数组来说,这种方法只能用于初始化,你在之后的程序中就不能再用这种方式来给整个数组赋值了,比如你不能这样:

char string[] = "Hello";

string = "nihao";           --> 出错!

只能一个字符一个字符地改,例如:

string[0] = 'j';                 --> 可以!

但是问题又来了,对于用char *来声明的字符串,我们可以在之后整个重新赋值,但是不可以单独修改某个字符:

char *string = "Hello";

string = "nihao";           --> 可以!

这样是可以的,但是如果修改其中的一个字符,就不可以:

string[1] = 'a';              -->  出错!

很有意思吧。大家可以亲自动手试试。所以这里就引出了一个话题:

指针和数组根本就是两码事!

为什么会出现上述的情况呢?

那是因为:

1.

char string[] = "Hello";

这样声明的是一个字符数组,里面的字符串是储存在内存的变量区,是在栈上,所以可以修改每个字符的内容,但是不可以单单通过数组名整体修改:

string = "nihao";      --> 出错!

只能一个个单独改:

string[0] = 'a';          --> 可以!

因为之前的课程里说过,string这个数组的名字表示的是数组首元素的首地址。

2.

char *string = "Hello";

这样声明的是一个指针,string是指针的名字。指针变量在32 位系统下,永远占4 个byte(字节),其值为某一个内存的地址。所以string里面只是存放了一个地址,这个地址上存放的字符串是常量字符串,存在内存的静态区,不可以更改。

和上面的字符数组情况不一样,上面的字符数组是本身存放了那一整个字符串。

string[0] = 'a';          --> 出错!

但是可以改变string指针的指向:

string = "nihao";      --> 可以!(因为可以修改指针指向哪里)

大家可以自己测试一下:

char *n1 = "it";

char *n2 = "it";

printf("%p\n%p\n", n1, n2);  //用%p查看地址

会发现二者的结果是一样的,指向同一个地址!

再进一步测试(生命在于折腾):

char *n1="it";

char *n2="it";

printf("%p\n%p\n",n1,n2);

n1 = "haha";

printf("%p\n%p\n",n1,n2);

你会发现以上程序,指针n2所指向的地址一直没变,而n1在经过

n1 = "haha";

之后,它所指向的地址就改变了。

经过上面地分析,可能很多朋友还是有点晕,特别是可能不太清楚内存各个区域的区别。如果有兴趣深入探究,既可以自己去看相关的C语言书籍。也可以参考下表和一些解释,如果暂时不想把自己搞得更晕,可以跳过,以后讲到相关内容时自然更好理解:

名称 内容

代码段 可执行代码、字符串常量
数据段 已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据
BSS段 未初始化全局变量,未初始化全局静态变量
局部变量、函数参数
动态内存分配

一般情况下,一个可执行二进制程序(更确切的说,在Linux操作系统下为一个进程单元,在UC/OSII中被称为任务)在存储(没有调入到内存运行)时拥有3个部分,分别是代码段(text)、数据段(data)和BSS段。这3个部分一起组成了该可执行程序的文件。

(1)代码段(text segment):存放CPU执行的机器指令。通常代码段是可共享的,这使得需要频繁被执行的程序只需要在内存中拥有一份拷贝即可。代码段也通常是只读的,这样可以防止其他程序意外地修改其指令。另外,代码段还规划了局部数据所申请的内存空间信息。

代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

(2)数据段(data segment):或称全局初始化数据段/静态数据段(initialized data segment/data segment)。该段包含了在程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据。

(3)未初始化数据段:亦称BSS(Block Started by Symbol)。该段存入的是全局未初始化变量、静态未初始化变量。

而当程序被加载到内存单元时,则需要另外两个域:堆域和栈域。

(4)栈(stack):存放函数的参数值、局部变量的值,以及在进行任务切换时存放当前任务的上下文内容。

(5)堆(heap):用于动态内存分配,即使用malloc/free系列函数来管理的内存空间。

在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈也由操作系统分配和管理,而不需要程序员显示地管理;堆由程序员自己管理,即显示地申请和释放空间。

很多C语言地初学者弄不清指针和数组到底有什么样的关系。

现在就告诉大家:它们之间没有任何关系!它们是清白的...

  1. 指针就是指针,指针变量在32 位系统下,永远占4 个byte(字节),其值为某一个内存的地址。指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到。

  2. 数组就是数组,其大小与元素的类型和个数有关。定义数组时必须指定其元素的类型和个数。数组可以存任何类型的数据,但不能存函数。

推荐大家去看《C语言深度解剖》这本只有100多页的pdf,是国人写的,里面对于指针和数组分析得很全面。



不禁感叹,C语言果然是博(shi)大(fen)精(keng)深(die)。

从scanf函数取得一个字符串

我们可以用scanf函数获取用户输入的一个字符串,也要用到%s符号。

但是有一个问题:就是你不能知道用户究竟会输入多少字符。假如我们的程序是问用户他的名字是什么。那么他可能回答Tom,只有三个字符,或者Bruce LI,就有8个字符了。

所以我们只能用一个足够大的数组来存储名字,例如 char [100]。你会说这样太浪费内存了,但是前面我们也说过了,目前的电脑一般不在乎这点内存。

所以我们的程序会是这样:

int main(int argc, char *argv[])

{

char name[100];

printf("请问您叫什么名字 ? ");

scanf("%s", name);

printf("您好, %s, 很高兴认识您!\n", name);

return 0;

}

运行程序:

请问您叫什么名字?Oscar

您好,Oscar,很高兴认识您!


操纵字符串的一些常用函数

字符串在C语言里是很常用的,事实上,此刻你在电脑或手机屏幕上看到的这些单词、句子等,都是在电脑内存里的字符数组。

为了方便我们操纵字符串,C语言的设计者们在 string 这个标准库中已经写好了很多函数,可供我们使用。

当然在这以前,需要在你的.c源文件中引入这个头文件

#include <string.h>

下面我们就来介绍它们之中最常用的一些吧:

strlen:计算字符串的长度

strlen函数返回一个字符串的长度(不包括\0)。

函数原型是这样:

size_t strlen(const char* string);

注意:size_t是一个特殊的类型,它意味着函数返回一个对应大小的数目。不是像int,char,long,double之类地基本类型,而是一个被“创造”出来的类型,在接下来的课程中我们就会学到如何创建自己的变量类型。暂时说来,我们先满足于将strlen函数的返回值存到一个int变量里(电脑会把size_t自动转换成int),当然严格来说应该用size_t类型,但是我们这里暂时不深究了。

函数地参数是 const char *类型,之前的课程中我们学过,const(只读的变量)表明此类型的变量是不能被改变的,所以函数strlen并不会改变它的参数的值。

写个程序测试一下strlen函数:

int main(int argc, char *argv[])

{

char string[] = "Hello";

int stringLength = 0;

// 将字符串的长度储存到stringLength中

stringLength = strlen(string);

printf("字符串 %s 中有 %d 个字符\n", string, stringLength);

return 0;

}

程序运行,显示:

字符串 Hello 中有5个字符

当然了,这个strlen函数,其实我们自己也可以很容易地实现。只需要用一个循环,从开始一直读入字符串中的字符,计算数目,一直读到'\0'字符结束循环。

我们就来实现我们自己的strlen函数好了:

int stringLength(const char *string);

int main(int argc, char *argv[])

{

char string[] = "Hello";

int length = 0;

length = stringLength(string);

printf("字符串 %s 中有 %d 个字符\n", string, length);

return 0;

}

int stringLength(const char *string)

{

int charNumber = 0;

char currentChar = 0;

do

{

currentChar = string[charNumber];

charNumber++;

}

while(currentChar != '\0'); // 我们做循环,直到遇到'\0',跳出循环

charNumber--;   // 我们将charNumber减一,使其不包含'\0'的长度

return charNumber;

}

程序输出:

字符串 Hello 中有 5 个字符

strcpy:把一个字符串地内容复制到另一个字符串里

函数原型:

char* strcpy(char* targetString, const char* stringToCopy);

这个函数有两个参数:

  1. targetString:这是一个指向字符数组的指针,我们要复制字符串到这个字符数组里。

  2. stringToCopy:这是一个指向要被复制的字符串的指针。

函数返回一个指向targetString的指针,通常我们不需要获取这个返回值。

用以下程序测试此函数:

int main(int argc, char *argv[])

{

/* 我们创建了一个字符数组string,里面包含了几个字符。我们又创建了另一个字符数组copy,包含100个字符,为了足够容纳拷贝过来的字符 */

char string[] = "Text", copy[100] = {0};

strcpy(copy, string);   // 我们把string复制到copy中

// 如果一切顺利,copy的值应该和string是一样的

printf("string 是 %s\n", string);

printf("copy 是 %s\n", copy);

return 0;

}

程序输出:

string 是 Text

copy 是 Text

如果我们的copy数组的长度小于6,那么程序会出错,因为string的总长度是6(最后有一个'\0'字符串结束符)。

strcpy的原理图解如下:

strcat:连接两个字符串

strcat函数的作用是连接两个字符串,就是把一个字符串接到另一个的结尾。

函数原型:

char* strcat(char* string1, const char* string2);

因为string2是const类型,所以我们就想到了,这个函数肯定是将string2的内容接到string1的结尾,改变了string1所指向的字符指针,然后返回指向string1所指字符数组的指针。略微有点拗口,但不难理解吧。

写个程序测试一下:

int main(int argc, char *argv[])

{

/* 我们创建了两个字符串,字符数组string1需要足够长,因为我们要将string2的内容接到其后 */

char string1[100] = "Hello ", string2[] = "Oscar!";

strcat(string1, string2);  // 将string2接到string1后面

// 如果一切顺利,那么string1的值应该会变为"Hello Oscar!"

printf("string1 是 %s\n", string1);

// string2没有变

printf("string2 始终是 %s\n", string2);

return 0;

}

程序输出:

string1 是 Hello Oscar!

string2 始终是 Oscar!

函数的原理如下:

当strcat函数将string2连接到string1的尾部时,它需要先删去string1字符串最后的'\0'。

strcmp:比较两个字符串

函数原型:

int strcmp(const char* string1, const char* string2);

可以看到,strcmp函数不能改变string1和string2,因为它们都是const类型。

这次,函数地返回值有用了。strcmp返回:

  1. 0:当两个字符串相等时

  2. 非零的整数(负数或正数):当两个字符串不等时

用以下程序测试strcmp函数:

int main(int argc, char *argv[])

{

char string1[] = "Text of test", string2[] = "Text of test";

if (strcmp(string1, string2) == 0) // 如果两个字符串相等

{

printf("两个字符串相等\n");

}

else

{

printf("两个字符串不相等\n");

}

return 0;

}

程序输出:

两个字符串相等

sprintf:向一个字符串写入

当然,这个函数其实不是在string.h这个头文件里,而是在stdio.h头文件里。但是它也与字符串的操作有关,所以我们也介绍一下,而且这个函数是很常用的。

看到sprintf函数的名字,大家是否想到了printf函数呢?

printf函数是向标准输出(一般是屏幕)写入东西,而sprintf是向一个字符串写入东西。前面的s就是英语string的首字母。

写个程序测试一下此函数:

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[])

{

char string[100];

int age = 18;

// 我们向string里写入"你18岁了"

sprintf(string, "你%d岁了", age);

printf("%s\n", string);

return 0;

}

程序输出:

你18岁了

其他常用的还有一些函数,如 strstr(在字符串中查找一个子串),strchr(在字符串里查找一个字符),等等,我们就不一一介绍了。


总结

  1. 电脑不认识字符,它只认识数字(0和1),为了解决这个问题,计算机先驱们用一个表格规定了字符与数值的对应关系,最常用的是ASCII表

  2. 字符类型char用来存储一个字符,且只能存储一个字符. 实际上存储的是一个数值,但是电脑会在显示时转换成对应的字符

  3. 为了创建一个词或一句话,我们需要构建一个字符串,我们用字符数组来实现

  4. 所有的字符串都是以'\0'结尾,这个特殊的字符'\0'标志着字符串的结束

  5. 在string这个C语言标准库中,有很多操纵字符串的函数,只需要引入头文件 string.h即可


第二部分第五课预告:

今天的课就到这里,一起加油咯。

下一次我们学习第二部分第五课:预处理


程序员联盟社区

目前有一个微信群和一个QQ群(都已经破百人),凡是对编程感兴趣的朋友都可以加,大家可以交流,学习,互动,分享写的程序的源代码,等。

微信群(程序员联盟),加群请私信我(微信群人数超过100之后,不能通过扫描二维码加入了,只能私信我,谢谢)

QQ群(程序员联盟),群号是 413981577

QQ群共享里有N多编程PDF。扫描下面二维码加QQ群:

我们还建立了一个公共的百度云盘,2TB容量,供大家上传优秀编程资源,链接加群之后会发送。

我的微信号可以在文章最后看到,QQ和邮箱也在最后。

也创建了《程序员联盟》的微社区,方便大家提问和互动。可以关注一下。

微社区地址和二维码如下:

http://m.wsq.qq.com/264152148

谢谢!


程序员联盟
微信公众号
*您若觉得本文不错,请点击画面右上角《···》按钮“分享到朋友圈”或“发送给朋友”

*新朋友请关注「程序员联盟」微信搜公众号
 ProgrammerLeague

小编微信号:

frogoscar

小编QQ号:  379641629

小编邮箱:    enmingx@gmail.com

程序员联盟QQ群:413981577

程序员联盟微信群:先加我微信

有朋友反映看手机端的文章太累,其实是可以用浏览器网页来看的

方法1. 点击画面右上角的《···》按钮,然后选择“复制链接”,再把链接黏贴到你的浏览器里面或用邮件发送给自己,就可以在电脑的浏览器里打开了

方法2. 头条网www.toutiao.com,搜索我的自媒体“程序员联盟”,里面有所有文章,也可以直接进这个链接:http://www.toutiao.com/m3750422747/

方法3. 我的51CTO博客和CSDN博客链接(所有文章会在上面)

http://4526621.blog.51cto.com/

http://blog.csdn.net/frogoscar

新朋友如何查看所有文章:

点击“查看公众号”,再点击“查看历史消息”

程序员联盟”公众号专为程序员,App设计师,各位喜爱编程和热爱分享的小伙伴们推送各样编程相关知识,优秀软件推荐,业界动态等。搜索

ProgrammerLeague
加关注~

【C语言探索之旅】 第二部分第四课:字符串的更多相关文章

  1. 【C语言探索之旅】 第一部分第九课:函数

    内容简介 1.课程大纲 2.第一部分第九课:函数 3.第一部分第十课预告: 练习题+习作 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. ...

  2. 【C语言探索之旅】 开宗明义及第一课:什么是编程?

    内容简介 1.课程大纲 2.第一部分第一课:什么是编程? 3.第一部分第二课预告:工欲善其事,必先利其器 ​ 课程大纲 不知道为什么,一直对C语言有一种很深厚的“情怀”(类似老罗对锤子手机的那种),说 ...

  3. 【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布

    内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做 ...

  4. 【C语言探索之旅】 第二部分第二课:进击的指针,C语言的王牌!

    内容简介 1.课程大纲 2.第二部分第二课: 进击的指针,C语言的王牌 3.第二部分第三课预告: 数组 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言 ...

  5. 【C语言探索之旅】 第二部分第三课:数组

    内容简介 1.课程大纲 2.第二部分第三课: 数组 3.第二部分第四课预告:字符串 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语 ...

  6. 【Web探索之旅】第二部分第四课:数据库

    内容简介 1.第二部分第四课:数据库 2.第二部分第五课预告:响应式网站 第二部分第四课:数据库 说到“数据库”,顾名思义,是“数据的仓库”的意思. 所以数据库的一大作用就是储存数据咯. 为什么Web ...

  7. 【Linux探索之旅】第二部分第四课:文件操纵,鼓掌之中

    内容简介 1.第二部分第四课:文件操纵,鼓掌之中 2.第二部分第五课预告:用户和权限 文件操纵,鼓掌之中 既然上一课我们学习了Linux中的文件组织方式,那么现在就该是玩弄,啊不,是操纵它们的时候了. ...

  8. 【C语言探索之旅】 第二部分第一课:模块化编程

    内容简介 1.课程大纲 2.第二部分第一课: 模块化编程 3.第二部分第二课预告: 进击的指针,C语言王牌 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C ...

  9. 【C语言探索之旅】 第二部分第十课:练习题和习作

    内容简介 1.课程大纲 2.第二部分第十一课:  练习题和习作 3.第三部分第一课预告:  安装SDL 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言 ...

随机推荐

  1. 深入理解Tomcat系列之二:源码调试环境搭建(转)

    前言 最近对Tomcat的源码比较感兴趣,于是折腾了一番.要调试源码首先需要搭建环境,由于参考了几篇帖子发现都不怎么靠谱,最后还是折腾出来了,然而却花了足足一天的时间去搭建这个环境.发现都不是帖子的问 ...

  2. codeforces#253 D - Andrey and Problem里的数学知识

    这道题是这种,给主人公一堆事件的成功概率,他仅仅想恰好成功一件. 于是,问题来了,他要选择哪些事件去做,才干使他的想法实现的概率最大. 我的第一个想法是枚举,枚举的话我想到用dfs,但是认为太麻烦. ...

  3. Struts2第一个工程helloStruts极其基本配置

    前面已经准备好了Struts-2.3.15,现在就可以直接搭建Struts2的工程了.前面http://blog.csdn.net/huangchnegdada/article/details/917 ...

  4. Android学习十九:ContentProvider初步

    一.Content Provider基本概念 1.ContentProvider为存储和获取数据提供了统一的接口.ContentProvide对数据进行封装.不用关心数据存储的细节.使用表的形式来组织 ...

  5. 开启本地MySql数据库远程连接

    解决MySQL不允许从远程访问的方法 开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 33 ...

  6. Android于fragment_main.xml文件问题组件收购

    package com.dhy.phonedial; import android.app.Activity; import android.app.Fragment; import android. ...

  7. pcie inbound、outbound及EP、RC间的互相訪问

    Inbound:PCI域訪问存储器域 Outbound:存储器域訪问PCI域 RC訪问EP: RC存储器域->outbound->RC PCI域->EP PCI域->inbou ...

  8. 一个简单而经典的RTX51 Tiny应用实例

    关于RTX51 Tiny嵌入式实时操作系统的描写叙述请參考本人的上一篇博文(RTX51 Tiny实时操作系统学习笔记-初识RTX51 Tiny). 本篇博文.我将通过一个实例代码,带大家深入了解一下R ...

  9. uvaLive5713 次小生成树

    uvaLive5713 修建道路使得n个点任意两点之间都可以连通,每个点有都有一定的人口,现在可以免费修一条道路, A是免费修的道路两端结点的人口之和, B的其它不是免费修道路的长度的总和 要求的是A ...

  10. Windows Phone开发(35):使用Express Blend绘图

    原文:Windows Phone开发(35):使用Express Blend绘图 上一节中我们简单扯了一下绘图指令,然而那也不是最简单的绘图法,今天,我再向大家推荐一种更好的绘图方案--Express ...