初学者对C语言的爱恨情仇之神秘的字符串

简介: 初学者对C语言的爱恨情仇之神秘的字符串

前言

本文是针对对字符串有疑惑的初学者。例如:对C语言中的字符串并不了解,不太会使用。学过其他编程语言,现在转入了C语言,但是在C语言中使用字符串时不能像Java一样如愿以偿,自由自在的使用。那么就可以看本篇文章,本篇文章不会涉及太深的东西,太深的东西对于初学者会受不了的。

字符串是谁

说到字符串是谁,那么需要提一下字符是什么,没有字符就没有字符串。

像我们学的“每一个”英文字符(a,b,c…)都是属于字符,并且汉字、数字、标点符号都是属于一个字符;

像“我是谁,我在哪”这7个字符合起来就是一个字符串。那么串的话其实就是多个字符合在一起的结果。

经常听说字符串字面量,究竟是什么鬼?

经常听别人说字符串字面量,字面量的这是啥呢?

其实你一点也磨陌生,可能只是对这个名字陌生一些,你在学习Hello World的时候,其实就在用了。没错用双引号包含的“Hello World”就是字符串字面量。

printf("Hello World!");

执行结果:

Hello World!

我们想换行时,可以加个\n:

printf("Hello  \n   World!");

结果:

Hello  
   World!

字符串字面量如何存储的

例如字符串:"Hello World!"

你看着是一个字符串,实际上在存储的时候,是像数组一样,一个字符一个字符分开存的。

[“H”,“e”,“l”,“l”,“o”," “,“W”,“o”,“r”,“l”,“d”,”!","\0"];

在存储的时候,每个字符串的结尾是包含"\0",所以一般我们如果不知道一个字符串的长度如何遍历每个字符呢?那就可以使用"\0"条件来判断。

C语言字符数组与字符指针

我们可以利用char类型的数组,来定义和初始化字符串。

char str[12] = "I Love You!";
char *pStr = "I Love You!";

我们在打印的时候,需要使用%s来格式化数值:

printf("str=%s\n",str);
printf("pStr=%s\n",pStr);

打印结果:

str=I Love You!
pStr=I Love You!

也支持多种单个访问方式:

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

结果:

*(str+2)=L
*(pStr+2)=L

C语言中的字符串库

在Java中有String类型的jar包,在C语言中也有相应的字符串库。无论是Java中的jar包,还是C语言中的库。其实都是一些封装好的工具,以便给他人使用。

在实际开发中,我们掌握这些库的基本用法是必须的,可以大大的提高我们的工作效率。

在Linux中我们可以使用man命令来查看帮助手册。

例如:

man string

会出现下面这样的结果:

可以看到:

这些都是我现在这个Ubuntu系统中的string库中所提供的一些功能的函数。

在此我带着熟悉几个常用的函数。

我挑选了几个常用的,其实也就四种:统计字符串中的字符个数、字符串拼接、字符串比较、字符串拷贝/赋值。

SYNOPSIS
       #include <string.h>
       size_t strlen(const char *s);
              Return the length of the string s.
       char *strcat(char *dest, const char *src);
              Append the string src to the string dest, returning a pointer dest.
       char *strncat(char *dest, const char *src, size_t n);
              Append at most n bytes from the string src to the string dest, returning a pointer to dest.
       int strcmp(const char *s1, const char *s2);
              Compare the strings s1 with s2.
       int strncmp(const char *s1, const char *s2, size_t n);
              Compare at most n bytes of the strings s1 and s2.
       char *strcpy(char *dest, const char *src);
              Copy the string src to dest, returning a pointer to the start of dest.
       char *strncpy(char *dest, const char *src, size_t n);
              Copy at most n bytes from string src to dest, returning a pointer to the start of dest.

我们如何想使用的话,需要先include一下头文件:

本次使用的代码框架如下:

#include <stdio.h>
#include <string.h>
int main(void)
{
        return 0;
}

1、strlen函数

从函数的名字上也不难看出,这个是跟字符串和长度有关系的函数。

如果第一次使用的话,可以使用:man strlen来查看这个函数的使用说明。

解释的非常详细。

可以看到strlen()函数在计算传入的字符串s的时候是不计算结束符"\0"的。

返回值是传入字符串s的字节数/字符格式。

