[C语言]指针和字符串

壹、指针

sizeof
1、是一个运算符,给出某个类型或变量在内存中所占据的字节数
2、sizeof(int)
3、Sizeof(i)

一、运算符 &

1、scanf(“%d, &i);里的&
2、获取表量的地址,它的操作数必须是变量
int i; printf(“%x, &i);
3、地址的大小是否与int相同取决于编译器
Int i;printf(“%p, &i);

&不能取的地址
&不能对没有地址的东西取地址
&(a+b)?
&(a++)?
&(++a)?

&a=a=a[0]
相邻地址的差距是4

二、scanf

如果能够将取得的变量的地址传递给一个函数,能否通过在这个地址在那个函数访问这个变量?
scanf(“%d”, &i)
scanf()的原型应该是怎样的?我们需要一个参数保存别的变量的地址,如何表达能够保存地址的变量?

指针,就是保存地址的变量

int i;
Int* p = &i;
Int* p,q;
Int *p,q;

三、指针变量

1、变量的值是内存的地址
2、普通变量的值是实际的值
3、指针变量的值是具有实际值的变量的地址

作为参数的指针
1、void f(int *p);
在被调用的时候得到了某个变量的地址;
2、int i=0; f(&i);
在函数里面可以通过这个指针访问外面这个i

访问地址那个变量*
*是一个单目运算符,用来访问指针的值所表示的地址上的变量
可以做右值也可以做左值
int = *p;
*p = k+1;

传入地址
Int i; scanf(“%d”,i);
编译不报错,运行一定出错

int isPrime(int x, int knownPrimes[], int numberOfknownPrimes)
{
	int ret = 1;
	int i;
	for ( i=1; i<numberOfknownPrimes; i++) {
		if ( x% knownPrimes[i] == 0 ) {
			ret = 0;
			break;
		}
	}
	return ret;
}

函数参数表中的数组实际上是指针;
sizeof(a) == sizeof(int*)
但是可以用数组的运算符][]进行运算

四、数组函数and变量

以下四种函数原型是等价的

int sum(int *ar, int n); 
int sum(int *, int); 
Int sum(int ar[], int n)
Int sum(int [], int);

数组变量是特殊的指针
1、数组变量本身表达地址;
int a[10]; int*p=a; // 无需用&取地址
但是数组的单元表达的是变量,需要用&取地址
a==&a[0]
2、[]运算符可以对数组做,也可以对指针做
P[0] 等价 a[0]
3、*运算符可以对指针做也可以对数组做
4、数组变量是const的指针,所以不能被赋值
int a[] 等价 *const a=…

贰、字符

char是一种整数,也是一种特殊的类型:字符。这是因为:
1、用单引号表示的字符字面量:’a’, ‘1’
2、“也是一个字符
3、printf和scanf里用%c来输入输出字符

将’1‘输入
scanf(“%c”, &c);–>1
Scanf(“%d”, &i); c=i; -->49
‘1’的ASCII编码是49,所以当c==49是,它代表’1‘
Printf(“%i %c\n”, c,c );
一个49的各自表述!

scanf(“%d %c”, &i, &c);
scanf(“%d%c”, &i, &c);
二者不同

大小写转换
字母在ASCII表中是顺序排列的
大写字母和小写字母是分开排列的,并不是在一起

\b 回退一格 \t 到下一个表格位
\n 换行 \r 回车 \”双引号
\’ 单引号 \ 反斜杠本身

逃逸字符
用来表达无法印出来的控制字符或特殊,它由反斜杠“\”,后面跟上另一个字符,这两个字符合起来,组成一个字符

叁、字符串

char word[] = {‘H’, ‘e’, ‘I’, ‘I’, ‘O’,!};		//不是字符串
word[0]	H
word[1]	e
word[2]	I
word[3]	I
word[4]	o
word[5]	!



char word[] = {‘H’, ‘e’, ‘I’, ‘I’, ‘O’,!, ‘\0};		//是字符串
word[0]	H
word[1]	e
word[2]	I
word[3]	I
word[4]	o
word[5]	!
word[6]	\0

一、字符串

1、以0(整数0)结尾的一串字符
0或‘\0’是一样的,但是和’0’不同
2、0标志字符串的结束,但他不是字符串的一部分
计算字符串长度的时候不包含这个0
2、字符串以数组的形式存在,以数组或指针的形式访问更多的是指针的形式
3、String,h里有很多处理字符串的函数

字符串
1、C语言的字符串是以字符数组的形态存在的
2、不能用运算符对字符串做运算
3、通过数组的方式可以遍历字符串
4、唯一特殊的地方是字符串字面量可以用来初始化字符数组
以及标准库提供了一系列字符串的函数

二、字符串常量和变量

字符串变量
“hello”会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0
两个相邻的字符常量会被自动连接起来

字符串常量

char* s = “Hello, world!;

·s是一个指针,初始化为指向一个字符串常量
由于这个常量所在的地方,所以实际上s是const char* s,但是由于历史的原因,编译器接受不带const的写法
但是试图对s所指的字符做写入会导致严重的后果
如果需要修改字符串,应该用数组:
char s[] = “Hello, world!”;

如果要构造一个字符串–>数组
如果要处理一个字符串–>指针
char *str = “Hello”;
char word[] = “Hello”;
数组:这个字符串在这里
作为本地变量空间自动被回收
指针:这个字符串不知道在哪里
处理参数
动态分配空间

字符串可以表达为char的形式
char
不一定是字符串
本意是指向字符的指针,可能指向的是字符的数组(就像int*一样)
只有它所指的字符数组有结尾的0,才能说它所指的是字符串

char *t = “title”
char *s;
s=t;

并没有产生新的字符串,只是让指针s指向了所指的字符串,对s的任意操作就是对t做的

