流心
发布于 2024-05-12 / 4 阅读
0

字符串

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

    • 0或‘\0’是一样的,但是和'0'不同

  • 0标志字符串结束,但它不是字符串的一部分

    • 就散字符串长度不包含这个0

  • 字符串以数组的方式存在,以数组或指针方式访问

  • string.h 中有很多处理字符串的函数

  • \0 是整数 0 ,'0'是Ascll码的0

  • char *str = "Hello";

    • 表示有一个 str 指针指向字符数组内容是 Hello

  • char word[] = "Hello";

    • 表示一个字符数组里面有一个 Hello

    • 表示有一个字符数组 line 里面有十个字节大小然后放了五个字符和一个 0

  • 字符串常量

    • “Hello”

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

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

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

    • 不能用运算符对字符串做运算

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

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

字符串常量

char *s = "Hello,world";

  • s 是一个指针,初始化为指向一个字符串常量

  • 由于这个常量所在的地方,实际上 s 是 const char* s,但是由于历史原因,编译器接受不带 const 的写法

  • 但是试图对 s 所指的字符串做写入会导致严重的后果

  • 如果需要修改字符串,应该用数组:

    • char s[] = "Hello world";

指针和数组

  • char *s = "Hello,world";

  • char word[] = "Hello,world";

  • 当需要程序里面有个字符串的时候,怎么选择

    • 数组:这个字符串在这,作为本地变量空间自动回收

    • 指针:这个字符串不知道在哪,处理常数,动态分配空间

  • 字符串可以表达为 char* 的形式

  • char* 不一定是字符串指向字符的指针,可能指向是字符的数组(和int*一样)

字符串赋值

  • char *t = "title";

  • char *s;

  • s = t;

  • 没有产生新的字符串,只是让指针s指向t所指的字符串,对s的操作都是对t做

字符串输入输出

  • char string[8];

  • scanf("%s",string);

  • printf("%s",string);

  • scanf 读入一个单词直到出现空格、tab、回车为止

  • scanf 是不安全的,因为不知道要读入的内容的长度

安全输入

  • char string[8];

  • scanf("%7s",string);

  • 在%和s之间的数字表示最多允许读入的字符数量,这个数字应该比数组的大小一致

常见错误

  • char *string;

  • scanf("%s",string);

  • 以为 char* 是字符串类型,定义一个字符串类型的变量 string 就可以直接使用了

  • 由于没有对 string 初始化为0,所以不一定每次运行都出错

空字符串

  • char buffer[100] = " ";

    • 这是空字符串,buffer[0] == '\0';

  • char buffer[] = " ";

    • 这个数组的长度只有1

字符串数组

  • char **a

    • a是一个指针,指向另外一个指针,那个指针指向一个字符(串)

  • char a[][]

    • 字符串二维数组,通常第二位要有确切的数字 比如 char a[][10] 否则会报错

程序参数

  • int main(int argc,char const * argv[])

  • argv[0] 是命令本身

    • 当使用 Unix 的符号链接时,反映符号链接的名字

单字符输入输出

#include<stdio.h>
int main(int argc,char const *argv[])
{
    int ch;
    while((ch = getchar()) != EOF){
        putchar(ch);
    }

    printf("EOF\n");

    return 0;
}
  • putchar

    • int putchar(int c);

    • 向标准输出写一个字符

    • 返回写了几个字符,EOF(-1)表示写失败

  • getchar

    • int getchar(void);

    • 从标准输入读入一个字符

    • 返回类型是int是为了返回EOF(-1)

      • windows -> Ctrl-Z

      • Unix -> Ctrl-D

字符串函数

  • strlen

    • size_t strlen(const char *s);

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

  • strcmp

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

    • 比较两个字符串,返回:

      • 0:s1 == s2

      • 1:s1 > s2

      • -1:s1 < s2

