C语言基础1

1 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
在这里插入图片描述

涉及到的知识点:

  1. 指针变量的定义以及内存的分配;
    指变量的定义: int *a;
    内存的分配:使用malloc()函数;
    用法:指针自身 = (指针类型*)malloc(sizeof(指针类型)*数据数量)
  2. *returnSize = 2; //*returnSize 就代表返回大小,这里的返回大小就是我们要返回的二维数组的行数
  3. 求解思路:
    (1) 定义一个整形指针a,存储返回结果。
    (2)定义变量i,j,遍历数组。
    (3)当nums[i] + nums[j+1] == target时,使 a[0] = i,a[1] = j;
    代码实现:
    /**
     * Note: The returned array must be malloced, assume caller calls free().
     */
    int* twoSum(int* nums, int numsSize, int target, int* returnSize){
        /*
        int a    :一个int类型,名称叫a
        int* a:一个整形的指针,名称叫a
        int *a:一个指向整型的地址,名称叫a(一级指针,表示a所指向的地址里面存放的是一个int类型的值)
        int **a :二级指针,表示a所指向的地址里面存放的是一个指向int类型的指针(即a指向的地址里面存放的是一个指向int的一级指针)
        int & a:声明一个int引用类型,名称叫a
        */
        int *a = (int *)malloc(sizeof(int) * 2);  //定义指针变量a,并为其开普内存空间,创建一个大小为2的数组
        int i,j;
        for(int i = 0; i < numsSize - 1; i++){
            for(int j = i + 1; j < numsSize; j++){
                if(target == nums[i] + nums[j]){
                    a[0] = i;
                    a[1] = j;
                    *returnSize = 2; //*returnSize 就代表返回大小,这里的返回大小就是我们要返回的二维数组的行数
                    return a;
                }
            }
        }
        *returnSize = 0;
         return 0;
    }
    

9.回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
在这里插入图片描述

涉及到的知识点:

  1. 字符数组胡创建:char s[]20;
  2. 将int类型转换成字符串数组:sprintf函数sprintf(s," ",str)
    其中要:s:转换到的字符串数组 " ":“转换格式” ,str:被转的整形
    代码实现:
    1. 方法一:转换为字符串求解:
      bool isPalindrome(int x){
          if(x < 0 || x % 10 == 0 && x != 0){
              return false;
          }
      
          char s[20];
          sprintf(s, "%d", x);  
          for(int i = 0; i < strlen(s) / 2; i++){
              if(s[i] != s[strlen(s) - 1 - i]){
                  return false;
              }
          }
          return true;
      }
      

循环

1. do…while循环

语法格式:

do
{
   statement(s);

}while( condition );

条件表达式出现在循环的尾部,所以循环中的 statement(s) 会在条件被测试之前至少执行一次。
如果条件为真,控制流会跳转回上面的 do,然后重新执行循环中的 statement(s)。这个过程会不断重复,直到给定条件变为假为止。

流程图:
在这里插入图片描述
例题:用do-while计算水仙花(100到999之间各个位数的立方和等于本身数成为水仙花数):

#include<stdio.h>
/*
  计算1-100之和
int main(void){
    int i = 1;
    int sum = 0;
    
    do{
        sum = sum + i;
        i++;
    }while(i <=100);
    
    printf("sum=%d", sum);
    return 0;

}  */

int main(void){
    int i = 100;
    int a,b,c;
    do {
        /* code */
        a = i / 100;  //百位
        b = i / 10 % 10;  //十位
        c = i %10; //个位
        if (a * a * a + b * b * b + c * c * c == i){
            printf("水仙花树:%d\n",i);
        }
        i++;    
    } while (i <= 999);   
    return 0;
}

2. while循环

语法格式:

while(condition)
{
   statement(s);
}

condition 可以是任意的表达式,当为任意非零值时都为 true。当条件为 true 时执行循环。 当条件为 false 时,退出循环,程序流将继续执行紧接着循环的下一条语句

流程图:
在这里插入图片描述

while循环的do…whiile循环的区别:

  • while 循环首先检查循环条件,只有当条件为真时才执行循环体。
  • do while 循环首先执行循环体,然后检查循环条件。

存储类

存储类定义了C程序中变量/函数的存储位置、生命周期以及作用域。这些符号说明方式它们所修饰的类型之前。

C程序中可用的存储类包括:

  • auto
  • register
  • static
  • extem

auto存储类

auto存储类是所有局部变量默认的存储类,限定变量只能在函数内部使用;
定义在函数中的变量默认是 auto存储类,这意味着它们在函数开始时被创建,在函数结束时被销毁。

