1.杨氏矩阵:(有一个数字矩阵,矩阵的每行从左到右都是递增的,矩阵从上到下都是递增的,编写程序在这样的矩阵中查找某个数字是否存在)
思想:一行或者一列的形式去消;可以加大效率;一个二维数组的右上角元素一定是一行中最大了,同样也一定是一列中最小的;
注意:定义函数传参的时候,需要把行数、列数一并传过来;即findnum(arr,k,3,3);三行三列一并传过来;数组下角标x=0定义第一行,y=col-1定义最后一列;锁定数组右上角的元素;
拿数组右上角的元素去和要找的元素进行比较,如果小于要找的元素,意味着这一行一定没有要找的元素;因为右上角的元素是一行中最大的元素;所以 行++-------x++ ;找下一行,同理:列也如此;
然后进行循环:循环条件是:每减一次就会少一行或者一列----------最少最少要到达二维数组左下角的元素,所以x++最多加到2;y--最多减到0;
int findnum(int arr[3][3], int k, int row, int col)
{
int x = 0;
int y = col - 1;
while (x <= 2 && y >= 0)
{
if (arr[x][y] < k)
{
x++;
}
else if (arr[x][y] > k)
{
y--;
}
else
return 1;
}
}
int main()
{
int arr[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int k = 10;
int ret = findnum(arr, k, 3, 3);
if (ret == 1)
{
printf("找到了\n");
}
else
printf("找不到\n");
return 0;
}
用下角标的形式打印出来:
思想:主函数中定义x=3;y=3;将地址传给函数;函数用指针进行接收,然后找到相应的元素以后,将找到的x和y传给指针,进行返回,主函数打印下角标;
int FindNum(int arr[3][3], int k, int *px, int *py)
{
int x = 0;
int y = *py - 1;
while (x <= 2 && y >= 0)
{
if (arr[x][y] < k)
x++;
else if (arr[x][y] > k)
y--;
else
{
*px = x;
*py = y;
return 1;
}
}
}
int main()
{
int arr[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int k = 7;
int x = 3;
int y = 3;
int ret = FindNum(arr, k, &x, &y);
if (ret == 1)
{
printf("找到了\n");
printf("下角标是:%d %d", x, y);
}
else
printf("找不到\n");
return 0;
}
2. 字符串函数:
strlen函数:字符串以 “\0” 作为结束标志,strlen函数返回值是 \0 之前出现的字符串个数;
ag.通过函数打印strlen的值:
assert函数的意思是断言:指针不等于空指针;切记:数组传参传过去的是首元素的地址;while开启循环,只要扫描的不是结束标志\0,count++;str++; str++表示扫描完第一个字符接着扫描第二个字符;依次类推;
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>//assert的头文件
int my_strlen(char* str)
{
int count = 0;
assert(str != NULL);//断言:指针不等于空指针;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
int len = my_strlen("abcdef");
printf("%d\n", len);
return 0;
}
打印结果:hehe; 第一个结果是3,第二个结果是6,相减得-3,原本应该打印出haha,但结果却是hehe;
原因在于:strlen函数的函数类型是size;等价于unsigned int----无符号函数;两个相减得到的并不是整型-3;无符号数-3打印出来 ,一定是大于0的,所以打印出来结果是hehe;
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>//assert的头文件
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf("hehe\n");
}
else
printf("haha\n");
return 0;
}
strcpy函数:字符串拷贝函数;
------返回类型
定义函数my_strcpy;传参两个char* 指针来接收首元素地址;assert进行函数断言;将arr1对应的指针char* dest传给ret ,最后返回ret;意思就是说把拷贝完的arr1作为返回值传给主函数进行打印;注意while循环中的意义:将指针src赋值给dest;因为接收的是首元素的地址,所以需要++寻找下一个字符;
此处注意可以对代码进行优化,直接在while循环中进行*dest++=*src++;赋值完后置++;
#include <stdio.h>
#include <string.h>
#include <assert.h>//assert的头文件
char* my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = dest;
while (*dest++ = *src++)
{//拷贝src指向的字符串到dest指向的空间,包含\0
;
}
return ret;//返回目的地的起始地址
}
int main()
{
char arr1[] = "abcdefgh";
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcpy函数使用的注意事项:原函数中必须包含结束标志\0;意思就是说如果初始化数组为arr[]={‘a’,‘b’,‘c’}------则该函数不能使用;
拷贝的时候会将\0一并拷贝到目标函数;
目标函数的空间必须足够大,以确保能够存放字符串;
strcat函数:字符串追加函数
------返回类型
注意需要保证:被追加的字符串函数需要足够大;如果是arr1[]=“hello”;把arr2追加到arr1后,arr1不一定有足够的位置去存放追加的内容,造成报错:内容溢出;所以需要给arr1[20]=“hello”足够的位置;
int main()
{
char arr1[20] = "hello";
//char arr1[] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
注意事项:目标函数必须足够大;源头函数必须有结束标志\0;否则没有结束,会造成溢出;目的地函数也必须有\0,因为追加时是从目的地函数的结束地\0进行追加的;
strcat函数不能自己给自己追加;
strcmp函数:字符串比较函数
------返回类型
strcmp函数的返回类型是:如果p1>p2,返回一个大于0的数;如果p1<p2,返回一个小于0的数;如果p1=p2,则返回值为0;
两个字符串的比较比的是:字符串首元素的大小,例如:b>a;所以输出1;按照26字母表比较,如果首元素相等,则比较第二个元素,依次类推;注意不是比较字符串的长度;
int main()
{
char* p1 = "bbcdef";
char* p2 = "ait";
int ret = strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
assert(str1&&str2);函数断言;与---有一个为假就是假,两个都是真才为真;所以两个指针都不是NULL我才继续,否则我就中断运行;
需要注意:判断两个相等时,一个指针到达结束标志,另一个一定也是到达了,意味着结束标志之前的字符完全相等,所以返回值0;
特别注意:指针用不用带 * 号是根据你的需要判断的:带 * 号意味着取地址,数组传参得到的是首元素的地址,比较首元素时带*号;而数组进行++时,对数组以后的元素进行比较时,不用带*号;
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>//assert的头文件
int my_strcmp(const char* str1, const char* str2)
{
assert(str1&&str2);//有一个指针为假我就终止,两个都是真我才继续
while (*str1 == *str2)
{
if (str1 = '\0')//循环语句是两个相等,其中一个扫描到结束标志
{//另一个一定也是结束标志,意味着两个字符串完全相等,所以返回0
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char* p1 = "abcdef";
char* p2 = "buhuh";
int ret = my_strcmp(p1, p2);
printf("ret=%d\n", ret);
return 0;
}
strncpy函数:限制长度的字符串拷贝函数
---返回类型
前两个返回类型和strcpy是一样的 size_t count的意思:我把字符串2拷贝到字符串1,我要拷贝几个字符,单位是字节;
int main()
{
char arr1[10] = "zbcdef";
char arr2[] = "hello";
strncpy(arr1, arr2,4);
printf("%s\n", arr1);
return 0;
}
输出结果:hellef
特殊的:如果字符串arr2仅仅只有5个字符,而strncmp需要复制字符串的设定为6,则会把结束标志 \0 一并cpy过去,会造成打印出来的arr1因为结束标志\0的存在,而造成打印的结果为hello;因为hello后面会加上\0 cpy到arr1上;
特殊的:
int main()
{
char arr1[10] = "zbcdef";
char arr2[] = "hello";
strncpy(arr1, arr2,6);
printf("%s\n", arr1);
return 0;
}
输出结果:hello
strncat函数:限制长度的字符串追加函数
---返回类型
同样的;前两个返回类型和strcat一致;size_t count是确定的追加字符串长度;
注意:我追加完成以后的arr1,arr1中结束标志\0不是arr2带过去的,而是arr1在追加完成以后自己主动在最后添加的;
int main()
{
char arr1[20] = "zbcdef";
char arr2[] = "hello";
strncat(arr1, arr2,6);
printf("%s\n", arr1);
return 0;
}
输出结果:zbcdefhello
strncmp函数:字符串比较函数
返回类型-----
相比于strcmp,同样是增加了size_t count / unsigned int----字节的个数,确定比较的大小;
int main()
{
char arr1[20] = "hellef";
char arr2[] = "hello";
int ret=strncmp(arr1, arr2,6);
printf("%d\n", ret);
return 0;
}
输出结果:-1
strncmp的返回类型和strcmp一致:两个相等,返回0;arr1>arr2,返回一个大于0的数(在VS编译器中默认返回值为1,但并不代表所有编译器都返回一,标准的应该是返回一个大于0的数);arr1<arr2,返回一个小于0的数,VS编译器中默认返回值是-1;第三个参数是比较的字符数,如果是3,则只比较arr1和arr2前三个元素的大小,后面的元素不参与比较;
插曲:NULL 表示空指针;NUL、null表示 \0;
strstr函数:找子字符串的函数
-----返回类型
返回值:如果能够找到子字符串,则返回值为子字符串的首元素地址;如果找不到子字符串,则返回值为NULL;
int main()
{
char* arr1 = "abcdefg";
char* arr2 = "r";
char* ret=strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
printf("找到了\n");
}
输出结果:找不到
找到了,要打印结果----即从找到的子字符串的首元素地址进行打印-----cdefg;
int main()
{
char* arr1 = "abcdefg";
char* arr2 = "c";
char* ret=strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
printf("%s\n",ret);
}
输出结果:cdefg
在初始化之前加上const表示:该函数初始化以后我不会再更改他了;