当前位置 : 主页 > 编程语言 > java >

【C primer Plus】字符串和字符串函数

来源:互联网 收集:自由互联 发布时间:2022-06-23
题目 # includestdio.h int main ( ) { printf ( "%s, %p, %c\n" , "We" , "are" , * "space farers" ) ; return 0 ; } 上面程序的输出是什么? 参考答案 jiaming @jiaming-System-Product-Name: / tmp $ . / strptr . o We , 0x56518dbe470

题目

# include<stdio.h>
int main()
{
printf("%s, %p, %c\n", "We", "are", *"space farers");
return 0;
}

上面程序的输出是什么?

参考答案

jiaming@jiaming-System-Product-Name:/tmp$ ./strptr.o
We, 0x56518dbe4704, s

说明
​​​printf()​​​ 根据 ​​%s​​​ 转换说明打印 ​​We​​​,根据 ​​p​​​ 转换说明打印一个地址, ​​*"space farers"​​​ 表示该字符串所指向地址上储存的值,应该是字符串 ​​space farers​​ 的首字符。



文章目录

  • ​​1. 在程序中定义字符串​​
  • ​​1.1 字符串字面量(字符串常量)​​
  • ​​1.2 字符串数组和初始化​​
  • ​​1.3 数组和指针​​
  • ​​1.4 数组和指针的区别​​
  • ​​1.5 字符串数组​​
  • ​​1.6 指针和字符串​​
  • ​​2. 字符串输入​​
  • ​​2.1 分配空间​​
  • ​​3. 自定义输入/输出函数​​
  • ​​字符串函数​​
  • ​​0. scanf()函数​​
  • ​​1. gets()函数​​
  • ​​2. gets_s()函数​​
  • ​​3. fgets() 函数​​
  • ​​4. puts() 函数​​
  • ​​5. fputs() 函数​​
  • ​​6. printf() 函数​​
  • ​​7. strlen() 函数​​
  • ​​8. strcat() 函数​​
  • ​​9. strncat() 函数​​
  • ​​10. strcmp() 函数​​
  • ​​11. strncmp() 函数​​
  • ​​12. strcpy() 函数​​
  • ​​13. strncpy() 函数​​
  • ​​14. sprintf() 函数​​
  • ​​其他字符串函数​​

1. 在程序中定义字符串

1.1 字符串字面量(字符串常量)

// 双引号中的字符会被编译器自动加入'\0', 存储在内存中,存储在字符常量区,静态存储
char greeting1[50] = "Hello, and"" how are"" you" " today!"; // ANSI C 标准视为串联起来的字符串字面量

1.2 字符串数组和初始化

