字符串(基础篇)


在进入正题之前,先上一波 思维导图,帮助你了解下面的知识体系。
在这里插入图片描述

字符串表示

概念

字符串:字符串是以空字符(’\0’)结尾的char数组。


创建

  1. 数组char name[] = "Elizabeth";
  2. 指针char *str = "Hello!";

看到这里,聪明的你也许会发现,既然有两种创建方式,那么它们之间有什么不同之处呢?


数组和指针创建的区别

  1. 相同点

    • 使用数组符号

          for (int i = 0; i < 10; i++)
                  printf("%c", name[i]);
      
          printf("");
      
          for (int i = 0; i < 6; i++)
                  printf("%c", str[i]);
      
    • 使用指针加法

      	for (int i = 0; i < 10; i++)
      		printf("%c", *(name+i));
      	
      	printf("");
      
      	for (int i = 0; i < 6; i++)
      		printf("%c", *(str+i));
      
  2. 不同点

只有指针可以使用自增运算符,WTF?难道数组名不是一个指针吗?

不急,先耐心的看一下,指针的自增运算符的使用:

while (*(str))	
		putchar(*str++);// 编译,运行正常

再来看一下,数组名能不能使用自增运算符

while (*name)
		putchar(*name++);// 编译报错,

结果:
在这里插入图片描述

从错误结果来看,难道说,数组名是一个常量

在《C和指针》这本书中“第八章 数组”中,作者从底层论述了:数组名是一个指针常量。


存储方式

字符串常量属于静态存储 static storage类。

静态存储:指如果在一个函数中使用字符串常量,即多次调用了这个函数,该字符串在程序的整个运行过程中只存储一份




字符串的输入和输出

输入

scanf

emmm…带有格式化输入的scanf函数更倾向于读入一个单词而不是字符串

scanf函数主要用于以某种标准形式输入的混合类型数据的读取和转换。(感觉这个跟占位符有很大的关系)

例如:

    char name[20];
    scanf("%s", name);
    printf("%s\n", name);

运行输入结果如下:
在这里插入图片描述

WTF?为什么只输出了一项?难道说后面的被计算机吃了?还是被抛弃了?

这也是scanf函数读取字符串时存在的一个小问题。

解释一下:如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理

注:当使用vs的时候,请在第一行添加 #define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查


gets

函数声明

char *gets(char *str)

先来说一下这个函数的特点,然后在分析一下其中的奥秘。

特点:它从系统的标准输入设备(通常是键盘)获得一个字符串,当遇到换行符时,表示这个字符串接收完毕。在接受完的字符串的后面自动添加一个空字符(’\0’),不接收换行符

致命缺陷它不检查预留存储区是否能够容纳实际输入的数据。多出来的字符有可能会溢出到相邻的内存空间,造成缓冲区溢出(buffer overflow)。

例如:

    char name[10];
    gets(name);

输入:
在这里插入图片描述

(巧了,我这边出现了不幸。):警告,变量name周围的栈堆已损坏。
在这里插入图片描述

嗯哼,这是为啥呢?(简单来说,发明者没有添加这种机制。)

从上面的函数声明中可得知:返回值是一个char*(返回一个指向接收字符串的指针)。

嗯哼?如果gets函数遇到了错误或者是到了文件的结尾,它就返回一个空地址(空指针 NULL)。这不就使我们可以方便的添加一些错误检查(适用于读取文件)。

whlie(get(file) != NULL)

综上所述:当你用gets函数的时候,一定,一定,一定要注意,你的buffer空间的大小。不然,可能你就要遭遇不幸了。


fgets

gets函数的升级版,改进了gets函数溢出问题

函数声明

char *fgets(char *str, int n, FILE *stream)

注:这里的返回值是跟gets函数的无差别。

参数解释

  • char *str:这是指向一个字符数组的指针,该数组存储了要读取的字符串
  • int n:这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
  • FILE *stream:这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。从键盘录入数据时,可以使用stdin作为该参数。

例如:

    char name[10];// 这里是不规范的写法,规范的数组长度应该是使用宏定义
    printf("What's your name?\n");
    fgets(name, 10, stdin);
    printf("%s,Hello.", name);

输入:
在这里插入图片描述

从上面的两种不同输入来看:

  • 当输入的长度超出数组的存储空间的时候,超出部分就扔掉了。
  • fgets函数读取换行符



输出

printf
emmm… 这个函数啊,万能,当然在输出字符串的时候还是得用下面的函数。


puts:

函数声明

int puts(const char *string)

返回值如果成功,该函数返回一个非负值,如果发生错误则返回 EOF。

参数解释

  • const char *string:这是要被写入的 C 字符串。

特点在要显示的字符串后面,自动添加一个换行符。

例如:

    char *str = "Hello";
    int res = puts(str);
    print("res = %d",res);

输出:
在这里插入图片描述

致命缺点puts函数遇到空字符时它就会停下来。

例如:

    char name[] = {'J','o','e'};// 创建一个没有空字符的字符串
    puts(name);

输出:
在这里插入图片描述

WTFFFFFF?这是?FFFFFF,因为没有遇到空字符puts函数不知道在哪里停止,它会往输出的字符后面找(在内存中),直到找到空字符位置。(是不是发现,这哥们一点都不可靠。)


fputs

puts函数的面向文件版本,进化版。

函数声明

int fputs(const char *str, FILE *stream)

返回值该函数返回一个非负值,如果发生错误则返回 EOF(-1)。

参数解释

  • str:这是一个数组,包含了要写入的以空字符终止的字符序列。
  • fp:指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。