#include<stdio.h>
#include<string.h>
int main(int argc,char const *argv[])
{
    char s1[] = "abc";
    char s2[] = "Abc ";
    printf("%d\n",strcmp (s1,s2));
    printf("%d\n",'a'-'A');
    return 0;

    // 如果s1和s2内容相同则 输出 0
    // 如果s2多加一个空格则 输出-1
    /** strcmp 给出的是 s1 和 s2 不相等字符的差值比较数组
    *   s1[0] 和 s2[0] 两个是否一样不一样就做个减法取出差值
    */

}
  • strcpy

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

    • 把 src 的字符串拷贝到 dst

      • restrict 表明 src 和 dst 不重叠(C99)重叠会有冲突

    • 返回 dst

      • 为了能链起代码来

    • char dst = (char*)malloc(strlen(src)+1); 注意事项:一定要+1

    • strcpy(dst,src);

#include<string.h>

char* mycpy(char* dst,const char* src)
{   
/*     int idx = 0;
    while(src[idx]){
        dst[idx] = src[idx];
        idx++;
    }
    dst[idx] = '\0'; */

    char* ret = dst;
    while ( *dst++ == *src++ );
    *dst = '\0';
    
    return dst;
}

int main(int argc,char const *argv[])
{
    char s1[] = "abc";

    char s2[] = "abc";

    strcpy(s1,s2);
    
    return 0;
}
  • strcat

  • strchr

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

    • char strrchar(const char *s,int c);

    • 返回 NULL 表示没找到

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc,char const *argv[])
{
    char s[] = "hello";
    // 如果有两个 ll 会在查到第一个 l 就输出
    char *p = strchr(s,'l'); // llo
    // printf("%s\n",p); // llo


    /** 如果想输出第二个 l 则 p+1
    *   p = strchr(p+1,'l'); // lo
    *   printf("%s\n",p); 
    */

    /** 
     * 想输出 l 前面的字符,创建 c 指向 p
     *   让 *p 等于 '\0'
     *   char c = *p;
     *   p = '\0';
     *   char *t = (char*)malloc(strlen(p)+1);
     *   strcpy(t,s);
    printf("%s\n",t); // he
    */
    
    char *t = (char*)malloc(strlen(p)+1);
    strcpy(t,p);
    printf("%s\n",p); // llo
    free(t);
    return 0;
}
  • strstr

    • char *strstr(const char *s1,const char s2);

      • strstr 函数用于查找字符串 s2 在字符串 s1 中第一次出现的位置。如果找到,返回指向该位置的指针;如果找不到,则返回 NULL

      • const char *s1:指向第一个字符串(主字符串)的指针。

      • const char *s2:指向第二个字符串(子字符串)的指针。

      • 返回值:返回一个指向第一个匹配位置的指针。如果没有找到子字符串 s2,则返回 NULL

      • strstr 是区分大小写的,即 "Hello""hello" 是不同的字符串。

      • 该函数是非常常用的字符串查找函数,但它并不安全,在使用时应确保传递的字符串指针是有效的,并且要避免传递 NULL 指针

    • 解释:

      • strstr(s1, s2) 会查找 s2s1 中的第一次出现。如果找到,它返回一个指向该子字符串的指针。如果没有找到,它返回 NULL

      • result - s1 计算匹配子字符串的位置(即偏移量),通过将返回的指针与原字符串的起始指针相减。

#include <stdio.h>
#include <string.h>

int main() {
    const char *s1 = "Hello, world!";
    const char *s2 = "world";
    
    char *result = strstr(s1, s2);
    
    if (result) {
        printf("Found '%s' at position: %ld\n", s2, result - s1);
    } else {
        printf("'%s' not found in '%s'.\n", s2, s1);
    }

    return 0;
}
  • char strcassestr(const char *s1, const char *s2);

    • 解释

      • const char *s1:指向主字符串的指针。

      • const char *s2:指向要查找的子字符串的指针。

      • 返回值:返回指向第一个匹配子字符串的位置的指针(不区分大小写)。如果没有找到匹配的子字符串,返回 NULL

      • strcasestr(s1, s2) 查找 s2s1 中的第一次出现,并忽略大小写。如果找到,它返回一个指向该位置的指针;如果找不到,则返回 NULL

    • 功能

      • strcasestrstrstr 类似,但它是大小写不敏感的,即在查找时会忽略字符的大小写。

报错

'strcpy' is deprecated: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use CRTSECURE_NO_WARNINGS. See online help for details.

将下面宏定义添加到代码开头

#define _CRT_SECURE_NO_WARNINGS