定义字符串数组时,需要让编译器知道需要多少空间:

  • 用足够空间的数组存储字符串;
  • 让编译器自动计算数组长度;
  • const char m1[40] = "Limit yourself to one line's worth."; // const 表明不会更改这个字符串
    const char m2[40] = {'L', 'i', 'm', 'i', 't', ' ', 'y', 'o', 'u', 'r', 's', 'e', 'l', 'f', ' ', 't', 'o', ' ', 'o', 'n', 'e', ' ', 'l', 'i', 'n', 'e', "'", 's', ' ', 'w', 'o', 'r', 't', 'h', '.'};
    const char m3[] = "Limit yourself to one line's worth."; // 编译器会根据字符串末尾的空字符自动计算数组的大小,只能用在数组初始化时
    int n = 8;
    char crumbs[n]; // C99 标准之前无效,C99 标准之后这种数组是变长数组

    1.3 数组和指针

    const char * pt1 = "Something is pointing at me." // 字符串字面量被视为const数据,由于pt1指向这个const数据,所以应该把pt1声明为指向const数据的指针。不能改变指向的数据,但是可以改变指向。
    const char ar1[] = "Something is pointing at me." // 把字符串字面量拷贝给数组,如果没有 const 限定,可以随意更改数据。
    • 指针形式(*pt1)也使得编译器为字符串在静态存储区预留 29 个元素的空间。一旦开始执行程序,它会为指针变量 pt1 留出一个储存位置,并把字符串的地址储存在指针变量中,该变量最初指向该字符串的首字符,但是它的值可以改变,因此,可以使用递增运算符。
    • 数组形式在计算机内存中分配为一个内含 29 个元素的数组(每个元素对应一个字符,还加上一个末尾的空字符),每个元素被初始化为字符串字面量对应的字符。字符串作为可执行文件的一部分储存在数据段中。当把程序载入内存时,也载入了程序中的字符串。字符串储存在静态存储区,但是,当程序开始运行时才会为该数组分配内存。此时字符串有两个副本,一个是在静态内存中的字符串字面量,另一个是储存在 ar1 数组中的字符串。
    #define MSG "abc"
    char arr[] = MSG;
    const char* pt = MSG; // pt 和 MSG的地址相同

    1.4 数组和指针的区别

    char * head = "Something is pointing at me." // 字符串变量
    char head[] = "Something is pointing at me." // 字符串常量
  • 都可以使用数组表示法 head[index];
  • 都能进行指针加法 *(head+index);
  • 只有指针表示法可以进行递增操作 *(head++);
  • 建议把指针初始化为字符串字面量时使用 const 限定符:

    const char* p = "Klingon"; // 推荐用法

    1.5 字符串数组

    # define SLEN 40
    # define LIM 5
    // 含有5个指针的数组,40B,指针指向初始化时所用的字符串字面量的位置,这些字符串字面量被储存在静态内存中
    const char *mytalents[LIM] = {
    "Adding numbers swiftly",
    "Multiplying accurately",
    "Stashing data",
    "Following instructions to the letter",
    "Understanding the C language"
    };
    // 含有5个数组的数组 5x40=200B,数组则储存着字符串字面量的副本,所以每个字符串都被储存了两次
    char yourtalents[LIM][SLEN] = {
    "Walking in a strarght line",
    "Sleeping",
    "Watching television",
    "Mailing letters",
    "Reading email"
    };

    1.6 指针和字符串

    字符串的绝大多数操作都是通过指针完成的。

    2. 字符串输入

    2.1 分配空间

    char *name;
    scanf("%s", name); // 未初始化指针
    char name[80]; // 初始化空间

    3. 自定义输入/输出函数

    不一定非要使用 C 库中的标准函数,如果无法使用这些函数或者不想用它们,完全可以在 ​​getchar()​​​ 和 ​​putchar()​​的基础上自定义所需的函数。


    字符串函数

    0. scanf()函数

    ​​scanf()​​​ 配合 ​​%s​​ 只能读取一个单词。

    如果使用 %s 转换说明,以下一个空白字符(空行、空格、制表符和换行符)作为字符串的结束(字符串不包括空白字符),如果指定了字段宽度,如 %10s,那么 scanf() 将读取 10 个字符或读到第 1 个空白字符停止。

    【C primer Plus】字符串和字符串函数_数组

    1. gets()函数

    读取整行输入,直到遇到换行符,然后丢弃换行符,储存其余字符,自动添加空字符,但是它无法检查数组是否装得下输入行,​​gets()​​ 函数只知道数组的开始处,并不知道数组中有多少个元素。

    **如果输入的字符串过长,会导致缓冲区溢出,即多余的字符超出了指定的目标空间。**如果这些多余的字符只是占用了尚未使用的内存,就不会立即出现问题;如果它们擦写掉程序中的其他数据,会导致程序异常终止。过去,有些人通过系统编程,利用 ​​gets()​​​ 插入和运行一些破坏系统安全的代码。制定 C99 标准的委员会将摒弃 ​​gets()​​​ 的建议放入了标准,承认了 ​​gets()​​ 的问题并建议不使用它。

    Segmentation fault. Unix 系统中,这条消息说明该程序试图访问未分配的内存。

    ​​gets()​​ 替代品:

    • fgets()
    • gets_s()
    • s_gets()

    【C primer Plus】字符串和字符串函数_c语言_02

    2. gets_s()函数

    和 fgets() 的区别:

    • gets_s() 只从标准输入中读取数据,没有第三个参数。
    • gets_s() 读到换行符,会丢弃,非存储。
    • 如果 gets_s() 读到最大字符数都没有读到换行符,会执行以下几步。首先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针,接着调用依赖实现的处理函数,以中止或退出程序。

    3. fgets() 函数

    通过第 2 个参数限制读入的字符数来解决溢出的问题,专门用于处理文件输入,和 gets() 的区别:

    • fgets() 第 2 个参数指明了读入字符的最大数量,如果该参数的值为 n,那么 fgets() 将读入 n-1 个字符,或者读到遇到的第一个换行符为止。
    • 如果 fgets() 读到一个换行符,会把它存储在字符串中,而非丢掉。
    • 第 3 个参数指定了要读入的文件,如果读入从键盘输入的数据,则以 stdin 作为参数。
    char words[20];
    fgets(words, 10, stdin); // 输入 abc\n, words="abc\n\0";
    puts(words);

    空字符和空指针:

    空字符是整数类型,可以用 0 来表示,一个字符,占 1 个字节。

    空指针是指针类型,可以用 0 来表示,一个地址,通常 4 个字节。

    【C primer Plus】字符串和字符串函数_c++_03

    4. puts() 函数

    ​​puts()​​ 在显示字符串时会自动在其末尾添加一个换行符,该函数在遇到空字符时就停止输出。

    char c[] = {'a', 'b', 'c', '\0'};
    puts(c); // puts("abc") 只需要把字符串的地址作为参数传递给它即可,确保有空字符,否则不知道何时结束

    5. fputs() 函数

    是 puts() 函数针对文件定制的版本:

    • fputs 函数的第 2 个参数指明要写入数据的文件,如果要打印在显示器上,可以stdout作为参数。
    • fputs() 不会在输出的末尾添加换行符。
    • fgets() 保留输入中的换行符,fputs() 不在输出中添加换行符。

    【C primer Plus】字符串和字符串函数_c++_04

    6. printf() 函数

    与 puts() 不同的是,printf() 不会自动在每个字符串末尾加上一个换行符,计算机执行的时间更长。

    【C primer Plus】字符串和字符串函数_字符串_05

    7. strlen() 函数

    统计字符串的长度。

    【C primer Plus】字符串和字符串函数_c++_06

    8. strcat() 函数

    用于拼接字符串,接受两个字符串作为参数。接受两个字符串作为参数,把第 2 个字符串的备份附加在第 1 个字符串末尾,并把拼接后形成的新字符串作为第 1 个字符串,第 2 个字符串不变。

    【C primer Plus】字符串和字符串函数_c语言_07

    9. strncat() 函数

    strcat() 函数无法检查第 1 个数组能否容纳第 2 个字符串。

    ​​strncat(bugs, addon, 13)​​ 把 addon 字符串的内容附加给 bugs,在加到第 13 个字符或遇到空字符时停止。

    【C primer Plus】字符串和字符串函数_c语言_08

    10. strcmp() 函数

    比较的是字符串,非字符,可以比较储存在不同大小数组中的字符串。

    【C primer Plus】字符串和字符串函数_换行符_09

    11. strncmp() 函数

    可以比较两个字符串的不同字符位置。

    12. strcpy() 函数

    strcpy() 接受两个字符串指针作为参数,可以把指向源字符串的第 2 个指针声明为指针、数组名或字符串常量;而指向源字符串副本的第 1 个指针指向一个数据对象,且该对象有足够的空间储存源字符串副本。

  • strcpy() 的返回类型是 char*,该函数返回的第一个参数的值,即一个字符的地址。
  • 第一个参数不必指向数组的开始。​​strcpy(array+7, orig)​​。
  • 【C primer Plus】字符串和字符串函数_换行符_10

    13. strncpy() 函数

    更谨慎的选择 strncpy(),该函数的第 3 个参数指明可拷贝的最大字符数。​​strncpy(target, source, n)​​,把 source 中的 n 个字符或空字符之前的字符拷贝至 target 中。

    【C primer Plus】字符串和字符串函数_换行符_11

    14. sprintf() 函数

    该函数申明在 stdio.h 中,而不是在 string.h 中,该函数和 prinf() 函数类似,但是它是把数据写入字符串,而不是打印在屏幕上。

    【C primer Plus】字符串和字符串函数_c++_12

    其他字符串函数

    • ​​char *strcpy(char * restrict s1, const char * restrict s2);​​
    • ​​char *strncpy(char * restrict s1, const char * strict s2, size_t n)​​
    • ​​char *strcat(char * restrict s1, const char * restrict s2);​​
    • ​​char *strncat(char * restrict s1, const char * restrict s2, size_t n);​​
    • ​​int strcmp(const char * s1, const char * s2);​​
    • ​​char *strchr(const char *s, int c);​​
    • ​​char *strpbrk(const char * s1, const char * s2);​​
    • ​​char *strrchr(const char * s, int c);​​
    • ​​char *strstr(const char * s1, const char * s2);​​
    • ​​size_t strlen(const char *s);​​


    上一篇:查找可执行文件、创建多个用户账户
    下一篇:没有了
    网友评论