C 语言(二)数组与字符串

C 语言(二)数组与字符串

1. 数组

所谓数组,就是一个集合,里面存放了相同类型的数据元素

特点1:数组中的每个数据元素都是相同的数据类型

特点2:数组是由连续的内存位置组成的

1541748375356

1.1 一维数组

  • 定义:

    // 伪代码
    数据类型 数组名 【数组长度】;
    数据类型 数组名 【数组长度】 = {值1,值2};
    数据类型 数组名 【数组长度】 = {值1,值2};
    
    // 规则
    数组名的命名规则和变量名的规则相同。
    在定义数组时, 需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
    常量表达式中可以包含常量和符号常量,但是不能包含变量,也就是说,C 语言不允许对数组的大小做动态定义,即数组的大小不依赖与程序运行中变量的值。
    

    上述的伪代码是数组常见的三种定义形式;

    • 方式一

      #include <stdio.h>
      #include <stdlib.h>
      
      int main() {
          // 定义方式一
          int score[10];  // 数组名 score , 数组中醉倒存放 10 个 int 形的数据;
      
          score[0] = 100; // 索引从  0 开始;
          score[1] = 10; // 索引从  0 开始;
          score[2] = 90; // 索引从  0 开始;
          //利用下标法输出
          printf("%d\n", score[0]);
          printf("%d\n", score[1]);
          printf("%d\n", score[2]);
          return 0;
      }
      

      image-20240802200339152

    • 方式二

      #include <stdio.h>
      #include <stdlib.h>
      
      int main() {
          // 定义方式二
           int score2[10]={1,2,3,};
           // 不足的 10 个数据, 剩余的位置自动用 0 填充;
           for(int i=0; i<10; i++){
               printf("%d\n",score2[i]);
           }
      }
      

      image-20240802200903614

    • 方式三

      #include <stdio.h>
      #include <stdlib.h>
      
      int main() {
      
          // 定义方式三
           int score3[]={1,2,3,};
           // 不足的 10 个数据, 剩余的位置自动用 0 填充;
           for(int i=0; i<3; i++){
               // 容易发生越界异常, 可以使用 sizeof(score3)/sizeof(int) 获取数组的长度;
               printf("%d\n",score3[i]);
           }
      }
      

      image-20240802210305105

1.2 一维数组的存储

