美文网首页
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