{
	//两种mount定义的含义相同
	int mount;
	auto int mount;
}

register存储类

register存储类用于定义存储在寄存器中而不是RAM中的局部变量。这就意味着变量的最大尺寸等于寄存器的大小,并且不能对它应用一元的“&”运算符。
register存储类定义存储在寄存器,所以变量的访问速度更快,但它不能直接取地址。因为它不是存储在RAM中的,在需要频繁访问的变量上使用register存储类可以提高程序的运行速度。

{
	register int miles;
}

寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

static存储类

static存储类是编译器在程序的生命周期内保持的局部变量的存在,而不需要在每次它进入和离开作用域时创建和销毁。因此,使用static修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。
静态变量在程序中只被初始化一次,即使函数被调用多次,该变量的值也不会重置。

实例演示了 static 修饰全局变量和局部变量的应用:

#include<stdio.h>

void func1(void);
static int count = 10;  //全局变量,static是默认的

int main(){
    while (count--)
    {
        func1();
    }
    return 0;
}

void func1(void){
    /* 
        'thingy' 是 'func1' 的局部变量 - 只初始化一次
        每次调用函数 'func1' 'thingy' 值不会被重置。
    */                
    static int thingy = 5;
    thingy++;
    printf("thingy为 %d, count为%d\n",thingy,count);
}

实例中 count 作为全局变量可以在函数内使用,thingy 使用 static 修饰后,不会在每次调用时重置。
在这里插入图片描述

extern 存储类

extern 存储类用于定义在其他文件中声明的全局变量或函数。当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义。
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示:
第一个文件:main.c

#include <stdio.h>
 
int count ;
extern void write_extern();
 
int main()
{
   count = 5;
   write_extern();
}

第二个文件:supprot.c

#include <stdio.h>
 
extern int count;
 
void write_extern(void)
{
   printf("count is %d\n", count);
}

在这里,第二个文件中的 extern 关键字用于声明已经在第一个文件 main.c 中定义的 count。现在 ,编译这两个文件,如下所示:

$ gcc main.c support.c

这会产生 a.out 可执行程序,当程序被执行时,它会产生下列结果:count is 5

运算符

逻辑运算符

运算符描述
&&称为逻辑与运算符。如果两个操作数都非零,则条件为真。
在这里插入图片描述称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。
称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

位运算符

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
在这里插入图片描述假设如果A=60,且B=13,以二进制格式表示为:
A=00111100 B=00001101
A&B = 00001100
A|B=00111101
A^B=00110001
~A=11000011
下表显示了 C 语言支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:
在这里插入图片描述

#include<stdio.h>

int main(){
    unsigned int a = 60; //无符号类型;
    unsigned int b = 13;
    int c = 0;

    c = a & b;//对两个操作数的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。
    printf("Line1 - c 的值是 %d\n",c);

    c = a | b;//对两个操作数的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。
    printf("Line2 - c 的值是 %d\n",c);
        
    c = a ^ b;//对两个操作数的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。
    printf("Line3 - c 的值是 %d\n",c);

    c = ~a; //对操作数的每一位执行逻辑取反操作,即将每一位的 0 变为 1,1 变为 0。
    printf("Line2 - c 的值是 %d\n",c);

    c = a << 2; //将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。
    printf("Line2 - c 的值是 %d\n",c);

    c = a >> 2; //将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。
    printf("Line2 - c 的值是 %d\n",c);
}

在这里插入图片描述

杂项运算符

下表列出了 C 语言支持的其他一些重要的运算符,包括 sizeof 和 ? :。
在这里插入图片描述
实例:请看下面的实例,了解 C 语言中所有可用的杂项运算符:

#include <stdio.h>
 
int main()
{
   int a = 4;
   short b;
   double c;
   int* ptr;
 
   /* sizeof 运算符实例 */
   printf("Line 1 - 变量 a 的大小 = %lu\n", sizeof(a) );
   printf("Line 2 - 变量 b 的大小 = %lu\n", sizeof(b) );
   printf("Line 3 - 变量 c 的大小 = %lu\n", sizeof(c) );
 
   /* & 和 * 运算符实例 */
   ptr = &a;    /* 'ptr' 现在包含 'a' 的地址 */
   printf("a 的值是 %d\n", a);
   printf("*ptr 是 %d\n", *ptr);
 
   /* 三元运算符实例 */
   a = 10;
   b = (a == 1) ? 20: 30;
   printf( "b 的值是 %d\n", b );
 
   b = (a == 10) ? 20: 30;
   printf( "b 的值是 %d\n", b );
}

在这里插入图片描述

作用域规则