特点不会自动添加换行符。

例如:

    FILE *fp;

    fp = fopen("file.txt", "w+");

    fputs("文件操作函数。", fp);

    fclose(fp);

输出:它会在当然文件目录下,创建一个名为:file,后缀是:.txt的文件,里面内容为:文件操作函数。

怎么将文件中的内容输出到控制台中,在这里就不再演示了,等到文件操作那一章节好好深入研究一波。


sprintf
printf函数的升级版。

函数声明

int sprintf(char *str, const char *format, ...)

参数解释

  • char *str:这是指向一个字符数组的指针,该数组存储了 C 字符串。
  • const char *format:这是字符串,包含了要被写入到字符串 str 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。

特点:将后面的内容存储到前面指定的字符串中。

例如:

    char str[80];

    sprintf(str, "Pi 的值 = %f", 3.1415926);
    puts(str);

输出:
在这里插入图片描述

总结

  • gets:读取字符串的时候,自动除去换行符。读取会发生溢出
  • puts:读取字符串的时候,自动添加换行符。如果字符串中没有空字符,输出会发生隐患
  • fgets存储换行符
  • fputs不自动添加换行符



字符串常用函数

strlen

strlen:计算字符串的长度,直到空结束字符,但不包括空结束字符。

函数声明

size_t strlen(const char *str)

参数解释

  • const char *str:要计算长度的字符串。

返回值:该函数返回字符串的长度。

例如:

    char str[] = "Hello!"; // 末尾包含一个空字符,加上空字符,len = 7
    int len = strlen(str);
    printf("len = %d\n", len);

输出:

在这里插入图片描述


strcmp、strncmp

strcmp:

strcmp:把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

函数声明

int strcmp(const char *str1, const char *str2)

参数解释

  • const char *str1:要进行比较的第一个字符串。
  • const char *str2:要进行比较的第二个字符串。

返回值

  • 如果返回值 < 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str2 小于 str1。
  • 如果返回值 = 0,则表示 str1 等于 str2。

比较规则:比较两个字符串的ASCII值。

例如:

	char str1[] = "Hello!"; // o : 111
	char str2[] = "Helle!"; // e : 101

	int res = strcmp(str1, str2);
	printf("res = %d\n", res);

输出:
在这里插入图片描述


strncmp:

strncmp:把 str1str2 进行比较,最多比较前 n 个字节。

函数声明

int strncmp(const char *str1, const char *str2, size_t n)

参数解释

  • const char *str1 : 要进行比较的第一个字符串。
  • const char *str2 :要进行比较的第二个字符串。
  • size_t n :要比较的最大字符数。

返回值:同上。

注:在这里就不做这个函数的演示了,简单来说,这个函数主要作用就是比较指定的字节数目



strcpy、strncpy

strcpy

strcpy:把 src 所指向的字符串复制到 dest

函数声明

char *strcpy(char *dest, const char *src)

参数解释

  • char *dest:指向用于存储复制内容的目标数组。
  • const char *src:要复制的字符串。

返回值:该函数返回一个指向最终的目标字符串 dest 的指针。

例如:

	char dest[20];
	char src[20] = "Hello!";

	
	strcpy(dest, src);
	printf("Dest = %s\nSrc = %s\n", dest,src);

输出:

在这里插入图片描述

注意!注意!注意!倘若,目标数组的空间 不够装下 源字符串时,会发生缓冲溢出。切记!切记!切记!


strncpy

strncpy:把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

函数声明

char *strncpy(char *dest, const char *src, size_t n)

返回值:同上。

注:在这里就不做这个函数的演示了,我相信你懂得。



strcat、strncat

strcat

strcat:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。

函数声明

char *strcat(char *dest, const char *src)

参数解释

  • char *dest :指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
  • const char *src:指向要追加的字符串,该字符串不会覆盖目标字符串。

返回值:该函数返回一个指向最终的目标字符串 dest 的指针。

例如:

	char dest[20] = "Hello!";
	char src[20] = "你好!";

	
	strcat(dest, src);
	printf("Dest = %s\nSrc = %s\n", dest,src);

输出:

在这里插入图片描述

从上面文字中,你可能会发现一个WWTFFFF的问题。那就是如果Dest的空间不够大,可能会的发生跟gets、strcpy函数等同样的问题。所以说:三思而后行。

strncat

strncat:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。

函数声明

char *strncat(char *dest, const char *src, size_t n)

参数解释

  • char *dest:指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串,包括额外的空字符。
  • const char *src:要追加的字符串。
  • size_t n:要追加的最大字符数。

返回值:同上。

注:在这里就不做这个函数的演示了,简单来说,这个函数主要作用就是追加指定大小的字节数目



strstr

strstr:在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。

函数声明

char *strstr(const char *haystack, const char *needle)

参数解释

  • const char *haystack:要被检索的 C 字符串。
  • const char *needle:在 haystack 字符串内要搜索的字符串。

返回值:该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。

例如:

	const char haystack[40] = "I am a super man!";
	const char needle[10] = "super";
	char *res = strstr(haystack, needle); // 在haystack中,没有,则返回null

	printf("输出结果是: %s\n", res);

输出:
在这里插入图片描述


最后说一下,嘿嘿,不喜勿喷,小生菜鸟一只,如有不足,还需各位兄长们多多指教。

发布了10 篇原创文章 · 获赞 30 · 访问量 1399

猜你喜欢

转载自blog.csdn.net/qq_35502243/article/details/97955548
今日推荐