指针与字符串

size of

一个运算符,给出某个类型或变量在内存中所占据的字节数

size of(int)

size of(i)

 

运算符&

scanf("%d", &i) 里的&

获得变量的地址,操作数必须是变量

地址的大小是否与int相同,取决于编译器

int i;

printf("%p", &i);

 

常用的几种格式符:

%o输出八进制,%d输出十进制,%x输出十六进制,%f输出浮点型数据,%c输出单个字符,%s输出字符串,%l输出长整型

%p输出十六进制,用于输出变量地址

&只能对变量取地址

 

指针

就是保存地址的变量

 

指针变量

变量的值是内存地址

普通变量的值是实际的值

指针变量的值是具有具体的值的变量的地址

 

作为参数的指针

void(int *p)

在被调用时获得了某个变量的地址

在函数里面可以通过这个指针访问外面这个变量

#include<stdio.h>

void f(int *p);

int main(){
int i;
printf("&i=%p\n", &i);
f(&i);

return 0;
}

void f(int *p){
printf("p=%p\n", p);
}

 

访问地址上的变量 用*

*是一个单目运算符,用来访问指针的值所表示的地址上的变量;

可以作右值,也可以作左值

int k = *p

*p = k+1

 

#include<stdio.h>

void f(int *p);
void g(int k);

int main(){
int i=3;
printf("&i=%p\n", &i);
f(&i);    
g(i);

return 0;
}

void f(int *p){    //获取i的地址

printf("p=%p\n", p);   // p保存的是i的地址
printf("*p=%d\n", *p);     // *p 用i的地址访问i
*p = 10;    //对i做修改
}

void g(int k){
printf("k=%d\n", k);
}

 

指针与数组

传入函数的数组,

函数参数表中的数组实际上就是指针;

sizeof(a) == sizeof(int *)

但是可以用数组运算符[]进行计算

这也是为什么不能在函数里用sizeof(a)/sizeof(a[0]) 来计算数学组长度

 

字符类型

char

可以看作是一个整数,也可以看作是一个字符

用单引号表示字符自变量,'a', '1'

'' 也表示一个字符

printf 和 scanf 里用 %C 来输入输出字符

 

字符的输入输出

#include<stdio.h>

int main()
{
char c;
char b;
c = 1;     // 整数1
b = '1';     // 字符1

if(c==b){
printf("相等\n");
}
else{
printf("不相等\n");
}

printf("c = %d\n", c);       // 输出结果1
printf("b = %d\n", b);       // 输出结果49。  计算机内部字符1对应的数值是49

return 0;
}

 

如何输入'1' 这个字符给 char C?

scanf("%c", &c);  // 输入1

scanf("%d", &i);  c=i;      //输入49 

 

 

#include<stdio.h>

int main()
{
char c;

scanf("%c",&c);     //    以字符形式读入,输入1

printf("c = '%c'\n", c);    // 输出结果字符1
printf("c = %d\n", c);   // 输出结果数值49

return 0;
}

 

 

 

 

#include<stdio.h>

int main()
{
int i;
char c;

scanf("%d",&i);   // 以整数形式读入,输入1
c = i;

printf("c = %d\n", c);    // 输出结果整数1
printf("c = '%c'\n", c);     // 输出结果' '

return 0;
}

--------

#include<stdio.h>

int main()
{
int i;
char c;

scanf("%d",&i);   // 以整数形式读入,输入49
c = i;

printf("c = %d\n", c);    // 输出结果整数49
printf("c = '%c'\n", c);     // 输出结果字符'1'

return 0;
}

 

1的ASCII编码值是49,所以当c ==  49时,它代表字符'1'

 

 

混合输入

scanf("%d %c", %i, &c);

scanf("%d%c", &i, &c);

有什么不同?

#include<stdio.h>

int main()
{
int i;
char c;

scanf("%d %c",&i, &c);  // 中间有空格,前面的整数会把后面的字符前面的空格读完

printf("i = %d, c = %d, c = '%c'\n", i, c, c);

return 0;
}

 

 

#include<stdio.h>

int main()
{
int i;
char c;

scanf("%d%c",&i, &c);  // 中间没有空格,前面的整数只读到整数结束为止,后面的输入(包括空格)留给%c读入

printf("i = %d, c = %d, c = '%c'\n", i, c, c);

return 0;
}

 

字符计算

#include<stdio.h>

int main()
{
char c = 'A';

c++;
printf("%c\n", c);

return 0;
}

// 得到B

#include<stdio.h>

int main()
{
char c = 'A';

c+=2;
printf("%c\n", c);

return 0;
}

// 得到C

#include<stdio.h>

int main()
{
int i = 'Z' - 'A';
printf("%d\n", i);

return 0;
}

// 得到25

一个字符如果加一个数字,得到ASCII码表中那个数之后的字符;

两个字符减,得到他们在表中的距离。

 

在ASCII码表中,

数字0-9从小到大排序;

字母按顺序排列,大写字母和小写字母分开排列

大小写转换:

