美文网首页
C语言基础

C语言基础

作者: 五分钟诗人 | 来源:发表于2019-07-27 09:24 被阅读0次

Hello, World!

介绍

C语言是一种通用编程语言,与机器工作密切相关。理解计算机内存如何工作是C语言的一个重要的层面。纵然C被认为是“难学的”,但实际上C是一种非常简单语言,有很大的可拓展性。

C是一种非常通用的语言,被用来编写很多应用,比如Windows、Python解释器、Git,等等。

C是一种编译型的语言,这意味着为了运行它,编译器就必须处理我们所写的的代码,然后建立一个可执行文件。这个文件可以被执行,然后完成我们想要做的任务。

我们的程序

每个C程序都使用库,以提供执行必要函数的可能。比如,最基础的函数叫做printf,(用来打印内容到屏幕),就是定义在stdio.h头文件中的。

为了能够运行printf命令,我们还必须直接地包含下面这行代码到我们的程序的第一行:

 #include <stdio.h>

程序的第二部分是我们实际要写的代码,main函数提供了运行的入口。

 int main() 
 {
     //... our code goes here
     printf("Hello, World!");
     return 0;
 }

int关键字指明了main函数将返回一个简单的整数。返回的数字将直接地指明我们的程序是否成功地工作。如果我们想说我们的程序成功地运行,我们将返回一个整数0,而大于0的整数意味着程序出现了某种错误。

注意:C语言程序的每一行都必须以分号(;)结束。

变量和类型

数据类型

C有很多类型的变量,以下是基础:

  • 整型 - 可正可负,使用char,int,short,long,long long来定义。
  • 非负整型 - 只能是正数,使用unsigned char,unsigned int,unsigned short,unsigned long,unsigned long long来定义。
  • 浮点型 - 实数,使用float,double来定义。
  • 结构体(后面会阐述),使用struct来定义。

不同类型的变量定义了它们的边界,char类型的范围从-128127,而long则从-2,147,483,6482,147,483,647,另一些类型在不同计算机上可能会有差别。

注意:C没有boolean类型。但是可以使用下面的方法定义:

 #define BOOL char
 #define FALSE 0
 #define TRUE 1

C使用字符数组来定义字符串,后面将会阐述。

定义变量

对于数字,我们通常使用类型int,在计算机里面占据一个word的大小(4 Bytes)。

定义变量foobar,需要使用下列语法:

 int foo;
 int bar = 1;

变量foo可以被使用,但我们没有初始化它,我们并不知道它实际上存储的是什么。变量bar包含了整数1

现在,我们可以做一些数学。假设abcde是变量,我们在下面使用加减乘除操作,以及将一个新的值给a

 int a = 0, b = 1, c = 2, d = 3, e = 4;
 a = b - c + d * e;
 printf("%d", a); /* will print 1-2+3*4 = 11 */

数组

数组是一种特殊的变量,可以包含超过一个相同类型的值,通过索引来访问。数组使用一种直接的语法来定义:

 /* defines an array of 10 integers */
 int numbers[10];

从数组中访问元素使用同样的语法。注意C中的数组是以0为第一个索引的,这意味着如果我们定义了 一个大小为10的数组,数组的下标是09numbers[10]不是一个实际的值。

 int numbers[10];
 
 /* populate the array */
 numbers[0] = 10;
 numbers[1] = 20;
 numbers[2] = 30;
 numbers[3] = 40;
 numbers[4] = 50;
 numbers[5] = 60;
 numbers[6] = 70;
 
 /* print the 7th number from the array, which has an index of 6 */
 printf("The 7th number in the array is %d", numbers[6]);

数组只能有一种类型的元素,因为它们在计算机内存是一系列连续存储的值。正是这样,访问数组中的每一个元素都非常的高效。

多维数组

在之前的数组章节中,我们概述了什么是数组及其工作原理。我们当时着眼的是一维数组,但C可以创建和使用多维数组,这里是声明多维数组的通用形式:

 type name[size1][size2]...[sizeN];

比如,这样:

 int foo[1][2][3];

或者,这样:

 char vowels[1][5] = {
     {'a', 'e', 'i', 'o', 'u'}
 };

二维数组

多维数组最简单的形式是二维数组。一个二维数组不过是拓展的一维数组而已,一维数组的的每一个元素都是一个列表:

 type arrayName[x][y];

type可以是C的任何数据类型(int,long,long long,double,etc),arrayName是一个合法的C标识符或者变量。二维数组也可以看成是xy列的表格,一个3行4列的数组可以表示如下:

二维数组

在这种情况下,数组中的每一个元素都可以用a[i][j]来表示,其中a是数组名,i,j是该元素在数组中的唯一下标。

其实,并不一定要指定数组a的行数,因为你可以像下面这样定义:

 char vowels[][5] = {
     {'A', 'E', 'I', 'O', 'U'},
     {'a', 'e', 'i', 'o', 'u'}
 };