#include <stdio.h>
#include <string.h>
int main(void)
{
        char str[12] = "I Love You!";
        char *pStr = "I Love You!";
        printf("str=%s\n",str);
        printf("pStr=%s\n",pStr);
        int strLen = strlen(str);
        int pStrLen = strlen(pStr);
        printf("str len:%d \n",strLen);
        printf("pStr len:%d \n",pStrLen);
        return 0;
}

结果:

可以看到无论是字符数组还是字符指针,都是可以统计出来有多少个字符的

zhenghui@zhlinux:~/桌面/code/string$ 
zhenghui@zhlinux:~/桌面/code/string$ make strtest && ./strtest 
cc     strtest.c   -o strtest
str=I Love You!
pStr=I Love You!
str len:11 
pStr len:11 
zhenghui@zhlinux:~/桌面/code/string$

计算时到底有没有跟数组的大小有关系?

char str[12] = "I Love You!";
  char str2[100] = "I Love You!";
  char str3[100] = "I        Love      You!   ";
  int strLen = strlen(str);
  int strLen2 = strlen(str2);
  int strLen3 = strlen(str3);
  printf("str len:%d \n",strLen);
  printf("str2 len:%d \n",strLen2);
  printf("str3 len:%d \n",strLen3);

打印结果:

str len:11 
str2 len:11 
str3 len:26

可以看到str2和str统计的数量是一样的。

从上面结果来看,数组的大小并不决定这个字符串的长度。

strlen函数只统计“\0”结尾之前的字数,而且不算“\0”这个字符。

2、strcat 和 strncat函数

不了解strcat函数可以直接在linux的命令行中输入:man strcat

就可以看到有两个相关的函数:

SYNOPSIS
       #include <string.h>
       char *strcat(char *dest, const char *src);
       char *strncat(char *dest, const char *src, size_t n);

还有很详细的说文。

The  strcat()  function  appends  the src string to the dest string, overwriting the terminating null byte
       ('\0') at the end of dest, and then adds a terminating null byte.  The strings may not  overlap,  and  the
       dest  string  must have enough space for the result.  If dest is not large enough, program behavior is un‐
       predictable; buffer overruns are a favorite avenue for attacking secure programs.

这个strcat函数是用来拼接字符串的,分别传入dest和src字符串,最终把src拼接到dest中进行返回。

实验代码:

zhenghui@zhlinux:~/桌面/code/string$ 
zhenghui@zhlinux:~/桌面/code/string$ cat strcatTest.c 
#include <stdio.h>
#include <string.h>
int main(void)
{
  char str1[12] = " I ";
  char str2[100] = " Love ";
  char *pStr = " You!iiiiii ";
  int sl = strlen(str1);
  printf("str1 len :%d \n",sl);
  printf("str1=%s\n",str1);
  printf("str2=%s\n",str2);
  printf("pStr=%s\n",pStr);
  strcat(str1,str2);
  strcat(str1,pStr);
  printf("#####################\n");
  printf("str1 :%s \n",str1);
  sl = strlen(str1);
  printf("str1 len :%d \n",sl);
  return 0;
}
zhenghui@zhlinux:~/桌面/code/string$

执行结果:

用法很简单,就是传入两个需要拼接的字符串即可

zhenghui@zhlinux:~/桌面/code/string$ make strcatTest && ./strcatTest
cc     strcatTest.c   -o strcatTest
str1 len :3 
str1= I 
str2= Love 
pStr= You!iiiiii 
#####################
str1 : I  Love  You!iiiiii  
str1 len :21 
zhenghui@zhlinux:~/桌面/code/string$

相比较来说,strncat比strcat安全一些。

例如:

如果a的空间是有限的,b的长度又很大。那么就会超出了a的大小。

那么为了安全,就可以使用strncat来指定拼接的大小。

strcat(a,b);

为了安全,我们可以使用strncat:

