《C语言高级》(一) ------ 数组与字符串 篇

目录

一、数组

1.1、创建数组

1.2、打印12个月的天数

1.3、多维数组

1.4、冒泡排序

1.5、斐波那契数列解法其二

1.6、打家劫舍(力扣)

二、字符串

2.1、字符串的创建与使用

2.2、scanf、gets、puts函数

2.3、回文串判断

2.4、字符串匹配(暴力解法)

2.5、字符串匹配(KMP算法)


一、数组

存放数据的一个组,所有的数据都统一存放在这一个组中,一个数组可以同时存放多个数据。保存在数组中的数据,称为“元素

1.1、创建数组

创建数组的方式有很多种

int a[10];   //直接声明int数据类型,容量为10

int b[10]  = {1, 2, 3};  //声明后,可以赋值初始值,使用{}囊括,不一定需要让10个位置都有初始值,比如这里仅仅是为前三个设定了初始值,注意,跟变量一样,如果不设定初始值,数组内的数据并不一定都是0

int c[10] = {1, 2, [4] = 777,  [9] = 666};  //我们也可以通过[下标]  = 的形式来指定某一位的初始值。注意下标是从0开始的,第一个元素就是第0个下标位置,比如这里数组容量为10,那么最多到9

int c[] = {1, 2, 3};  //也可以根据后面的赋值来决定数组长度

基本类型都可以声明数组:

#include <stdio.h>

int main() {
    
    char str[] = {'A', 'B', 'C'};  //多个字符
    char str2[] = "ABC";   //实际上字符串就是多个字符的数组形式

}

1.2、打印12个月的天数

比如现在需要打印12个月的天数

# include <stdio.h>
int main(){
    int arr[12] = {31,28,31, 30, 31,  30, 31, 30, 31,  30, 31, 30};
    for(int i=0; i< 12; i++){
        int days = arr[i];
        printf("%d月的天数是%d天\n", (i+1), days);
    }
}

同样的,我们也可以对数组中的值进行修改

# include <stdio.h>

int main() {
    
    int arr[] = {666, 777, 888};
    arr[1] = 999;  //让第二个元素的值变为999
    printf("%d", arr[1]);
}

 现在要求将低于31天的月份修改为0

# include <stdio.h>
int main(){
    int arr[12] = {31,28,31, 30, 31,  30, 31, 30, 31,  30, 31, 30};
    for(int i=0; i< 12; i++){
        if(arr[i] < 31){
            arr[i] = 0;

        };
    printf("%d月的天数是%d天 \n", (i+1), arr[i]);
//        printf("%d月的天数是%d天\n", (i+1), days);
    }
}

1.3、多维数组

数组不仅仅只可以有一个维度,我们可以创建二维甚至多维的数组,简单来说就是,存放数组的数组。

int main(){
    int arr[3][12] = {{31,28,31, 30, 31,  30, 31, 30, 31,  30, 31, 30},
                      {31,28,31, 30, 31,  30, 31, 30, 31,  30, 31, 30},
                      {31,28,31, 30, 31,  30, 31, 30, 31,  30, 31, 30}};
    printf("%d", arr[1][2]);
};

1.4、冒泡排序

现在有一个int数组,但是数组内的数据是打乱的,现在请你通过C语言,实现将数组中的数据按从小到大的顺序进行排序:

冒泡排序的核心思想是:

假设数组长度为N;

进行N轮循环,每次循环都选出一个最大的数放到后面;

每次循环中,从第一个数开始,让其与后面的数两两比较,如果更大,就交换位置,如果更小,就不动。

# include<stdio.h>
int main(){
    int arr[10] = {3,5,7,2,9,0,6,1,8,4};
    int mid;
    for (int i = 0; i < 10; ++i) {
        for (int j = i+1; j < 10; ++j) {
            if(arr[i] > arr[j]){
                mid = arr[i];
                arr[i] = arr[j];
                arr[j] = mid;
            } else continue;
        }
    }
    for (int i = 0; i < 10; ++i) {
        printf("数组中第%d个数为%d \n", i, arr[i]);
    }
};

1.5、斐波那契数列解法其二

学习过数组,我们就可以利用数组来计算斐波那契数列,这里可以采用动态规划的思想

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优解的值。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

我们可以在一开始创建一个数组,然后从最开始的条件不断向后推导

