第九周(笔记)
9.1 指针和二维数组,指向指针的指针
- 指针和二维数组
- 定义二维数组 T a[M] [N]; a[i] (i是整数)是一个一维数组,类型为T * ,sizeof(a[i]) = sizeof(T * N),a[i]指向的地址:数组a的起始地址 + i * N * sizeof(T)
- 向函数中传入二维数组,例:Reverse(a[1],4),代表第一行的4个元素执行reverse操作,假如第一行不满足四个,因为二维数组在存储中是连续的所以直接在传入第二行中的元素
- 指向指针的指针
- 定义:T * * p; 解释:p是指向指针的指针,p指向的地方应该存放着一个类型为T * 的指针
#include <iostream>
using namespace std;
int main()
{
int ** pp;
int * p;
int n = 1234;
p = &n;
pp = &p;
cout << *(*pp) << endl;
return 0;
}
9.2 9.3指针和字符串
- 指针和数组之间的关系
- 字符串常量的类型与字符串数组名的类型都是 char *
- char name[20], char * pName = name
- 假如定义char name[20]; int n; 读入这两个变量,命令为:scanf("%d%s",&n,name);
- 为什么读入整型为&n,而字符串却没有,因为scanf函数在执行的时候他得知道他输入的那个整数他是放内存里的哪个地方,这里是&n,就代表着要把读入的n放到n的地址那里去,而name前面就不需要,因为数组名字的类型为char * ,就是一个地址,所以不需要加&。
- 字符串操作库函数
- strchr 寻找字符c在str中第一次出现的位置,并返回指向该位置的指针,否则返回NULL
- strstr 寻找子串substr在str中第一次出现的位置,找到返回指向该位置的指针,否则返回NULL
- stricmp 大小写无关的字符串比较,如果s1< s2返回负数,s1=s2返回0,s1>s2返回正数
- strncmp 比较s1前n个字符组成的子串和s2前n个字符组成的子串的大小,若长度不足n,则取整个作为子串,返回值和strcmp类似
- strncpy 拷贝src的前n个字符到dest。如果src长度大于或等于n,该函数不会自动往dest中写入’\0’;若src长度不足n,则拷贝src的全部内容以及结尾的’\0’到dest。
- strtok 连续调用该函数若干次,可以做到从str中逐个抽取出被字符串限制中的字符分割开的若干个子串
- atoi 将字符串s里的内容转换成一个整型数返回,比如s的内容为"1234",那么函数返回值就是1234,如果s不是一个整数,例如"a12",则返回0。
- atof 将字符串中的内容转成实数返回,比如"12.34"就会转成12.34,如果s的格式不是一个实数则返回0
- itoa 将整型值value以radix进制表示法写入string。
- 例:char szValue[20];itoa(27,szvalue,10);//使得szvalue的内容变为"27"
- 库函数中的用法实例
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char s1[100] = "12345";
char s2[100] = "abcdefg";
char s3[100] = "ABCDE";
strncat(s1,s2,3);
cout << "1) " << s1 << endl;
strncpy(s1,s3,3);
cout << "2) " << s1 << endl;
strncpy(s2,s3,6);
cout << "3) "<< s2 << endl;
cout << "4) "<< strncmp(s1,s3,3) << endl;
char *p = strchr(s1,'B');
if (p)
cout << "5) " << p - s1 << "," << *p << endl;
else
cout << "5) Not Found" << endl;
p = strstr(s1,"45a");
if (p)
cout << "6) " << p-s1 << "," << p << endl;
else
cout << "6) Not Found" << endl;
char str[] = "- This, a sample string, OK.";
p = strtok(str," ,.-");
while (p!=NULL) {
cout << p << endl;
p = strtok(NULL," ,.-");
}
return 0;
}
9.4 void 指针和内存操作函数
- void指针
- 可以用任何类型的指针对void指针进行赋值或初始化,比如double d = 1.54,void * p = &d。
- 与其他指针的区别
- 因sizeof(void) 没有定义,所以对于void * 类型的指针p, * p 无定义,++pdeng操作均无定义
- 内存操作库函数memset(cstring头文件)
- void * memset(void * dest,int ch,int n); 将从dest开始的n个字节,都设置成ch。返回值是dest。ch只有最低的字节起作用。
- 例如:将szName的前10个字符,都设置成’a’;
- char szName[200] = “”; memset(szName,‘a’,10);cout << szName << endl; 输出的为aaaaaaaaaa
- 使用memest函数将数组内容全部设置成0;int a[100];memset(a,0,sizeof(a));
- 小细节,因为形参是void * 所以不管实参是char * 还是 int * 都可以传入了
- 内存操作函数 memcpy(cstring头文件)
- void * memcpy (void * dest, void * src, int n); 将地址src开始的n个字节,拷贝到地址dest。返回值是dest。
- 将数组a1的内容拷贝到数组a2去,结果是a2[0]=a1[0],a2[1]=a1[1],a2[2]=a1[2]…
- 例如:int a1[10]; int a2[10]; memcpy(a2,a1,10 * sizeof(int));
void * MyMemcpy (void * dest ,const void * src, int n) {
char * pDest = (char *) dest;
char * pSrc = (char *) src;
for (int i = 0;i<n;i++) {
* (pDest + i) = *(pSrc + i);
}
return dest;
}
9.5 函数指针
- 基本概念
- 程序在运行期间,每个函数都会占用一段的内存空间。而函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。我们可以将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。这种指向函数指针的变量称“函数指针”。
- 定义形式
- 类型名 ( * 指针变量名) (参数类型1,参数类型2,…); 例如:int ( * pf) (int ,char);
- 使用方法
- 可以用一个原型匹配的函数的名字给一个函数指针赋值。通过函数指针调用它所指向的函数,写法:函数指针名(实参表);
#include <iostream>
using namespace std;
void PrintMin(int a,int b) {
if (a < b)
printf("%d",a);
else
printf("%d",b);
}
int main()
{
void (*pf) (int ,int);
int x = 4,y = 5;
pf = PrintMin;
pf(x,y);
return 0;
}
- 函数指针和qsort库函数
- void qsort(void * base,int nelem, unsigned int width,int( * pfCompare)(const void * ,const void * )); //可以对任意类型的数组进行排序
- base :待排序数组的起始地址
- nelem:待排序数组的元素个数
- width:待排序数组的每个元素的大小(亿字节为单位)
- pfCompare:比较函数的地址(自己编写)
- int 函数名字(const void * eleml,const ovid * elem2);
- 比较函数编写规则:
- 如果 * elem1应该排在 * elem2前面,则函数返回值是负整数。
- 如果 * elem1和 * elem2 哪个排在前面都行,那么函数返回0.
- 如果 * elem1应该排在 * elem2后面,则函数返回值是正整数
- 对数组排序,需要知道:
- 数组起始地址,数组元素的个数,每个元素的大小(由此可推算出每个元素的地址),元素谁在谁前谁在谁后
#include <iostream>
#include <stdlib.h>
using namespace std;
int MyCompare (const void * elem1, const void * elem2) {
unsigned int * p1, * p2;
p1 = (unsigned int * )elem1;
p2 = (unsigned int * )elem2;
return (*p1 % 10) - (*p2 % 10);
}
#define NUM 5
int main()
{
unsigned int an[NUM] = {8,123,11,10,4};
qsort(an,NUM,sizeof(unsigned int),MyCompare);
for (int i = 0;i<NUM;i++) {
cout << an[i];
}
return 0;
}
|