三、字符串的输入 输出

char string[8];
scanf(%s”, string);
printf(%s”, string);

scanf读入一个单词(到空格、tab或回车为止)
scanf是不安全的,因为不知道要读出的内容的长度

安全的输入
char string[8];
scanf(“%7s”, string);
在%和之间的数字表示允许读入的数量,这个数字应该比数组的大小小一

常见错误
char string
scanf(“%s”, string);
以为char
是字符串类型,定义了一个字符串类型string就可以直接使用了
由于没有对string初始化为0,所以不一定每次运行都出错

空字符串
char buffer[100]=” “;
只是一个空字符串,buffer[0] == ‘\0’
char buffer[] = “ “;
这个数组的长度只有1!

肆、指针运算

给一个指针加1表示让指针指向下一个变量
int a[10];
int *p = a;
*(p+1)< -->a[1]
如果指针不是指向一篇连续分配的空间,如果数组,则这种运算没有意义

一、指针计算

这些算术运算可以对指针做;
给指针加、减一个整数(+,+=,-,-=)
递增递减(++/–)
两个指针相减(sizeof的量)

*p++

取出p所指的那个数据来,完事后顺便把p移到下一个位置去
*的优先级虽然高,但是没有++高
常用于数组类的连续空间操作
某些CPU上,可以直接被翻译成一条汇编指令

遍历数组

for( p=ac; *p!=-1;p++) {
while ( *p != -1 ) {
	printf(%d\n”, *p++);
}

二、指针比较

<,<=,==,>,>=,!= 都可以对指针做
比较他们在内存中的地址
数组中的单元的地址肯定是线性递增的

三、地址

当然你的内存中也有0地址,但是0地址通常是个不能随意碰的地址
所以指针不应该具有0值
因此可以用0地址来用表示特殊的事情
返回的指针是无效的
指针没有被真正初始化(先初始化为0)
NULL是一个预定定义的符号,表示0地址
有的编译器不愿意用0来表示0地址

指针的类型与转换

指针的类型
无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
但是指向不同类型的指针是不能相互赋值的
这是为了避免用错指针

指针的类型转换
void表示不知道指向什么东西的指针
计算时与char
相同(但不相通)
指针也可以转换类型
int p = &i; voidq = (void*)p;
这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量

用指针来做什么
需要传入较大的数据时用作参数
传入数组后对数组做操作
函数返回不止一个结果
需要用函数来修改不止一个变量
动态申请的内存…

伍、指针函数

一、strlen

size_t strlen(const char *s);

返回s的字符串长度(不包括结尾的0)

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

size_t mylen(const char* s)
{
	int cnt = 0;
	int idx = 0;
	while(s[idx] != '\0') {
		idx++;
		cnt++;
	}
	return cnt;
 } 
 
 int main(int argc, char const *argv[])
 {
 	char line[] = "hello";
 	printf("strlen=%lu\n", mylen(line));
 	printf("sizeof=%lu\n", sizeof(line));
 	
 	return 0;
 }

二、strcmp

strcmp

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

比较两个字符串,返回:
0:s1 == s2
1:s1>s2
-1:s1<s2

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

int mycmp(const char* s1, const char* s2)
{
	while ( *s1 == *s2 && *s1 != '\0' ) {		//判断指针 
		s1++;
		s2++;		//移动指针 
	}
	return *s1 - *s2;		//得出结果 
}

int main(int argc, char const *argv[])
{
	char s1[] = "abc";
	char s2[] = "abc";
	printf("%d\n", mycmp(s1,s1));
	printf("%d\n", 'A' - 'a');
	
	return 0;
}

三、strcpy和strcat

strcpy
char* strcpy(char *restrict dst, const char *restrict src);
把src的字符串拷贝到dst
restrict表明src和dst不重叠(C99)
返回dst
为了能链接起代码来
先是目的后是元
复制一个字符串

 char *dst = (char*)malloc(strlen(src)+1);
 strcpy(dst, src);
#include <stdio.h>
#include <string.h>

char* mycpy(char* dst, const char* src)
{
	int idx = 0;
	while ( src[idx] ) {
		dst[idx] = src [idx];
		idx++;
	}
	dst[idx] = '\0';
	return dst;
 } 
 
 int main(int argc, char const *argv[])
 {
 	char s1[] = "abc";
 	char s2[] = "abc";
 	strcpy(s1,s2);
 }

strcat
charstrcat(charrestrict s1,const char *resrict s2);
把s2拷贝到s1的后面,结成一个长长的字符串
返回s1
s1必须有足够的空间
tip:strcpy和strcat都可能出现安全问题(即,字符串容量问题)

char* strncpy(char *restrict dst, const char *restrict src, size_t n);
char* strncat(char*restrict s1, const char *restrict s2, size_t n);
int strncmp(const char *s1, const *s2, size_t n);

四、strchr

strchr

char*strchr(const char*s, int c);			//从左
char*strrch(const char*s, int c);			//从右

返回NULL表示没有找到

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

int main(int argc, char const *argv[])
{
	char s[] = "hello";
	char *p = strchr(s, 'l');
	//*p = '\0'
	char *t = (char*)malloc(strlen(p)+1);		//改为strlen(s) 
	strcpy(t, p);		//p改为s 
	printf("%s\n", t);		//即可输出l前的字母 
	free(t);
	
	return 0;
}

五、strstr和strcasestr

strstr //寻找字符串

char *strrchr(const char *s1, const char *s2);`

该函数返回 str 中最后一次出现字符 c 的位置。如果未找到该值,则函数返回一个空指针。

strcasestr //寻找单个字符

char* strcasestr(const char *s1, const char *s2);

忽略大小写

tips:
sizeof(char)=1
sizeof(int)=4

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值