# include<stdio.h>
int main() {
    int target = 8;
    int arr[target];
    arr[0] = 1;
    arr[1] = 1;
    for (int i = 2; i < target; ++i) {
        arr[i] = arr[i-1] + arr[i-2];
    }
    printf("%d", arr[target-1]);
}

1.6、打家劫舍(力扣)

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你不触动警报装置的情况下,一夜之内能够偷窃到的最高金额。

实例1:

输入:[1, 2, 3, 1]

输出:4

解释:偷窃1号房屋(金额 = 1),然后偷窃3号房屋(金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4。

实例2:

输入:[2, 7, 9, 3, 1]

输出:12

解释:偷窃1号房屋(金额=2),偷窃3号房屋(金额=9),接着偷窃5号房屋(金额=1)。偷窃到的最高金额 = 2 + 9 + 1 = 12

# include<stdio.h>
int main() {
    int target = 5;
    int result;
    int dp[target];
    int arr[] = {2, 7, 9, 3, 1};
    dp[0] = arr[0];
    dp[1] = arr[1] > arr[0] ? arr[1] : arr[0];
    for (int i = 2; i < target; ++i) {
        dp[i] = dp[i-1] > dp[i-2]+arr[i] ? dp[i-1]:dp[i-2]+arr[i];
    }
    result = dp[target-1];
    printf("%d", result);
    printf("\n");
    for (int i = 0; i < target; ++i) {
        printf("%d \t", dp[i]);
    }
}

第一步:假设现在只有 [2] 这一个房屋,那么我们只能去偷一号房。

第二步:假设现在有 [2, 7] 两个房屋,我们需要比较 2 和 7 ,去选择偷钱多的那一间房。

第三步:假设现在有 [2, 7, 9] 三间房屋,我们需要比较是先偷一号房再偷三号房,还是直接偷二号房。

所以有如下递推关系

dp[i] = max(dp[i - 1], dp[i - 2] + arr[i])

二、字符串

对于字符类型的数组,比较特殊,它实际上可以作为一个字符串(String)表示,字符串就是一个或多个字符的序列,比如我们在一开始认识的 “hello world”,像这样的多个字符形成的一连串数据,就是一个字符串,而printf函数接收的第一个参数也是字符串

2.1、字符串的创建与使用

在c语言中并没有直接提供存储字符串的类型,我们熟知的能够存储字符的只有char类型,但是它只能存储单个字符,而一连串的字符想要通过变量进行保存,就只能依靠数组。

    //直接保存单个字符,字符串末尾必须添加一个'\0'表示结束
    char str[] = {'H','e','l','l','o','\0'}; 
    //用%s来作为一个字符串输出
    printf("%s", str); 
    char str[] = "Hello";
    printf("%s", str);

2.2、scanf、gets、puts函数

前面我们认识了printf函数,实际上这个函数就是用于打印字符串到控制台,我们只需要填入一个字符串和后续的参数即可。

#include<stdio.h>
int main() {
    
    const char str[] = "hello world";
    printf(str);

}

现在我们知道该如何输出,那么输入该如何实现呢,比如我们现在希望将我们想要说的话告诉程序,让程序从控制台读取我们输入的内容,这时候我们就需要用到scanf函数

# include<stdio.h>
int main() {
    char str[10];
    // 用scanf函数来接受控制台输入,并将输入的结果按照格式,分配给后续的变量
    scanf("%s", str);
    printf("%s", str);
}

除了扫描字符串之外,我们也可以直接扫描数字

# include<stdio.h>
int main() {
    int a,b;
    scanf("%d", &a);
    scanf("%d", &b); //对于不是数组类型的数,在填写变量时要在前面添加一个&符号
    printf("a + b = %d", a + b);
}

除了使用scanf之外,我们也可以使用字符串专用的函数来接受字符串类型的输入和输出:

# include<stdio.h>
int main() {
    char str[10];
    gets(str);
    puts(str);
}

当然也有专门用于字符输入输出的函数:

# include<stdio.h>
int main() {
    int c = getchar();
    putchar(c);
}

2.3、回文串判断

“回文串”是一个正读和反读都一样的字符串,请你实现一个C语言程序,判断用户输入的字符串(仅出现英文字符)是否为“回文”串。

ABA就是一个回文串,因为正读反读都是一样的

ABCA就不是一个回文串,因为反着读不一样

# include<stdio.h>
# include<string.h>
int main() {
    char str[64];
    scanf("%s", str);
    int len = strlen(str); //字符串长度
    int left=0, right=len-1;
    _Bool flag = 1;
    while (left < right) {
        if(str[left] != str[right]){
            flag = 0;
            break;
        }
        left++;
        right--;
    }
    flag ? printf("yes") : printf("no");

}

2.4、字符串匹配(暴力解法)

现在有两个字符串:

str1 = "abcdabbc"

str2 = "cda"

现在请你设计一个C语言程序,判断第一个字符串中是否包含了第二个字符串,比如上面的例子中,很明显第一个字符串包含了第二个字符串

# include<stdio.h>
# include<string.h>
int main() {
    char str1[64];
    char str2[64];
    _Bool flag = 0;
    gets(str1);
    gets(str2);
    int len1 = strlen(str1);
    int len2 = strlen(str2);
    for (int i = 0; i < len1; ++i) {
        for (int j = 0; j < len2; ++j) {
            if(str1[i + j] != str2[j]){
                flag = 1;
                break;
            }
        }
        if(!flag) break;          
    }
    puts(flag?"不包含":"包含");
    }

2.5、字符串匹配(KMP算法)

暴力解法虽然比较好理解,但可能会做一些无意义的比较

如果不匹配的位置发生在第三个字符,而前面是a,b两个字符都匹配,显然完全没有必要再继续挨着去比较a和b,因为很明显不可能匹配。

当拿到子串时,就需要根据子串来计算一个叫做next的数组,与子串的长度相同,它存储了当不匹配发生在对应的位置上时,应该在哪一个位置开始继续比较。

KMP算法:

从第一位开始依次推导。

next数组的第一位一定是0。

从第二位开始(用i表示),将第i-1个字符(也就是前一个)与其对应的 next[i-1]-1 位上的字符进行比较。

如果相等,那么next[i]位置的值就是next[i - 1] + 1

如果不相等,则继续向前计算一次next[next[i-1] - 1] - 1 位置上的字符和第 i - 1 个字符是否相同,直到找到相等的为止,并且这个位置对应的值加上1就是next[i]的值了,如果都已经到头了都没遇到相等的,那么next[i] 直接等于 1 

# include<stdio.h>
# include<string.h>
int main() {
    char str1[] = "abababcabb";
    char str2[] = "ababc";

    int len1 = strlen(str1), len2 = strlen(str2);
    int next[len2];
    next[0] = 0;

    for (int i = 1; i < len2; ++i) {
        int j = i - 1;
        while (1) {
            if (next[j] == 0 || str2[i - 1] == str2[next[j] - 1]) {
                next[i] = next[j] + 1;
                break;
            }
            j = next[j] - 1;
        }
    }
    for (int i = 0; i < len2; ++i) {
        printf("%d", next[i]);
    }

    int i = 0, j = 0;
    while (i < len1) {
        if (str1[i] == str2[j]) {
            i++;
            j++;
        } else {
            if (j == 0) {
                i++;
                j++;
            } else {
                j = next[j] - 1;
            }
        }
        if(j == len2) break;
        }
    printf(j == len2 ? "yes" : "no");
    }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. C 语言中的指针和内存泄漏 ............................................................................................................. 5 2. C语言难点分析整理 .......................................................................................................................... 9 3. C语言难点 ........................................................................................................................................ 16 4. C/C++实现冒泡排序算法 ................................................................................................................. 29 5. C++中指针和引用的区别 ................................................................................................................. 31 6. const char*, char const*, char*const的区别 ..................................................................................... 32 7. C中可变参数函数实现 .................................................................................................................... 34 8. C程序内存中组成部分 .................................................................................................................... 37 9. C编程拾粹 ........................................................................................................................................ 38 10. C语言中实现数组的动态增长 .................................................................................................... 40 11. C语言中的位运算 ........................................................................................................................ 41 12. 浮点数的存储格式: .................................................................................................................... 45 13. 位域 ................................................................................................................................................ 52 14. C语言函数二维数组传递方法 .................................................................................................... 58 15. C语言复杂表达式的执行步骤 .................................................................................................... 60 16. C语言字符串函数大全 ................................................................................................................ 62 17. C语言宏定义技巧 ........................................................................................................................ 80 18. C语言实现动态数组 .................................................................................................................... 89 19. C语言笔试-运算符和表达式 ....................................................................................................... 93 20. C语言编程准则之稳定 ............................................................................................................ 96 21. C语言编程常见问题分析 ............................................................................................................ 97 22. C语言编程易犯毛病集合 .......................................................................................................... 101 23. C语言缺陷与陷阱(笔记) ............................................................................................................ 107 24. C语言防止缓冲区溢出方法 .......................................................................................................113 25. C语言高效编程秘籍 ...................................................................................................................115 26. C运算符优先级口诀 ...................................................................................................................119 27. do/while(0)的妙用 ....................................................................................................................... 120 28. exit()和return()的区别 ................................................................................................................ 125 29. exit子程序终止函数与return的差别 ........................................................................................ 126 30. extern与static存储空间矛盾 ..................................................................................................... 130 31. PC-Lint与C\C++代码质量 ........................................................................................................ 132 32. spirntf函数使用大全................................................................................................................... 142 33. 二叉树的数据结构 ...................................................................................................................... 150 34. 位运算应用口诀和实例 .............................................................................................................. 153 35. 内存对齐与ANSI C中struct内存布局 .................................................................................... 156 36. 冒泡和选择排序实现 .................................................................................................................. 162 37. 函数指针数组与返回数组指针的函数 ...................................................................................... 168 38. 右左法则- 复杂指针解析 ........................................................................................................... 170 39. 回车和换行的区别 ...................................................................................................................... 173 40. 堆和堆栈的区别 .......................................................................................................................... 175 41. 堆和堆栈的区别 .......................................................................................................................... 178 42. 如何写出专业的C头文件 ......................................................................................................... 181 43. 打造最快的Hash表 .................................................................................................................... 185 44. 指针与数组学习笔记 .................................................................................................................. 199 45. 数组不是指针 .............................................................................................................................. 201 46. 标准C中字符串分割的方法 ..................................................................................................... 205 47. 汉诺塔源码 .................................................................................................................................. 208 48. 洗牌算法 .......................................................................................................................................211 49. 深入理解C语言指针的奥秘 ..................................................................................................... 213 50. 游戏外挂的编写原理 .................................................................................................................. 229 51. 程序实例分析-为什么会陷入死循环 ......................................................................................... 232 52. 空指针究竟指向了内存的哪个地方 .......................................................................................... 234 53. 算术表达式的计算 ...................................................................................................................... 238 54. 结构体对齐的具体含义 .............................................................................................................. 242 55. 连连看AI算法 ............................................................................................................................ 246 56. 连连看寻路算法的思路 .............................................................................................................. 254 57. 重新认识:指向函数的指针 ......................................................................................................... 258 58. 链表的源码 .................................................................................................................................. 261 59. 高质量的子程序 .......................................................................................................................... 264 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解.................................................... 266 61. C语言常见错误 .......................................................................................................................... 286 62. 超强的指针学习笔记 .................................................................................................................. 291 63. 程序员之路──关于代码风格 .................................................................................................. 306 64. 指针、结构体、联合体的安全规范 .......................................................................................... 309 65. C指针讲解 .................................................................................................................................. 314 66. 关于指向指针的指针 .................................................................................................................. 327 67. C/C++ 误区一:void main() ...................................................................................................... 331 68. C/C++ 误区二:fflush(stdin) ..................................................................................................... 334 69. C/C++ 误区三:强制转换 malloc() 的返回值 ........................................................................ 338 70. C/C++ 误区四:char c = getchar(); ............................................................................................ 339 71. C/C++ 误区五:检查 new 的返回值....................................................................................... 341 72. C 是 C++ 的子集吗? .............................................................................................................. 342 73. C和C++的区别是什么? .......................................................................................................... 345 74. 无条件循环 .................................................................................................................................. 346 75. 产生随机数的方法 ...................................................................................................................... 347 76. 顺序表及其操作 .......................................................................................................................... 348 77. 单链表的实现及其操作 .............................................................................................................. 349 78. 双向链表 ...................................................................................................................................... 353 79. 程序员数据结构笔记 .................................................................................................................. 357 80. Hashtable和HashMap的区别.................................................................................................... 364 81. hash 表学习笔记 ......................................................................................................................... 366 82. C程序设计常用算法源代码 ...................................................................................................... 368 83. C语言有头结点链表的经典实现 .............................................................................................. 375 84. C语言惠通面试题 ...................................................................................................................... 383 85. C语言常用宏定义 ...................................................................................................................... 402
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清忖灬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值