zhenghui@zhlinux:~/桌面/code/string$ 
zhenghui@zhlinux:~/桌面/code/string$ 
zhenghui@zhlinux:~/桌面/code/string$ cat strcatTest.c 
#include <stdio.h>
#include <string.h>
int main(void)
{
  char str1[12] = " I ";
  char str2[100] = " Love ";
  char *pStr = " You!iiiiii ";
  int sl = strlen(str1);
  printf("str1 len :%d \n",sl);
  printf("str1=%s\n",str1);
  printf("str2=%s\n",str2);
  printf("pStr=%s\n",pStr);
  //strcat(str1,str2);
  //strcat(str1,pStr);
  strncat(str1,str2,sizeof(str1) - strlen(str1) - 1);
  strncat(str1,pStr,sizeof(str1) - strlen(str1) - 1);
  printf("#####################\n");
  printf("str1 :%s \n",str1);
  sl = strlen(str1);
  printf("str1 len :%d \n",sl);
  return 0;
}
zhenghui@zhlinux:~/桌面/code/string$

可以看到结果也是正常的:

zhenghui@zhlinux:~/桌面/code/string$ make strcatTest && ./strcatTest
cc     strcatTest.c   -o strcatTest
str1 len :3 
str1= I 
str2= Love 
pStr= You!iiiiii 
#####################
str1 : I  Love  Y 
str1 len :11 
zhenghui@zhlinux:~/桌面/code/string$

我们使用sizeof(str1) - strlen(str1)就可以计算出str1所剩余的空间,-1是为了给“\0”留出空间。

strncat(str1,str2,sizeof(str1) - strlen(str1) - 1);

3、strcmp 和 strncmp函数

在C语言日常开发中,strcmp是非常常用的,我们做字符串比较,两个字符串是否相等,我们直接调用这个函数就可以很好的解决这个难题。

我们仍然可以使用:man strcmp来查看帮助手册:

SYNOPSIS
       #include <string.h>
       int strcmp(const char *s1, const char *s2);
       int strncmp(const char *s1, const char *s2, size_t n);
DESCRIPTION
       The strcmp() function compares the two strings s1 and s2.  The locale is not taken into account (for a lo‐
       cale-aware comparison, see strcoll(3)).  It returns an integer less than, equal to, or greater  than  zero
       if s1 is found, respectively, to be less than, to match, or be greater than s2.
       The strncmp() function is similar, except it compares only the first (at most) n bytes of s1 and s2.
RETURN VALUE
       The strcmp() and strncmp() functions return an integer less than, equal to, or greater than zero if s1 (or
       the first n bytes thereof) is found, respectively, to be less than, to match, or be greater than s2.

这是用来比较两个字符串的。

原型如下:

SYNOPSIS
       #include <string.h>
       int strcmp(const char *s1, const char *s2);
       int strncmp(const char *s1, const char *s2, size_t n);

我们需要传递两个字符串s1和s2;

返回值是:

返回值是一个大于、小于或等于0的值。

如果strcmp(s1,s2)==0:说明s1和s2相等;

如果strcmp(s1,s2) > 0:说明s1 > s2;

如果strcmp(s1,s2) < 0:说明s1 < s2;

当然了<=和>=运算符也是可以使用的。

RETURN VALUE
       The strcmp() and strncmp() functions return an integer less than, equal to, or greater than zero if s1 (or
       the first n bytes thereof) is found, respectively, to be less than, to match, or be greater than s2.

实验代码:

zhenghui@zhlinux:~/桌面/code/string$ cat strcmpTest.c 
#include <stdio.h>
#include <string.h>
int main(void)
{
  char str1[12] = "abc";
  char *str2 = "ABC";
  printf("str1=%s\n",str1);
  printf("str2=%s\n",str2);
  printf("#####################\n");
  int res1 = strcmp(str1,str2);
  printf("strcmp(str1,str2) :%d \n",res1);
  int res2 = strcmp(str2,str1);
  printf("strcmp(str2,str1) :%d \n",res2);
  if(res1 > 0)
  {
    printf("res1:%s > %s \n",str1,str2);
  }
  if(res2 < 0)
  {
    printf("res2:%s < %s \n",str2,str1);
  }
  return 0;
}
zhenghui@zhlinux:~/桌面/code/string$

实验结果:

zhenghui@zhlinux:~/桌面/code/string$ make strcmpTest && ./strcmpTest
make: “strcmpTest”已是最新。
str1=abc
str2=ABC
#####################
strcmp(str1,str2) :32 
strcmp(str2,str1) :-32 
res1:abc > ABC 
res2:ABC < abc 
zhenghui@zhlinux:~/桌面/code/string$

4、strcpy 和 strncpy函数

从字面上看,看着就很想copy拷贝。

没错,这个就是拷贝的功能。

