C语言的学习(十四)---快速排序与指针操作一维字符型数组
本文摘要:文章首先介绍了快速排序算法的分治策略实现,包括基准值选择、分区处理和递归排序过程。随后详细讲解了指针操作字符串的注意事项,重点区分了字符数组和字符指针的区别,以及const修饰符在指针中的不同应用场景。最后通过实例演示了如何用指针和const封装字符串操作函数(如strncmp、strncat等),并强调函数设计应遵循低耦合原则。全文涵盖了算法实现和指针应用两个核心编程知识点。
目录
一、快速排序基本思想
快速排序采用分治策略:
-
选择一个基准元素(pivot)
-
将数组分为两部分:小于基准的放左边,大于基准的放右边
-
递归地对左右两部分排序
void quickSort(int *begin ,int *end) { if (begin>= end)//递归结束条件 { return ; }else//开始递归 { int *k = begin;//设定基准值为首元素地址 int *p = begin;//记录开始位置 int *q = end;//记录结束位置 while(begin <end)//begin与end相遇时的位置的值和基准值交换 { while(begin<end &&*end >=*k)//从右边开始,找比基准值小的数, //同时条件必须满足begin没有和end相遇 { --end;//从右边开始逐个对比 } while(begin<end &&*begin<=*k)//从左边开始,找比基准值大的数, //同时条件必须满足begin没有和end相遇 { ++begin;//从左边开始逐个对比 } swap(begin,end);//比基准值大的数和比基准值小的数互相交换 } swap(begin,k);//begin = end后将相遇位置上的值与基准值交换 //这时候就实现了,基准值左边的数比基准值小,基准值右边的数比基准值大 //然后接着递归,把左右半边的部分也用相同的方法,即可实现排序 quickSort(p,end-1);//排序基准值左半边,起始位置是begin, //结束位置是end-1也可以是begin-1反正位置都相等 quickSort(begin+1,q);//排序基准值右半边,同理 }
二、指针操作字符串
1.指针操作字符型一维数组与整型一维数组的区别:
char s[] = "hello"; //s中存放的是"hello" 内容
s[0] = 'A'; //可以修改数值
char *s = "hello"; //s中存放的是"hello" 地址(地址位于字符型常量区)
s[0] = 'A'; //不行 试图修改常量区数据
2.const关键字:
const关键字用于声明一个变量为常量,即该变量的值在初始化后不能被修改。如果尝试修改一个const变量的值,编译器会报错。
const 左边的内容是常量(如果左边没东西,就看右边第一个)
修饰原则: 就近原则 距离谁近 就修饰谁
const char * s; //表示基类型只读 --- 只是通过*s访问时是只读
基类型 指针变量
char const * s; //等价与const char * s;
char * const s; //表示地址不能变,数值可以变
const char * const s; //表示地址不能变,数值也不能变const char *s; <=>char const *s; //表示数值不能变,地址能变
const char * s ; //为什么要这么设计?
//1.为了避免 被调函数 对主调函数 数据的修改
//2.从函数功能角度出发考虑? 如果改函数只是用数据,而不修改,那么一般为 const char * 类型
//好处:
1.编译时,就可以发现的问题
2.增加参数适用性
//const char *
//char *
// "hello"
// char s[]
3.字符串操作函数:
用学到的const和指针,封装strncmp,strncat,strncpy等函数
#include<stdio.h>
//void Puts(const char *s)
void Puts(const char *s)
{
while (*s != '\0')
{
putchar(*s);
++s;
}
putchar('\n');
}
size_t Strlen(const char *s)
{
int cnt = 0;
while (*s != '\0')
{
cnt ++;
++s;
}
return cnt;
}
char * Strcpy(char *dest,const char *src)
{
char *ret = dest;
while (*src != '\0')
{
*dest = *src;
++dest;
++src;
}
*dest = '\0';
return ret;
}
char * Strncpy(char *dest,const char *src,int n)
{
char *ret = dest;
while (n && *src != '\0')
{
*dest = *src;
++dest;
++src;
--n;
}
while (n)
{
*dest = '\0';
dest++;
n--;
}
return ret;
}
char * Strcat(char *dest, const char *src)
{
char *ret = dest;
//1 定位 '\0'
while (*dest != '\0')
dest++;
//2.复制
while (*src != '\0')
{
*dest = *src;
++dest;
++src;
}
//3.'\0'
*dest = '\0';
return ret;
}
char * Strncat(char *dest, const char *src,int n)
{
char *ret = dest;
//1 定位 '\0'
while (*dest != '\0')
dest++;
//2.复制
while (n&&*src != '\0')
{
*dest = *src;
++dest;
++src;
--n;
}
//3.'\0'
*dest = '\0';
return ret;
}
int Strcmp(const char *s1,const char *s2)
{
while (*s1==*s2&&*s1!='\0'&&*s2!='\0')
{
++s1;
++s2;
}
return *s1 - *s2;
}
int Strncmp(const char *s1,const char *s2,int n)
{
//01234
//hello
//help
//n = 3 h
//n = 2 e
//n = 1 l
// s1 -- l
// s2 -- p
// n = 0
//n = 0 //结束
while (n>1&&*s1==*s2&&*s1!='\0'&&*s2!='\0')
{
++s1;
++s2;
--n;
}
return *s1 - *s2;
}
int main(void)
{
#if 0
char s[] = "hello";
Puts(s);
//printf("s = %s\n",s);
Puts("world");
const char * s1 = "china";
Puts(s1);
#endif
char s1[20] = {1,1,1,1,1,1,1,1,1,1,1,1,1};
//gets(s1);
// printf("len = %ld\n",Strlen(s1));
char s2[20];
char s3[20];
// Strcpy(s3,Strcpy(s2,s1));
// printf("s1 = %s s2 = %s s3 = %s\n",s1,s2,s3);
#if 0
Strncpy(s1,"hello",3);
int i = 0;
for (i = 0; i< 10; ++i)
{
printf("s[%d] = %d:%c\n",i,s1[i],s1[i]);
}
#endif
//Strcpy(s1,"hello");
//Strcpy(s2,"world");
//printf("dest = %s\n",Strcat(s1,s2));
#if 0
Strcpy(s1,"hello");
Strncat(s1,"world",3);
int i = 0;
for (i = 0; i< 20; ++i)
{
printf("s[%d] = %d:%c\n",i,s1[i],s1[i]);
}
#endif
gets(s1);
gets(s2);
printf("%d\n",Strncmp(s1,s2,3));
return 0;
}
三、小结
1.封装的函数最好是低耦合,不要依赖其他函数,且功能要完全区别开
2.问题,绿框中程序的结果是什么?

结果是段错误,char *s里面的数值不能修改
更多推荐



所有评论(0)