语句int mark[100];定义的一维数组 mark在内存中的存放情况如下图所示,每个元素都是整型元素,占用 4 字节,数组元素的引用方式是数组名[下标],所以访问数组mark中的元素的方式是 mark[O1,mark[1..,markI99]。注意,没有元素mark[100],因为数组元素是从0开始编号的。

image-20240802212824380

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


//一维数组名称
void test02()
{
    int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    //1、统计整个数组占用内存空间大小
    printf("sizeof arr =  %d\n", sizeof(arr));
    // 每个数据占用空间大小
    printf("Size of space occupied by each data = %d\n", sizeof(arr[0]));
    // 数组中元素的个数
    printf("The number of elements in an array = %d\n", sizeof (arr) / sizeof(int));

    //2、通过数组的名称,获取到数组的首地址

    // 数组的首地址为
    printf("The first address of the array is :%d\n", arr);  //%p可以用十六进制显示  %d用十进制显示地址
    //printf("数组的首地址为:%p\n", arr);


    printf("The address of the first element in the array :%d\n", &arr[0]);
    printf("数组中第二个元素的地址: %d\n", &arr[1]);  // c 语言使用中文可能会乱码
    printf("数组中第三个元素的地址: %d\n", &arr[2]);


}


int main() {

    test02();
}

image-20240802213351188

1.3 数组的越界与传递

  • 数组越界

    下面借助一个数组的实例来掌握数组元素的赋值、访问越界.下例中给出了该例的全部代码。

    #include <stdio.h>
    
    int main() {
        int a[5] = {1, 2, 3, 4, 5};
        int j = 20;
        int i = 10;
        a[5] = 6; // 越界访问
        a[6] = 7;  // 越界访问会造成数据异常;
        printf("i=%d\n", i); // i 发生改变
        return 0;
    }
    

    在变量窗口中输入sizeof(a),可以看到数组a的大小为20字节,计算方法其实就是sizeof(int)*5: 数组中有 5 个整型元素,每个元素的大小为 4 字节,所以共有 20 字节。访问元素的顺序是依次从 a[0]到a[4]a[5]=6a[6]=7 均为访问越界。下图显示了代码运行情况,从中看出,执行到第 12 行时,变量 i 的值被修改了,这就是访问越界的危险性——未对变量 i 赋值,其值却发生了

    image-20240802220356376

    数组另一个值得关注的地方是,编译器并不检查程序对数组下标的引用是否在数组的合法 范围内。这种不加检查的行为有好处也有坏处,好处是不需要浪费时间对有些已知正确的数组下 标进行检查,坏处是这样做将无法检测出无效的下标引用。一个良好的经验法则是:如果下标值是通过那些已知正确的值计算得来的,那么就无须检查;如果下标值是由用用户输入的数据产生的,那么在使用它们之前就必须进行检查,以确保它们位于有效范围内。

    注意:C 语言中没有异常检测的机制,发生异常之后不会有提示,因此需要再程序编写中自己注意数组越界的异常。

  • 数组传递

    依旧通过代码来进行演示;

    //
    // Created by 86152 on 2024/8/2.
    //
    #include <stdio.h>
    
    
    // 一维数组在传递时,其长度是传递不过去的,所以我们通过 len 来传递数组中的元素个数;
    void func(int b[], int len){
        int i;
        for(i=0; i<len;i++){
            printf("%3d", b[i]);
        }
        b[4] = 20;
        printf("\n");
    }
    int main(){
        int a[5] = {1,2,3,4,5};
        func(a,5);
        printf("a[4]=%d\n", a[4]);
        return 0;
    }
    

    image-20240802222037266

    执行完成之后数组的元素发生了更改,在调用函数传递时,是将数组的首地址给了变量 b(其实变量 b 是指针类型),在 b[]的方括号中填写任何数字都是没有意义的。这时我们在 print 函数内修改元素 b[4]=20,可以看到数组 b 的 起始地址和 main 函数中数组 a 的起始地址相同,即二者在内存中位于同一位置,当函数执行结束时,数组 a 中的元素 a[4]就得到了修改。

1.4 数组的常见算法

  • 数组逆转

    需求:一个数组中包含了6个元素,元素为 { 1,3,5,2,4,6 } 将元素逆置并输出。

    (如原数组元素为:1,3,2,5,4;逆置后输出结果为:4,5,2,3,1);

    //
    // Created by 86152 on 2024/8/2.
    //
    #include <stdio.h>
    #include <stdlib.h>
    
    void inversion() {
        int arr[6] = {1, 2, 3, 4, 5, 6};
        printf("before :\n");
        for (int i = 0; i < sizeof(arr) / sizeof(int); i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
        // 逆置
        int start = 0;
        // 计算数组的长度,作为末尾的指针
        int end = sizeof(arr) / sizeof(int) - 1; // 长度减一获取索引;
        // 循环逆转
        while (start<end){
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] =temp;
            start++;
            end--;
        }
    
        printf("after :\n");
        for (int i = 0; i < sizeof(arr) / sizeof(int); i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
    }
    
    int main() {
        inversion();
    }
    

    image-20240802224836062

  • 冒泡排序

    作用: 最常用的排序算法,对数组内元素进行排序

    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
    3. 重复以上的步骤,每次比较次数-1,直到不需要比较

    示例: 将数组 { 4,2,8,0,5,7,1,3,9 } 进行升序排序

    void bubble_sort(int arr[], int len) {
        // 置换前打印
        printf("before :\n");
        for (int i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
        for (int i = 0; i < len - 1; i++) {
            for (int j = 0; j < len - i - 1; j++) {
                // 检测第二个数字是否比第一个数字大,
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    
        printf("after :\n");
        for (int i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
    }
    
    int main() {
        int arr[] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
        int len = sizeof(arr) / sizeof(int) - 1;
        bubble_sort(arr, len);
    }
    

    image-20240802230057363

1.5 二维数组

二维数组的定义的四种方式

// 伪代码
数据类型 数组名【行数】【列数】;
数据类型 数组名【行数】【列数】= {{数据1,数据2},{数据3,数据4}};
数据类型 数组名【行数】【列数】= {数据1,数据2,数据3,数据4};
数据类型  数组名[  ][ 列数 ] = { 数据1,数据2,数据3,数据4}

以上四种定义方式,一般使用第二种方式,提高代码的可读性

//
// Created by 86152 on 2024/8/3.
//
// 二维数组

#include <stdio.h>

void test01(){
    int arr[2][3];
    // 使用索引进行赋值;
    arr[0][0] = 1;
    arr[0][1] = 2;
    arr[0][2] = 3;
    arr[1][0] = 4;
    arr[1][1] = 5;
    arr[1][2] = 6;

    // 使用循环遍历打印
    for(int i=0; i<2; i++){
        for(int j=0;j<3;j++){
            printf("%d ", arr[i][j]);
        }
        printf("\n");  // 换行打印;
    }

}

int main(){
    test01();
    return 0;
}

image-20240803220103063

void test02(){
    // 使用方式二进行声明;
    int arr[2][3] = {
            {1,2,3},
            {4,5,6}
    };
    // 使用循环遍历打印
    for(int i=0; i<2; i++){
        for(int j=0;j<3;j++){
            printf("%d ", arr[i][j]);
        }
        printf("\n");  // 换行打印;
    }

}


int main(){
    test02();
    return 0;
}

image-20240803220136090

void test03(){
    int arr[2][3] = { 1, 2, 3, 4, 5, 6 }; //本质也是一个一维数组,地址也是连续
    // 使用循环遍历打印
    for(int i=0; i<2; i++){
        for(int j=0;j<3;j++){
            printf("%d ", arr[i][j]);
        }
        printf("\n");  // 换行打印;
    }
}


int main(){
    test03();
    return 0;
}

image-20240803220434754

void test04(){
    int arr[][3] = { 1, 2, 3, 4, 5, 6 ,7};  //行数可以省略
    for (int i = 0; i < 3; i++)
    {
        //内层循环
        for (int j = 0; j < 3; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

int main(){
    test04();
    return 0;
}

image-20240803221553888

总结:在定义二维数组时,如果初始化了数据,可以省略行数

1.6 二维数组存储

void test05(){
    int arr[2][3] = {
            { 1, 2, 3 },
            { 4, 5, 6 },
    };

    //可以查看整个数组占用内存空间大小
    printf("The space occupied by the two-dimensional array is %d\n", sizeof(arr));
    printf("The space occupied by each row in a two-dimensional array is%d\n", sizeof(arr[0])); //12
    printf("二维数组每个元素占用空间为%d\n", sizeof(arr[0][0])); // 4
    // 查看行数列数
    printf("二维数组行数:%d\n", sizeof(arr) / sizeof(arr[0]));
    printf("二维数组列数:%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));

    //可以查看二维数组首地址
    printf("二维数组首地址 %d\n", arr);
    printf("二维数组第一行地址 %d\n", arr[0]);
    printf("二维数组第二行地址 %d\n", arr[1]);

    printf("第一个元素的地址:%d\n", &arr[0][0]);
    printf("第二个元素的地址:%d\n", &arr[0][1]);

}

int main(){
    test05();
    return 0;
}

image-20240803222200710

总结1:二维数组名就是这个数组的首地址

总结2:对二维数组名进行sizeof时,可以获取整个二维数组占用的内存空间大小

  • 应用案例

    考试成绩统计:

    案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的总成绩

    语文 数学 英语
    张三 100 100 100
    李四 90 50 100
    王五 60 70 80
    void test06() {
        int scores[3][3] = {
            {100, 100, 100},  //第一个人考试成绩
            {90,  50,  80},  //第二个人考试成绩
            {60,  70,  80},  //第三个人考试成绩
        };
    
        int row = sizeof(scores) / sizeof(scores[0]);
        int col = sizeof(scores[0]) / sizeof(scores[0][0]);
        for (int i = 0; i < row; i++)
        {
            int sum = 0;
            for (int j = 0; j < col; j++)
            {
                sum += scores[i][j];
            }
            printf("This %d student sum score %d\n", i + 1, sum);
        }
    }
    
    int main() {
        test06();
        return 0;
    }
    

    image-20240803223416573

2. 字符串

2.1 字符数组

字符数组是一个存储字符的数组,它可以包含任意数量的字符,包括空字符(null terminator,ASCII码为0)。字符数组在C语言中用方括号[]定义,例如:

char charArray[10];
// 这个数组可以存储最多10个字符,包括最后一个空字符'\0',用来标记数组的结束。

示例

//
// Created by 86152 on 2024/8/4.
//
#include <stdio.h>
//字符数组定义方式
void test01() {
    char ch[5]; //声明字符数组 ,每个元素是 char类型,一共有5个元素
    printf("sizeof = %d\n", sizeof(ch));
}

//操作字符数组
void test02()
{
    //逐个初始化字符数组
    char arr[5] = { 'h','e','l','l','o' }; //error,因为没有
    printf("%s\n", arr);
}

int main() {
    test01();
    test02();
}

image-20240804092653573

打印的时候出现乱码,因为字符数组中没有结尾空字符的位置;

void test02()
{
    //逐个初始化字符数组
    char arr[6] = { 'h','e','l','l','o' }; // \0本质就是0


    printf("%s\n", arr);
}

int main() {
    test01();
    test02();
}

image-20240804092851831

成功打印出结果;

void test02()
{
    char arr[6] = "hello"; //自动在字符串后面加 \0
    //遍历字符数组
    for (int i = 0; i < sizeof(arr) / sizeof(char); i++)
    {
    	printf("%c\n", arr[i]);
    }
    printf("\n");


    printf("%s\n", arr);
}

int main() {
    test02();
}

image-20240804093242879

成功打印出结果;

字符串(String)

字符串实际上是以空字符(null terminator)结尾的字符数组。在C语言中,字符串通常用双引号定义,

例如:

char str[] = "Hello, World!";

这个字符串包含了12个字符(包括空格),最后一个字符是一个空字符,用来告诉C语言这个字符串的结束位置。

字符串与字符数组的区别

  • 定义方式:字符数组通常用方括号定义,而字符串用双引号定义。

  • 结束标记:字符串必须以空字符结尾,而字符数组不一定需要。

  • 长度:字符串的长度是自动计算的,不包括空字符;字符数组的长度是在定义时指定的,包括空字符。

  • 用途:字符串通常用于存储文本信息,而字符数组可以用于更广泛的用途,包括存储任意字符数据。

2.2 字符串操作

C语言提供了一些标准库函数来操作字符串,如strcpy, strcat, strlen, strcmp等。这些函数都假设字符串以空字符结尾。

2.2.1 strcpy 与 strncpy

复制字符串;

char *strcpy(char *dest, const char *src);

功能:src所指向的字符串复制到dest所指向的空间中,'\0'也会拷贝过去

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

void test03(){
    char charArray[10] = {'H', 'e', 'l', 'l', 'o', '\0'};
    char str[] = "Hello";

    printf("Character Array: %s\n", charArray);
    printf("String: %s\n", str);

    // 字符串操作示例
    char copyStr[10];
    strcpy(copyStr, str); // 复制字符串
    printf("Copied String: %s\n", copyStr);
}

int main() {
//    test01();
//    test02();
    test03();
}

在这个示例中,我们定义了一个字符数组和一个字符串,然后使用printf函数打印它们。我们还使用strcpy函数复制了字符串。注意,字符数组charArray中我们手动添加了空字符,而字符串str在定义时自动添加了空字符。

image-20240804094409034

strncpy

复制指定个数的字符;

功能:把src指向字符串的前n个字符复制到dest所指向的空间中,是否拷贝结束符看指定的长度是否包含'\0'

返回值:

​ 成功:返回 dest 字符串的首地址,因为数组打印的时候返回的是首地址。

​ 失败:NULL

#include <string.h>
void test04(){
    char buf[64] = { 0 };

    strncpy(buf, "hello world", 8);

    printf("buf = %s\n", buf);

    char buf2[64] = { 0 };
    strncpy(buf2, "hello\0world", 8);  //遇到\0结束拷贝
    printf("buf2 = %s\n", buf2); //hello
}

int main() {
    test04();
}

image-20240804095418506

2.2.2 strcat

在C语言中,strcat函数用于将一个字符串追加到另一个字符串的末尾。它是一个字符串处理函数,是C标准库中的一部分,定义在<string.h>头文件中。

函数原型

char *strcat(char *dest, const char *src);

参数说明

  • dest:指向目标字符串的指针,该字符串将被追加。
  • src:指向源字符串的指针,该字符串将被追加到目标字符串的末尾。

返回值

strcat函数返回指向目标字符串的指针。

注意事项

  • 使用strcat函数时,需要确保目标字符串有足够的空间来容纳源字符串,包括源字符串的结束字符'\0'。如果目标字符串空间不足,将会导致缓冲区溢出,这是C语言中常见的安全问题之一。
  • strcat函数会覆盖目标字符串的结束字符'\0',然后将源字符串的内容复制到目标字符串之后。
#include <stdio.h>
#include <string.h>

void test07(){
    char str1[20] = "Hello, ";  // 设置一个较长的字符数组
    char str2[] = "World";
    strcat(str1, str2);  // 拼接到后方;
    printf("Concatenated String : %s \n", str1);

}

int main() {
    test07();
}

image-20240805082718366

2.2.3 strlen

strlen 函数是C语言标准库函数之一,用于计算字符串的长度,但不包括字符串末尾的空字符(null terminator)。下面是使用 strlen 函数的一个示例:

void test06(){
    // 定义一个字符串
    char myString[] = "Hello, World!";
    size_t length = strlen(myString);

    // 打印字符串长度;
    printf("The length of the string \"%s\" is : %zu\n", myString, length);
}
int main() {
    test06();
}

image-20240804104429951

在这个示例中,myString 是一个字符数组,它包含了一个字符串 "Hello, World!"。我们使用 strlen 函数来计算这个字符串的长度,并将结果存储在 length 变量中。然后,我们使用 printf 函数打印出字符串及其长度。

请注意,strlen 函数返回的类型是 size_t,这是一个无符号整数类型,通常用于表示大小和长度。在 printf 函数中,我们使用 %zu 格式说明符来打印 size_t 类型的值。

2.2.4 strcmp 与 strncmp

strcmp

int strcmp(const char *s1, const char *s2);

功能:比较 s1 和 s2 的大小,比较的是字符ASCII码大小

返回值:

​ 相等:=0,如果str1等于str2,则返回0。

​ 大于:>0,如果str1大于str2,则返回大于0的值。

​ 小于:<0,如果str1小于str2,则返回小于0的值。

注意事项

  • strcmp函数在比较时是区分大小写的。
  • 比较操作会在遇到任一字符串的终止字符'\0'时停止。
#include <stdio.h>
#include <string.h>

void test05() {
    char str1[] = "Apple";
    char str2[] = "apple";
    char str3[] = "Apple";
    // 比较str1和str2
    int result1 = strcmp(str1, str2);
    if (result1 == 0) {
        printf("str1 and str2 are equal.\n");
    } else {
        printf("str1 and str2 are different.\n");
    }

    // 比较str1和str3
    int result2 = strcmp(str1, str3);
    if (result2 == 0) {
        printf("str1 and str3 are equal.\n");
    } else {
        printf("str1 and str3 are different.\n");
    }
}

int main() {
    test05();
}

image-20240805083942410

strncmp

C 语言中的strncmp函数用于比较两个字符串的前n个字符。它是 C 标准库中的一部分,定义在<string.h>头文件中。

函数原型

int strncmp(const char *str1, const char *str2, size_t n);

参数说明

  • str1:指向第一个字符串的指针。
  • str2:指向第二个字符串的指针。
  • n:要比较的字符数。

返回值

  • 如果str1小于str2,则返回小于0的值。
  • 如果str1等于str2,则返回0。
  • 如果str1大于str2,则返回大于0的值。

注意事项

  • strncmp函数在比较时是区分大小写的。
  • 如果n大于任一字符串的长度,则strncmp会一直比较到遇到字符串的终止字符'\0'为止。
  • 如果n为0,strncmp会立即返回0。

示例代码

void test08(){
    char str1[] = "HelLo";
    char str2[] = "hello";
    // 比较str1和str2的前5个字符
    int result = strncmp(str1, str2, 5);

    if (result == 0) {
        printf("The first 5 characters of both strings are equal.\n");
    } else {
        printf("The first 5 characters of the strings are different.\n");
    }
}


int main() {
    test08();
}

image-20240805085243297

在这个示例中,strncmp比较了str1str2的前5个字符,由于第一个字符Hh不同,所以返回了非零值,表示它们不相同。

2.2.5 sprintf
int sprintf(char *str, const char *format, ...);

功能:根据参数format字符串来转换并格式化数据,然后将结果输出到str指定的空间中;

返回值:

​ 成功:实际格式化的字符个数

​ 失败: - 1

void test09(){
    char buf[64] = { 0 };
    sprintf(buf, "hello world");
    printf("buf = %s\n", buf);
}

int main() {
    test09();
}

image-20240805094919530

2.2.6 sscanf

特别注意区分与输入函数 scan 不同

int sscanf(const char *str, const char *format, ...);

功能:从str指定的字符串读取数据,并根据参数format字符串来转换并格式化数据

返回值:

成功:成功转换的值的个数

失败: - 1

void test10()
{
    char msg[1024] = "phone:13690000000;2019/5/20;It's time to repay the money";

    unsigned long long phone = 0;
    int year = 0;
    int month = 0;
    int day = 0;
    char content[64] = { 0 };
	
    // 从字符串中提取指定的位置提取信息;
    // 遇见空格的时候好像会结束;
    int num =sscanf(msg, "phone:%llu;%d/%d/%d;%s", &phone, &year, &month, &day, content);

    printf("%llu\n", phone);
    printf("%d\n", year);
    printf("%d\n", month);
    printf("%d\n", day);
    printf("%s\n", content);

    printf("%d\n", num);  // 打印指定的个数
}

int main() {
    test10();
}

image-20240805101315069

sscanf扩展

格式化分割字符串的时候,可以通过一些特殊格式实现不同拆分;类似正则不在演示;

格式 作用
%*s 或 %*d 忽略数据
%[w]s 读n个宽度的数据
%[a - z] 匹配a到z中任意字符
%[aBc] 匹配指定的a、B、c
%[^a] 匹配非a的任意字符
%[^a-z] 匹配非 a - z 的所有字符
2.2.7 strchr

strchr 函数原型:

char *strchr(const char *s, char c);

返回值:

​ 成功:返回第一次出现的c地址

​ 失败:NULL

功能:在字符串s中查找字母c出现的位置

void test11(){
    char str[1024] = "zhangtao@sina.com";

    char* ret = strchr(str, '@');

    if (ret == NULL)
    {
        printf("not exist @ char \n");
    }
    else
    {
        printf("Excites @ char, location in %d\n", ret - str);
    }
}

int main() {
    test11();
}

image-20240805102653703

2.2.8 strstr
char *strstr(const char *s, const char *s2);

功能:在字符串s中查找字符串s2出现的位置

返回值:

​ 成功:返回第一次出现的s2地址

​ 失败:NULL

void test12() {
    char src[] = "ddddabcd123abcd333abcd";
    char *p = strstr(src, "abcd");
    if (p == NULL) {
        printf("没有找到目标字符串\n");
    } else {
        printf("找到了目标字符串\n");
        printf("p = %s\n", p);
    }
}

int main() {
    test12();
}

image-20240805103027330

2.2.9 strtok
char strtok(char *str, const char *dst);

功能:

  • 将字符串分割成一个个片段。
  • strtok()在参数str的字符串中发现参数dst中包含的分割字符时, 则会将该字符改为\0 字符
  • 当连续出现多个时只替换第一个为\0
  • 第一次需要填入参数str,之后str中填入NULL即可

返回值:

​ 成功:分割后字符串首地址

​ 失败:NULL

void test13(){
    char buf[1024] = "a:b:c:d:e:f";

    char* names[64] = { 0 }; //将buf中的信息按照:分割,放入到字符串数组names中

    int i = 0;
    names[i] = strtok(buf, ":");

    while ( names[i] != NULL)
    {
        i++;
        names[i] = strtok(NULL, ":");
    }

    //遍历字符串数组
    i = 0;
    while (names[i] != NULL)
    {
        printf("%s\n", names[i++]);
    }
}

int main() {
    test13();
}

image-20240805103431436

2.2.10 atoi
int atoi(const char *nptr);

功能:atoi()会扫描nptr字符串,跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字'\0'才结束转换,并将结果返回。

返回值:

​ 成功转换后整数

类似的函数有:

  • atof():把一个小数形式的字符串转化为一个浮点数。

  • atol():将一个字符串转化为long类型

  • atoll():将一个字符串转化为long long类型

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

void test14(){
    char buf[1024] = "  123abc";

    int num = 0;

    num = atoi(buf);

    printf("%d\n", num);
}

int main() {
    test14();
}

image-20240805103826128

2.2.11 常见函数功能总结
函数 功能
gets() 获取可带空格的字符串
fgets() 获取可带空格的字符串(安全)
puts() 向屏幕输出字符串(自带换行)
fputs() 向屏幕输出字符串(不带换行)
strlen() 统计字符个数(\0结束统计)
strcpy() 字符串拷贝
strncpy() 字符串拷贝(拷贝n个字符)
strcat() 字符串拼接
strncat() 字符串拼接(拼接n个字符)
strcmp() 字符串对比
strncmp() 字符串对比(对比n个字符)
sprintf() 格式化拼接字符串
sscanf() 格式化拆分字符串
strchr() 查找字符
strstr() 查找字符串
strtok 分割字符串
atoi() 字符串转整数

度过大难,终有大成。

继续努力,终成大器。

posted @ 2024-08-05 10:40  紫青宝剑  阅读(70)  评论(0编辑  收藏  举报