C语言学习笔记——字符与字符串

C语言学习笔记

字符与字符串

字符介绍

  • 基本数据类型分为数值类型和字符类型,数值类型分为整形和浮点型,字符类型分为字符和字符串。
  • 什么是字符:我们屏幕上出现的所有数字、汉字、符号等等全部是字符;我们使用的字符分为三类,ASCII字符(ASCII码表),拓展ASCII码(制表符),宽字符(汉字和特殊字符)
  • 字符类数据也有自己的转义字符,就像%d对应int,%u对应unsigned,%lf对应double一样,%c对应的是字符型数据。
  • 常见的输出方法:
    printf("%c",'A');
    putchar('a');

    这两种方法都能正确的输出A或者a,但是一定要记得单引号,否则会被系统认为是未声明的变量。
  • 每一个字符都对应着一个编号,每一个编号也对应一个字符

字符变量的定义

  • 字符的本质也是数字,比如用%d打印’A’,其结果还是65。
  • 定义方法char c这样就声明了一个字符变量。我们也可以直接定义char c = 'A',但是不能在单引号内写多个字符,被认为是错误写法。

字符输入的实质

  • 我们输入的所有内容全部储存在缓冲区,当我们按下回车时,表示输入结束,此时,有输入函数在缓冲区依次取数据,并存入变量的空间。
  • 输入字符很容易被缓冲区存留的呢绒影响,所以在输入字符前,我们把缓冲区清空,就可以去掉影响了。
  • 清空输入缓冲区的三种函数:
setbuf(stdin,NULL);
fflush(stdin);
while(c = getchar() != '\n' && c != EOF);
  • 其中第二种非C语言标准,有的编译器不支持,所以不建议使用。

scanf_s的用法

  • 编译器常见警告:scanf不安全,解决办法就是换用scanf_s
  • scanf_s("%c",&c,1);这样的语句是其标准写法。
  • 1指示了c的字节数
  • 读数值型变量没有问题,读字符型变量需要多加一个参数,就是这个数字1。
  • 后面学到字符串也要注意这个参数问题。

getchar()用法

  • 其函数原型是将缓冲区的一个字符作为返回值
  • c = getchar()这样的语句就是将一个字符给变量c。

_getch()用法

  • 随输入随读取,他的优点是不需要回车来确认。
  • 在很多游戏的制作中都大量使用了这个函数
  • getch()函数已经不被认可,所有的getch都应换用_getch。
  • 头文件<conio.h>

字符串

  • 概念:以'\0'为结尾的字符数组,如
    char str1[5] = {'a','b','c','d',0}
    char str2[5] = {'a','b','c','d','\0'}
    char str3[5] = {'a','b','c','\0'}
    char str4[5] = {'a','b','c'}
    这些全都是字符串。
  • 字符串的输出:printf("%s",str),%s是字符串专属的转义字符。意义是从给定的字符串地址开始,一个一个的输出,直到遇到'\0'结束,如果没有遇到'\0',就会继续向下输出,直到被'\0'结束,这是初学者能经常遇到的烫烫烫烫烫。同理,字符数组只能使用循环一个一个输出。
    字符串的首地址也有两种表达方法:str&str[0],类似于普通一维数组。
  • puts函数用法:专为字符串输出而制定的函数,直接puts(str)就可以完成。

字符串的声明方式

  • 有元素个数:和上述的声明方式相同,但是一定要注意别越界。
  • 无元素个数:char str[] = {'a','b','c','d','\0'}一定要手写0,否则极易导致越界。
  • 常量字符串:例如"hello world"要记得双引号,它和1,‘a’,12.3一样都是常量,是固定的,不能被赋值修改。
    输出方式:printf("%s","hello world");这样是不会导致越界操作的,常量字符串自带了0。
    char *p = "hello world";
    printf("%s",p);这样用指针来操作常量字符串也是没有任何问题的。
    printf(p);printf转定义,这与其本质有关。
  • 常量字符串初始化数组,这样数组在初始化时就不需要带大括号了,直接用双引号就可以。同样也是自带了0,但是一定要注意数组大小要大于等于常量字符串,否则会有警告,并且无法正常输出。

双引号的作用

  • 返回常量是字符串的首地址,hello world这是字符串本身
  • 因此上述printf(p)的写法才成立。

字符串的输入

  • 字符串的输入方式:scanf("%s",str),str还是字符数组的首地址,%s的输入方式会自动在字符串的后面补上'\0',因此要记得在输入的时候只能输入n-1个字符。同时scanf函数还无法读取空格,空格会被认为是分隔符。
  • 更加安全的输入方法scanf_s("%s",str,19);这样会给'\0'自动的留下一个位置。
  • gets(str)函数:首先它与scanf相比,可以读取空格,但是一定要小心越界。
  • 更安全的版本是gets_s(str,19),他也是会自动给'\0'留下一个位置。
  • 这四个函数中,不安全的版本如果输入越界,会在程序执行完成后发生报错。这样的错误应尽量避免,纠正很复杂。安全的版本如果越界了,则直接不进行输入,第一个字符就被记作'\0'