任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。C 语言中有三个地方可以声明变量:
(1)在函数或块内部的局部变量;
(2)在所有函数外部的全局变量;
(3)在形式参数的函数参数定义中。

全局变量与局部变量在内存中的区别:

  • 全局变量保存在内存的全局存储区中,占用静态的存储单元;
  • 局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元。

数组

数据基础知识

1.声明数组:arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C 数据类型。

type arrayName [ arraySize ];

2.初始化数组:

double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};

3.获取数组长度:数组长度可以使用 sizeof 运算符来获取数组的长度

#include <stdio.h>

int main() {
    int array[] = {1, 2, 3, 4, 5};
    int length = sizeof(array) / sizeof(array[0]);  //计算数组长度

    printf("数组长度为: %d\n", length);
   
    return 0;
}

也可以使用宏定义定义数组长度,如:

#include <stdio.h>

#define LENGTH(array) (sizeof(array) / sizeof(array[0]))

int main() {
    int array[] = {1, 2, 3, 4, 5};
    int length = LENGTH(array);

    printf("数组长度为: %d\n", length);

    return 0;
}

二维数组

C语言支持多维数组,多维数组的声明一般形式如下:

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

多维数组中使用最多的是二维数组,一个二维数组,在本质上,是一个一维数组的列表。声明一个 x 行 y 列的二维整型数组,形式如下:

type arrayName [ x ][ y ];

实例:使用嵌套循环来处理二维数组。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(){

    /*
    // 二维数组初始化 
    int a[2][3] = {{1,2,3},{4,5,6}};

    for (int  i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%d ",a[i][j]);
        }
        
        printf("\n");
    }

    printf("二维数组大小:%d\n",sizeof(a[0]));
    */

    int arr[5][3];
    for (int  i = 0; i < 5; i++){
        for (int  j = 0; j < 3; j++){
            scanf("%d", &arr[i][j]);
        }
    }

    // for (int  i = 0; i < 5; i++){
    //     for (int  j = 0; j < 3; j++){
    //         printf("%d ", arr[i][j]);
    //     }
    //     printf("\n");
    // }
    // return 0;

    for (int  i = 0; i < 5; i++){
        int sum = 0;
        for (int  j = 0; j < 3; j++){
            sum += arr[i][j];
            // printf("%d ", arr[i][j]);
        }
        printf("第%d门功课的总成绩为:%d\t 平均成绩为:%d\n",i + 1, sum, sum / 5);
    }
    return 0;
}

传递数组给函数

在函数中传递一个一维数组作为参数,您必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地,您也可以传递一个多维数组作为形式参数。
方式1:形式参数是一个指针

void myFunction(int *param)
{
.
.
.
}

方式 2:形式参数是一个已定义大小的数组

void myFunction(int param[10])
{
.
.
.
}

方式 3:形式参数是一个未定义大小的数组

void myFunction(int param[])
{
.
.
.
}

实例:将数组作为参数,同时传递另外一个参数,根据所传参数,返回数组中元素的平均值

#include<stdio.h>

// 函数
double getAverage(int arr[], int size){
    int i;
    double avg;
    double sum;

    for (int i = 0; i < size; i++)
    {
        /* code */
        sum += arr[i];
    }

    avg = sum / size;

    return avg;
}

// 声明函数
double getAverage(int arr[], int size);

int main()
{
    int balance[5] = {1000, 2, 3, 17, 50};
    double avg;

    avg = getAverage(balance, 5);

    printf("平均数是:%f", avg);

    return 0;
}

enum(枚举)

枚举是C语言中的一种基本数据类型,用于定义一组具有离散值的常量(一组相关的常量),使得数据更简洁、更易读。
定义一个枚举类型,需要使用enum关键字,后面跟着枚举类型的名称,以及用大括号{}括起来的一组枚举常量。每一个枚举常量都可以用一个标识符来表示,也可以为它们指定一个整数值。如果没有指定,那么默认从0开始递增。

枚举语法定义格式为:

enum 枚举名 {枚举元素1,枚举元素2,……};

比如:一星期有 7 天,如果不用枚举,我们需要使用 #define 来为每个整数定义一个别名

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7

使用枚举的方式可以让代码更简洁:

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};

注意:第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。

枚举变量的定义

我们可以通过以下三种方式来定义枚举变量

1.先定义枚举类型,再定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

2.定义枚举类型的同时定义枚举变量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

3.省略枚举名称,直接定义枚举变量

enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

实例2:使用 for 来遍历枚举的元素

#include <stdio.h>
 
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
    // 遍历枚举元素
    for (day = MON; day <= SUN; day++) {
        printf("枚举元素:%d \n", day);
    }
}