'a' - 'A' 可以得到两段之间的距离,

于是A + 'a' - 'A' 可以把一个大写字母变成小写字母,

#include<stdio.h>

int main()
{
char t = 'A';
int i = 'a' - 'A';

t = t + i;
printf("%c\n", t);

return 0;
}

而a + 'A' - 'a' 可以把一个小写字母变成大写字母

#include<stdio.h>

int main()
{
char t = 'a';
int i = 'A' - 'a';

t = t + i;
printf("%c\n", t);

return 0;
}

 

逃逸字符

\b  回退一格       

打印\b的作用并不是将之前的字符从屏幕上清除,而是将光标前移一个位置,而仅仅将光标前移并不能将此前的字符清除,除非输出一个空格将其覆盖

\t  到下一制表位

\n  换行

\r  回车

\"  双引号

\'  单引号

\\  反斜杠本身

 

字符串

以0(整数0)结尾的一串字符;

0或'/0'是一样的,不是'0';

0标志字符串的结束,不是字符串的一部分,计算字符串长度的时候不包括0;

字符串以数组的形式存在,以数组或指针的形式访问,更多的是以指针的形式;

处理字符串的函数放在string.h 

 

字符串变量

char *str = "Hello";

char world[] = "Hello";

char line[10] = "Hello";    

字符串常量

"Hello" 会被编译器变成字符串数组放在某处,这个数组的长度是6,结尾还有表示结束的0

两个相邻的字符串常量会被自动连接起来

字符串

C语言的字符串是以字符数组的形式存在的

不能用运算符对字符串进行计算

通过数组的方式可以遍历字符串

唯一特殊的地方在字符串字面量可以用来初始化字符数组

标准库提供了一系列字符串函数

 

字符串常量

 char* s  = "Hello world";

s 是一个指针,指向字符串常量,这个字符串常量的位置位于程序的代码段,只能读不能写

实际上是const char* s,由于历史的原因,编译器接受不带const的写法

试图对s所指的字符串做写入,会导致程序崩溃

想要对字符串做修改,应该用数组定义字符串:

char s[] = "Hello world";

 

用指针还是数组?

 char* s  = "Hello world";

char s[] = "Hello world";

 数组:

表示字符串在这里,知道在哪里

作为本地变量,空间被自动回收

指针:

不知道在哪里

只对字符串读,不做修改

作为函数的参数

动态分配空间

构造一个字符串,用数组;

处理一个字符串,用指针

 

char* 不一定是字符串:

字符串可以表示为char*,但是char* 不一定是字符串;

本意是指向字符的指针,可能指向的是字符的数组;

只有当它所指的字符数组的结尾有结束符0,才能说指的是字符串

 

字符串赋值

char* t = "title";

char* s;

s = t;

并没有产生新的字符串,而是让s也指向t所指的字符串,对s做的任何操作就是对t做的

 

字符串输入输出

char string[8];

scanf("%s", string);

printf("%s", string);

scanf 读入一个单词,以空格/tab/回车结束

这样的scanf是不安全的,不知道要读入的内容的长度

scanf("%ns",string);    //  n 表示最多读入的长度

 

常见错误:

①char* string;

scanf("%s", string);

以为char* 是字符串类型,定义了一个字符串类型的变量string就可以使用了。要初始化才能使用。

②空字符串

char buffer[100] = ''"

是一个空字符串,buffer[0] == "\0"

char* buffer[] = "";

这个数组的长度只有1,只有"\0", 放不下任何字符串

 

字符串函数

字符串函数存放在string.h

strlen:

size_t strlen(const char* s);

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

 

strcmp:

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

比较两个字符串,返回:

0:s1 == s2

1: s1 > s2

-1:s1 < s2

字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。strcmp()首先将s1 第一个字符值减去s2 第一个字符值,若差值为0 则再继续比较下个字符,若差值不为0 则将差值返回。例如字符串"Ac"和"ba"比较则会返回字符"A"(65)和'b'(98)的差值(-33)。

返回值:若参数s1 和s2 字符串相同则返回0。s1 若大于s2 则返回大于0 的值。s1 若小于s2 则返回小于0 的值。

 

strcpy:

char* strcpy(char* restrict dst, const char* restrict src);

把src 的字符串拷贝到dst

restrict 表明src和dst不重叠(c99)

返回dst

 

strcat:

char* strcat(char* restrict s1, const char* restrict s2);

把s2拷贝到s1后面,接成一个长的字符串

返回s1

s1必须有足够的空间

 

一般使用安全版本:

char* strncpy(char* restrict dst, const char* restrict src, size_t n);  //  最多拷贝n个字符

char* strncat(char* restrict s1, const char* restrict s2, size_t n);  // 最多连接n个字符

int strncmp(const char* s1, const char* s2, size_t n);   //只比较前面n个字符

 

字符串中找字符:

char* strchr(const char* s, int c );

char* strrchr(const char* s, int c);

posted @ 2021-12-12 21:58  泰勒斯儿童营养牙膏  阅读(67)  评论(0编辑  收藏  举报