多种其他函数介绍

  • 本节中介绍的所有函数的头文件均为<string.h>,因篇幅有限,不进行一一列举。
  • 拷贝赋值函数:strcpy(str, str1),其意义是将str1赋值给str,其中str,str1都是char定义的数组。该函数的返回值是str。str1可以等价替换为正确初始化的指针,或者字符串。如果越界赋值,会在程序结束后报错。
  • 更安全的版本:strcpy_s(str, n , str1)这里参数n是指定复制的字节数,目标是str。
  • strncpy(str,str1,m)这里的m是指定替换的字符数,对应的目标是str1
  • strncpy_s(str,n,str1,m)同上
  • 计算字符串长度函数:strlen(p)参数应是字符串/数组的首地址,其返回值是计算的长度。
  • 比较函数:strcmp(str1,str2) 其意义是比较第一个具有相同下标的数据的ASCII值大小,不是比较长度,返回值只有三种类型:如果1>2输出一个正数,1==2输出0,1<2输出一个负数,具体结果是其ASCII差值。
  • strcmp(str1,str2,n)是比较了前n个字符
  • 拼接函数:strcat(str,str1)将str1拼接到str后面,拼接原理是取代str中的'\0',并且向后顺延。
  • strcat_s(str,20,str1)将str保护在20个字符以内。
  • strncat(str,str1,n)是拼接n个到str后面
  • strncat_s(str, n,str1 ,m)意义同上。
  • 将字符串转换为整数:atoi(str),返回值是转好的整数,类型是int,如果字符串从第一个向后出现了非数字字符,返回值是前面所有字符,或者0(第一个字符就不是)
  • 将整数转化为字符串:itoa(232,str,10)参数一是被转化的整数,参数二是转好后装到哪里,参数三是以几进制来进行转化这里加不加下划线_都可以。
  • 更安全的版本:_itoa_S(233,str,4,10)这样的第三个参数就是指定接受的长度,注意下划线_。
  • 注意:以上几个转化函数的头文件是<stdlib.h>
  • 格式化字符串:sprintf("str,..." , ...)str是一个字符串,后面的参数和printf相同,意义是将缓冲区的内容存入str中,将不同类型的数据全部转化为字符串。
  • 更安全的版本:sprintf("str,20,..." , ...);意义和上面的_s版本完全相同。

汉字与特殊字符

  • 一个汉字占两个字节,也就是需要两个char类型变量来装,这是因为国际认可的汉字数共有40000多个,只能用两个来记
  • 我们可以直接使用char str{3];scanf("%s",str[0])来进行输入,或者用两个连续的%c来转义。
  • 可以通过百度查询“汉字国标码查询”来找到每个汉字对应的数码但只能找到16位的数据,我们可以通过计算器来转化,也可以通过下列代码printf("%x",*(short*)str);来得到汉字对应的10进制数。

转义字符和转换说明符

  • 认识:转义字符\,它不但可以配合一些字母输出\t \n \r等等,还可以使用它加一些特殊符号,来表示正确地输出该特殊字符,例如\\ \? \"等。在学到文件操作的时候,也需要使用 \\来进行路径的表示
    转换说明符%,,%%可以输出一个%。
  • 转义字符的字节大小可以用strlen函数来进行表示:printf("%u\n",strlen("\w"));这样的结果是1,+字母的字节数全部是1,即使是未定义的也是1
    +数字和+0+数字表示的都是八进制数,且有个数限制,前者后面的数字只能是13位,也就是0377的范围,对应10进制0255;后者后面加的数字只能是12个,八进制077,10进制063;+x+数字后面也是加12个数字,16进制0ff,对应10进制0~255。
    这些全是1字节,但是如果输入了\58这类的非法字符,系统就会自动认为这是两个字符,输出的结果就是2字节了。
  • 上述情况的测试:
strlen("\58") = 2
strlen("\555") = 2
strlen("\400") = 报错(有的系统会认为是两个字符)
strlen("\5555") = 同上,系统会检测前三个数
strlen("\018") = 2
strlen("\xfff") = 报错(不能超过两个)
strlen("\xffw") = 2 这样就不会报错了,w不是16进制数	

字符串数组和二维字符数组

  • 字符串数组的定义:char *str[3] = {"asd","asdsa","asdasddsa"};每一个元素都是char*类型,即其每一个元素都是指向地址的。可以用printf(str[0])这样的代码来测试。也不能对其进行直接的修改,因为字符串是常量,不能被修改,但是我们可以通过str[1] = "123"这样的方式,详见双引号的作用。它的本质就是指针数组,或者叫地址数组。
  • 二维字符数组:char str[2][4] = {"asd","12"}其中的注意点很多,建议反复阅读本文章。这是在用字符常量区赋值栈区,原理相当于char str1[4] = "asd"

本周小结:本周顺利的学完了递归函数以及字符与字符串的主要内容。下周我们或将开始着手做一些较大的项目,但是还是要先稳扎稳打,先学习完结构体的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lanciberrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值