实例3:枚举在 switch 中的使用

#include <stdio.h>
#include <stdlib.h>
int main()
{
 
    enum color { red=1, green, blue };
 
    enum  color favorite_color;
 
    /* 用户输入数字来选择颜色 */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    scanf("%u", &favorite_color);
 
    /* 输出结果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是红色");
        break;
    case green:
        printf("你喜欢的颜色是绿色");
        break;
    case blue:
        printf("你喜欢的颜色是蓝色");
        break;
    default:
        printf("你没有选择你喜欢的颜色");
    }
 
    return 0;
}

实例4:将整数转换为枚举

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
 
    enum day
    {
        saturday,
        sunday,
        monday,
        tuesday,
        wednesday,
        thursday,
        friday
    } workday;
 
    int a = 1;
    enum day weekend;
    weekend = ( enum day ) a;  //类型转换
    //weekend = a; //错误
    printf("weekend:%d",weekend);
    return 0;
}

指针

在32位操纵系统中,所有指针类型是4个字节大小
在32位操纵系统中,所有指针类型是8个字节大小

每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。
实例1:

#include <stdio.h>
 
int main ()
{
    int var_runoob = 10;
    int *p;              // 定义指针变量
    p = &var_runoob;
 
   printf("var_runoob 变量的地址: %p\n", p);
   return 0;
}

在这里插入图片描述

指针的定义

指针也就是内存地址,指针变量是用来存放内存地址的变量。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var_name;

type 是指针的基类型,它必须是一个有效的 C 数据类型,var_name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针
以下是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

如何使用指针

使用指针时会频繁进行以下几个操作:定义一个指针变量把变量地址赋值给指针、访问指针变量中可用地址的值
这些都是通过使用*来返回位于操作数所指地址的变量的值。
实例:

#include<stdio.h>

int main()
{
    int var  = 20; /*实际变量的声明*/
    int *ip; /*指针变量的声明*/

    ip = &var; /*在指针变量中存储var的地址*/
    printf("var变量的地址为:%p\n", &var);

    /*在指针变量中存储的地址*/
    printf("ip变量的地址为:%p\n", &ip);

    /*使用指针访问值*/
    printf("ip变量的值为:%d\n", *ip);

    return 0;
}

在这里插入图片描述

指针的算术运算

C 指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、–、+、-。

指针的每一次递增,它其实会指向下一个元素的存储单元。
指针的每一次递减,它都会指向前一个元素的存储单元。
指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。

递增一个指针

下面的程序递增变量指针,以便顺序访问数组中的每一个元素:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指针中的数组地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {
 
      printf("存储地址:var[%d] = %p\n", i, ptr );
      printf("存储值:var[%d] = %d\n", i, *ptr );
 
      /* 指向下一个位置 */
      ptr++;
   }
   return 0;
}

在这里插入图片描述

递减一个指针

对指针进行递减运算,即把值减去其数据类型的字节数

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指针中最后一个元素的地址 */
   ptr = &var[MAX-1];
   for ( i = MAX; i > 0; i--)
   {
 
      printf("存储地址:var[%d] = %p\n", i-1, ptr );
      printf("存储值:var[%d] = %d\n", i-1, *ptr );
 
      /* 指向下一个位置 */
      ptr--;
   }
   return 0;
}

指针数组

指向整数的指针数组的声明:

int *ptr[MAX];

ptr 声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针。下面的实例用到了三个整数,它们将存储在一个指针数组中,如下所示:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int i, *ptr[MAX];
 
   for ( i = 0; i < MAX; i++)
   {
      ptr[i] = &var[i]; /* 赋值为整数的地址 */
   }
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of var[%d] = %d\n", i, *ptr[i] );
   }
   return 0;
}

传递指针给函数

传递指针给函数:C 语言允许传递指针给函数,只需要简单地声明函数参数为指针类型即可。

#include <stdio.h>
 
/* 函数声明 */
double getAverage(int *arr, int size);
 
int main ()
{
   /* 带有 5 个元素的整型数组  */
   int balance[5] = {1000, 2, 3, 17, 50};
   double avg;
 
   /* 传递一个指向数组的指针作为参数 */
   avg = getAverage( balance, 5 ) ;
 
   /* 输出返回值  */
   printf("Average value is: %f\n", avg );
    
   return 0;
}

double getAverage(int *arr, int size)
{
  int    i, sum = 0;       
  double avg;          
 
  for (i = 0; i < size; ++i)
  {
    sum += arr[i];
  }
 
  avg = (double)sum / size;
 
  return avg;
}

函数指针

函数指针是指向函数的指针变量。
通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数
函数指针可以像一般函数一样,用于调用函数、传递参数。
函数指针变量的声明:

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型