编译器已经知道这是一个二维数组,你只需要指定有多少列!,编译器可能是智能的,它知道有多少个整数、字符、浮点数,无论你用多少维。

初始化二维数组

多维数组可以使用大括号({})来初始化每一行。下面是一个3行4列的数组。为了更加简化,你可以不写行数把它留空,编译照样通过。

 int a[3][4] = {  
    {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
    {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
    {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
 };

内部的指定每一行的大括号是可选的。下面的初始化与之前的相同:

 int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

访问二维数组中的元素

二维数组中的元素是通过下标访问的,即,数组的行标和列标。

 int val = a[2][3];

上面的语句将会从数组中取出第3行第4列的元素。

条件

作出决策

生活中,我们常常需要做决定。为了作出决定我们权衡我们的选择,在程序中也是这样的。

这里是一个C语言的判断结构。

 int target = 10;
 if (target == 10) {
     printf("Target is equal to 10");
 }

if 语句

if语句允许我们检查表达式的真假(true or false),然后根据结果执行不同的代码。

使用==来判断两个变量是否相等,就像第一个例子那样。

不等运算符也可以用在判断表达式中。比如:

 int foo = 1;
 int bar = 2;
 
 if (foo < bar) {
     printf("foo is smaller than bar.");
 }
 
 if (foo > bar) {
     printf("foo is greater than bar.");
 }

当计算的判断表达式为false时,我们可以使用else关键字来执行我们的其他代码。

 int foo = 1;
 int bar = 2;
 
 if (foo < bar) {
     printf("foo is smaller than bar.");
 } else {
     printf("foo is greater than bar.");
 }

有时我们会得到超过一个选择,这时,使用多个if else来完成。

 int foo = 1;
 int bar = 2;
 
 if (foo < bar) {
     printf("foo is smaller than bar.");
 } else if (foo == bar) {
     printf("foo is equal to bar.");
 } else {
     printf("foo is greater than bar.");
 }

你也可以使用多个嵌套if else语句如果你喜欢。

 int peanuts_eaten = 22;
 int peanuts_in_jar = 100;
 int max_peanut_limit = 50;
 
 if (peanuts_in_jar > 80) {
     if (peanuts_eaten < max_peanut_limit) {
         printf("Take as many peanuts as you want!\n");
     }
 } else {
     if (peanuts_eaten > peanuts_in_jar) {
         printf("You can't have anymore peanuts!\n");
     }
     else {
         printf("Alright, just one more peanut.\n");
     }
 }

两个或者多个判断表达式也可以同时计算。判断两个表达式是否都是真(true),使用&,判断它们至少有一个为真,使用||

 int foo = 1;
 int bar = 2;
 int moo = 3;
 
 if (foo < bar && moo > bar) {
     printf("foo is smaller than bar AND moo is larger than bar.");
 }
 
 if (foo < bar || moo > bar) {
     printf("foo is smaller than bar OR moo is larger than bar.");
 }

非操作符可以用来取反:

 int target = 9;
 if (target != 10) {
     printf("Target is not equal to 10");
 }

字符串

定义字符串

C中的string实际上是字符数组。纵然使用指针是高级的话题,后面会阐述,我们将使用指针来定义简单的字符串,以下面的形式:

 char * name = "John Smith";

这种方法创建的string只能读。如果我们希望在字符串上操作,我们需要将它定义局部字符数组:

 char name[] = "John Smith";

这种表示法和上面的是有区别的,因为我们分配了一个数组变量所以我们能够操纵它。空的中括号[]告诉编译器来动态地计算数组的大小。

 char name[] = "John Smith";
 /* is the same as */
 char name[11] = "John Smith";

即使字符串John Smith正好只有11个字符,但我们还必须在定义的时候加上一个。这是由字符串的表示法决定的。C中字符串的结尾有一个特殊字符\0表示字符串的结束,但这个字符不会纳入字符串长度的计算中,只是便于编译器处理罢了。

使用printf来格式化字符串

我们使用printf命令来格式化一些字符串,以下面的形式:

 char * name = "John Smith";
 int age = 27;
 
 /* prints out 'John Smith is 27 years old.' */
 printf("%s is %d years old.\n", name, age);

注意:在打印字符串的时候,我们必须增加\n来换行,因为printf函数不是默认换行的。

字符串的长度

函数strlen传入字符串的地址,返回其长度。

 char * name = "Nikhil";
 printf("%d\n",strlen(name));

字符串比较

函数strncmp比较两个字符串,参数是两个字符串,以及要比较的长度;如果他们相等则返回0,若不同则返回其他数字。也有一种不太安全的版本叫strcmp,但不推荐使用,比如:

 char * name = "John";
 
 if (strncmp(name, "John", 4) == 0) {
     printf("Hello, John!\n");
 } else {
     printf("You are not John. Go away.\n");
 }

字符串拼接

函数strcat在后面增加nsrc中字符到dest中,其中,nmin(n,length(src));参数是源字符串src和目的字符串dest,以及要增加的最大字符的数量。

 char dest[20]="Hello";
 char src[20]="World";
 strncat(dest,src,3);
 printf("%s\n",dest);
 strncat(dest,src,20);
 printf("%s\n",dest);

For循环

C中的for循环是直接的。当一段代码需要多次执行时使用循环来解决,for循环使用一个迭代变量,通常表示为i

for循环给出如下定义:

  • 用初始值初始化迭代变量
  • 检查条件,判断是否已经到达最后的值
  • 改变迭代变量的值

比如说,我们希望迭代一段代码10次,我们会写:

 int i;
 for (i = 0; i < 10; i++) {
     printf("%d\n", i);
 }

注意:在for循环头部声明迭代变量是C++的语法(随处声明随处使用)。

这个代码快将打印数字09(一共10个数字)。

for循环也可以迭代数组的值。比如,我们想要计算数组内元素的总和,我们使用迭代变量i作为数组索引:

 int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int sum = 0;
 int i;
 
 for (i = 0; i < 10; i++) {
     sum += array[i];
 }
 
 /* sum now contains a[0] + a[1] + ... + a[9] */
 printf("Sum of the array is %d\n", sum);

While 循环

while循环与for循环很像,但功能更少。但条件为true时,while循环会不断地执行内部的代码块。比如说,下面的代码将会正好执行10次。

 int n = 0;
 while (n < 10) {
     n++;
 }

while循环也可以无限地执行,如果条件永远都是true的话。在C中,所有非0的值都是true

 while (1) {
    /* do something */
 }

循环的控制

有两种循环的控制方法,breakcontinue

break将结束整个循环,即使循环没有完全地执行指定的次数。

 int n = 0;
 while (1) {
     n++;
     if (n == 10) {
         break;
     }
 }

continue语句用来跳过当次循环,即,对于一次迭代,continue以下的语句将不会被执行。下面的例子,continue导致了某些情况下printf函数将被忽略,只有偶数才被输出。

 int n = 0;
 while (n < 10) {
     n++;
 
     /* check that n is odd */
     if (n % 2 == 1) {
         /* go back to the start of the while block */
         continue;
     }
 
     /* we reach this code only if n is even */
     printf("The number %d is even.\n", n);
 }

函数

C函数是简单的,但由于C的工作方式,函数的功能有一些限制。

  • 函数接收固定或者不定数量的参数
  • 函数只能返回一个值,或不返回任何值。

在C中,实际参数按值的方式拷贝,这意味着我们不能改变在函数外部的变量的值。如果要改变,我们必须使用指针,后面会讲到。

函数以下面的形式定义:

 int foo(int bar) {
     /* do something */
     return bar * 2;
 }
 
 int main() {
     foo(1);
 }

我们定义的函数foo接收一个整型参数bar,将其乘以2,然后返回。

调用函数foo采用以下语法,传入参数bar的值是1。

 foo(1);

在C中,函数必须先定义再使用。函数可以先在文件开始处或者头文件中声明,然后再实现;也可以按照使用的顺序实现。

The correct way to use functions is as follows:

使用函数的正确方法如下:

 /* function declaration */
 int foo(int bar);
 
 int main() {
     /* calling foo from main */
     printf("The value of foo is %d", foo(1));
 }
 
 int foo(int bar) {
     return bar + 1;
 }

我们也可以创建一个没有返回值的函数,使用关键字void

 void moo() {
     /* do something and don't return a value */
 }
 
 int main() {
     moo();
 }

Static

static是C语言关键字,可以用来修饰变量和函数。

什么是静态变量?

默认地,变量在定义的时候作用域都是局部的。将变量定义为static可以将其作用域提升到整个文件;结果,这些static变量可以在文件内部访问。

考虑下面的程序,我们想计算所参与的跑步者。

 #include<stdio.h>
 int runner() {
     int count = 0;
     count++;
     return count;
 }
 
 int main()
 {
     printf("%d ", runner());
     printf("%d ", runner());
     return 0;
 }

我们将会看到count并没有被更新,因为当函数完成的时候,变量count会从内存中移除。但是,当static变量使用时,情况将会不一样,整个文件使用同一个count,更改也会被任何函数发现。

 #include <stdio.h>
 int runner()
 {
     static int count = 0;
     count++;
     return count;
 }
 
 int main()
 {
     printf("%d ", runner());
     printf("%d ", runner());
     return 0;
 }

什么是静态函数?

在C中,函数默认都是全局的。如果我们将函数定义为static,它的作用域将降低到包含该函数的文件。

语法就像这样:

 static void fun(void) {
    printf("I am a static function.");
 }

静态 VS 全局

静态变量只在包含它的文件内部有效,而全局的变量可以在文件外部访问。

相关文章

网友评论

      本文标题:C语言基础

      本文链接:https://www.haomeiwen.com/subject/emjsrctx.html