同样,我们使用:man strcpy来查看帮助手册。

也有很详细的说明:

SYNOPSIS
       #include <string.h>
       char *strcpy(char *dest, const char *src);
       char *strncpy(char *dest, const char *src, size_t n);
DESCRIPTION
       The  strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to
       the buffer pointed to by dest.  The strings may not overlap, and the destination string dest must be large
       enough to receive the copy.  Beware of buffer overruns!  (See BUGS.)
       The strncpy() function is similar, except that at most n bytes of src are copied.  Warning: If there is no
       null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
       If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total
       of n bytes are written.

废话不多说,直接上代码:

zhenghui@zhlinux:~/桌面/code/string$ 
zhenghui@zhlinux:~/桌面/code/string$ cat strcpyTest.c 
#include <stdio.h>
#include <string.h>
int main(void)
{
  char str1[12] = " abc aowmdi9";
  char *str2 = " ABC 9999";
  printf("str1=%s\n",str1);
  printf("str2=%s\n",str2);
  printf("#####################\n");
  strcpy(str1,str2);
  printf("strcpy(str1,str2):%s \n",str1);
  return 0;
}
zhenghui@zhlinux:~/桌面/code/string$

实验结果:

zhenghui@zhlinux:~/桌面/code/string$ make strcpyTest && ./strcpyTest
make: “strcpyTest”已是最新。
str1= abc aowmdi9
str2= ABC 9999
#####################
strcpy(str1,str2): ABC 9999 
zhenghui@zhlinux:~/桌面/code/string$

通过下面代码可以看出,直接把str2的内容拷贝到了str1中,直接覆盖了。

strcpy(str1,str2);

重点:其实strcpy是用来解决我们不能用赋值运算符来赋值的操作的问题

那么什么时候,不能用“=”号来赋值呢?

例如:

我们定义一个数组,一开始不赋值,然后等我们业务逻辑到达的时候,再赋值:

char str3[10];

假设到了该赋值的地方:

str3 = "zhenghui";

这个地方会执行错误的。

可以看下执行结果:

zhenghui@zhlinux:~/桌面/code/string$ make strcpyTest && ./strcpyTest
cc     strcpyTest.c   -o strcpyTest
strcpyTest.c: In function ‘main’:
strcpyTest.c:11:7: error: assignment to expression with array type
   11 |  str3 = "zhenghui";//错误
      |       ^
make: *** [<内置>:strcpyTest] 错误 1
zhenghui@zhlinux:~/桌面/code/string$

像这种特殊的赋值,我们可以利用strcpy来解决:

strcpy(str3,"zhenghui");

执行就没问题了。

如果带参数n的话,就是用来限制copy的数据值的多少,也是为了安全才有的。

目录
相关文章
|
19天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
39 10
|
22天前
|
存储 算法 C语言
C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项
本文深入探讨了C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项,并通过案例分析展示了实际应用,旨在帮助读者提高编程效率和代码质量。
68 4
|
6月前
|
NoSQL 程序员 Redis
C语言字符串的设计缺陷
C语言字符串的设计缺陷
63 1
|
2月前
|
C语言 C++
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
【C语言】解决不同场景字符串问题:巧妙运用字符串函数
|
3月前
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]=&quot;hello&quot;`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
106 8
|
3月前
|
存储 Serverless C语言
【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
217 7
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
127 4
|
3月前
|
C语言
C语言 字符串操作函数
本文档详细介绍了多个常用的字符串操作函数,包括 `strlen`、`strcpy`、`strncpy`、`strcat`、`strncat`、`strcmp`、`strncpy`、`sprintf`、`itoa`、`strchr`、`strspn`、`strcspn`、`strstr` 和 `strtok`。每个函数均提供了语法说明、参数解释、返回值描述及示例代码。此外,还给出了部分函数的自实现版本,帮助读者深入理解其工作原理。通过这些函数,可以轻松地进行字符串长度计算、复制、连接、比较等操作。
|
4月前
|
C语言
【C语言】字符串及其函数速览
【C语言】字符串及其函数速览
34 4
|
4月前
|
C语言
【C语言篇】字符和字符串以及内存函数详细介绍与模拟实现(下篇)
perror函数打印完参数部分的字符串后,再打印⼀个冒号和⼀个空格,再打印错误信息。
66 0