以下实例声明了函数指针变量 p,指向函数 max:

#include <stdio.h>
 
int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函数指针 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("请输入三个数字:");
    scanf("%d %d %d", & a, & b, & c);
 
    /* 与直接调用函数等价,d = max(max(a, b), c) */
    d = p(p(a, b), c); 
 
    printf("最大的数字是: %d\n", d);
 
    return 0;
}

回调函数

函数指针变量可以作为某个函数的参数来使用,回调函数就是一个通过函数指针调用的函数
实例:
实例中的populate_array()函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。
实例中我们定义了回调函数 getNextRandomValue(),其返回一个随机数,它作为一个函数指针传递给populate_array()函数。populate_array()将调用10次回调函数,并将回调函数的返回值赋值给数组。

#include<stdio.h>
#include<stdlib.h>

void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i = 0; i < arraySize; i++)
    {
        /* code */
        array[i] = getNextValue();
    }
}

// 获取随机数
int getNextRandomValue(void){
    return rand();
}

int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for (int i = 0; i < 10; i++)
    {
        /* code */
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

字符串

在这里插入图片描述

结构体

结构体允许存储不同类型的数据项,结构体中的数据成员可以是基本类型数据(int,float,char等),也可以是其他的结构体类型、指针类型等;

定义结构

结构体定义了由关键字struct和结构体名组成,结构体名可以根据需要自行定义。
struct语句定义了一个包含多个成员的新的数据类型,struct语句的格式如下:

struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;

tag是结构体标签;member-list是标准的变量定义,比如 int i,或者 float f,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。
下面是声明 Book 结构的方式:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct 
{
    int a;
    char b;
    double c;
} s1;

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;

//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;

结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。

//此结构体的声明包含了其他的结构体
struct COMPLEX
{
    char string[100];
    struct SIMPLE a;
};

//此结构体的声明包含了指向自己类型的指针
struct NODE
{
    char string[100];
    struct NODE *next_node;
};

结构体变量的初始化

和其他数据类型一样,对结构体变量可以在定义式指定初始值。

#include<stdio.h>

struct Books
{
    /* data */
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
} book = {"C语言", "RUNOOB", "编程语言",123456};

int main()
{
    printf("title: %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
    return 0;
}

访问结构成员

为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。您可以使用 struct 关键字来定义结构类型的变量。下面的实例演示了结构的用法:

#include<string.h>
#include<stdio.h>

struct Books
{
    /* data */
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
};

int main(){
    struct Books Book1;    /* 声明 Book1,类型为 Books */
    struct Books Book2;

    /*Book1详述*/
    strcpy(Book1.title,"C语言");
    strcpy(Book1.author,"Nuha Ali");
    strcpy(Book1.subject, "C Programming Tutorial");
    Book1.book_id = 64523387;

    /*Book2详述*/
    strcpy(Book2.title,"Telecom Billing");
    strcpy(Book2.author,"Zara Ali");
    strcpy(Book2.subject, "Telecom Billing Tutorial");
    Book2.book_id = 42324756;

    /*输出Book1的信息*/
    printf( "Book 1 title : %s\n", Book2.title);
    printf( "Book 1 author : %s\n", Book2.author);
    printf( "Book 1 subject : %s\n", Book2.subject);
    printf( "Book 1 book_id : %d\n", Book2.book_id);

    printf("---------------------------\n");

    /*输出Book2的信息*/
    printf( "Book 2 title : %s\n", Book2.title);
    printf( "Book 2 author : %s\n", Book2.author);
    printf( "Book 2 subject : %s\n", Book2.subject);
    printf( "Book 2 book_id : %d\n", Book2.book_id);

    return 0;
}

指向结构的指针

定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:

struct Books *struct_pointer;

现在,可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,把 & 运算符放在结构名称的前面,如下所示:

struct_pointer = &Book1;

为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:

struct_pointer->title;

使用结构指针来将结构作为函数参数

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

/* 函数声明 */
void printBook( struct Books *book );
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 通过传 Book1 的地址来输出 Book1 信息 */
   printBook( &Book1 );

   /* 通过传 Book2 的地址来输出 Book2 信息 */
   printBook( &Book2 );

   return 0;
}
void printBook( struct Books *book )
{
   printf( "Book title : %s\n", book->title);
   printf( "Book author : %s\n", book->author);
   printf( "Book subject : %s\n", book->subject);
   printf( "Book book_id : %d\n", book->book_id);
}

c语言中->和.的区别

->前面放的是指针,而.前面跟的是结构体变量

参考文献:C语言教程|菜鸟教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值