C Primer Plus: 第十一章 字符串和字符串函数

C Primer Plus: 第十一章 字符串和字符串函数

表示字符串和字符串I/O

  • put()函数只显示字符串,并且自动在显示的字符串末尾加上换行符。
  • 用双括号括起来的内容称为字符串字面量,也叫做字符串常量。如果字符串字面量之间没有间隔,或者用空白字符分隔,C会将其视为串联起来的字符串字面量。如
char greet[50] = "hello ,and" "how are" 
                 "today";
//等价于:
char greet[50] = "hello ,and how are today";
  • 字符串常量属于静态储存类别,这说明如果在函数中使用字符串常量,该字符串只会被存储一次,在整个程序的生命周期内存在,即使韩式被调用多次。用双引号括起来的内容被视为指向该字符串存储位置的指针。这类似于把数组名作为指向该数组位置的指针。
printf("%s,%p, %c\n", "We", "are", *"space fares");
//将会打印
We, 0x1000081, s
//%p,打印地址,"are"代表一个地址
//%s,打印字符,*"space fares"打印首字符(数组思想)
  • 数组和指针:
    • const char ar1[] = “Something is pointting at me.”;
    • 字符串存储在静态储存区中,但是在程序运行时才会为该数组分配内存。此时才将字符串拷贝到数组中。注意此时字符串有两个副本,一个是在静态内存中的字符串字面量,另一个是存储在ar1数组中的字符串。
    • ar1是地址常量,只允许ar1+1, 不允许ar1++
    • 初始化数组把静态储存区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针。
      C
      #define MSG "I am special"
      int main()
      {
      char ar[] = MSG;
      const char * pt = MSG;
      printf(%p, "I am special");
      printf(%p, ar);
      printf(%p, pt);
      printf(%p, MSG);
      printf(%p, "I am special");
      }
      //输出:
      0x123456
      0x414211
      0x123456
      0x123456
      0x123456
    • 虽然字符串字面量”I am special” 在程序的两个printf()函数中出现两次,但是编译器只使用了一个储存位置,而且与MSG的地址相同。编译器可以把多次使用的相同字面量储存在一处或多处。
    • 建议把指针初始化为字符串字面量时使用const限定符:const char *p = “king”;
      C
      const char *x[LIM]={
      "anc",
      "cbf"
      };
      char y[LIM][LIM]={
      "anc",
      "cbf"
      }
    • x中的指针指向初始化时所用的字符串字面量的位置,这些字符串字面量被存储在静态内存中。而y中的数组则存储这字符串字面量的副本,所以每个字符串都被存储了两次。

字符串输入

  • get()函数读取整行输入,直至遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符的末尾添加一个空字符使其成为一个C字符串。常与put()函数配对使用,该函数用于显示字符串,并在末尾添加换行符。
char words[LEN];
gets(words);
  • puts()只有一个参数,无法检查数组是否装得下该输入行,容易导致缓冲区溢出。
  • fgets():用来代替gets(),(fputs()代替puts()).fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到第一个换行符为止。fgets()读到换行符会储存在字符串中。(区别gets())
fgets(words, STLEN, stdin);//三个参数分别是,读入的存储区,最大读入字符数,输入流
  • gets():不读换行符
  • puts():添加换行符
  • fgets():读取换行符。读换行符返回char指针,该地址与传入的第一个参数相同。若读到文件末尾,则返回空指针。
  • fputs():不添加换行符
  • gets_s():C11新增。增加一个参数限制读入的字符数。区别于fgets()有以下:
    • 只从标准输入中读取数据,所以不需要第3个参数
    • gets_s()读到换行符,会丢弃而不是存储它
    • 若始终没有读到换行符,会执行以下几步。首先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着调用依赖实现的“处理函数”,可能会中止或者退出程序。
  • s_gets()

  • gets()\fgets()\gets_s()的适用性:

    • 如果目标存储区装得下输入行,3个函数都没有问题。但是fgets()会保留输入末尾的换行符作为字符串的一部分,要编写额外的代码将其替换成空字符。
    • 若输入行太长,gets()不安全,它会导致缓冲区溢出。gets_s()会丢弃该输入行的其余字符。fgets()函数最容易使用。
  • 区别空字符和空指针。

    • 空字符:’\0’是用于标记C字符串末尾的字符,其对应的字符编码是0。占一字节。
    • 空指针:NULL有一个值,该值不会与任何数据的有效地址对应。作为一个地址,占4字节。

自定义输入输出函数

  • 使用getchar()和putchar()自定义所需的函数。
  • strlen():统计字符串的长度
  • strcat():把2个字符串的备份附加在第1个字符串末尾,用于拼接字符串。
  • strncat():该函数的第三个参数用于指定最大添加字符。
  • strcmp():比较字符串,比较所有的字符,不止字母,直到不同的字符为止,持续到字符串末尾。相同返回0,否则返回非零值。。比较’A’和’B’,返回-1。比较’B’和’A’,返回1。这说明:如果第一个字符串在第二个字符串前面,返回负数,反之正数。
  • strncmp():多一个参数限制比较字符个数。
  • strcpy():拷贝整个字符串。返回char *,是第一个参数的值,即一个字符的地址。
  • strncpy():第三个参数指明可拷贝的最大字符数。

ctype.h 字符函数和字符串

  • Toupper()等

命令行参数

  • C编译器允许main()没有参数或者有两个参数。main(int argc, char *argv[])有两个参数时,第一个参数argc(argument count)是命令行中的字符串数量。第二个参数argv(argument value)存储输入字符串。第一个argv[0]为程序名称。

把字符串转换成数字

  • 使用<stdlib.h>头文件。包含了atoi(),atof(),atol()等函数原型。
  • atoi()把字符串转换成int.
  • atof()把字符串转换成double.
  • ANSI C还提供了一套更智能的函数:strtol(),strtoul(),strtod()
long strtol(const char* restrict nptr, char ** restrict endptr, int base)
nptr 指向待转换的字符串的指针
endptr是一个指针地址,该指针被设置为标识输入数字结束字符的地址
base标识以什么进制写入数字
  • 相反itoa()ftoa()则是把数字变成字符串。

  • 参考博客

restrict的用法:来源马中马博客

  • restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改;
  • 这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如 int *restrict ptr, ptr 指向的内存单元只能被 ptr 访问到,任何同样指向这个内存单元的其他指针都是未定义的,直白点就是无效指针(野指针)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值