第11章字符串和字符串函数


title: 第十一章 字符串和字符串函数
author: HardyDragon
tags: C Notes


第十一章 字符串和字符串函数

  • 使用字符串的几种方式,赋值都是字符串用双引号括起来。

    1. 字符数组赋值
    2. 字符指针赋值
    3. 字符串常量
    4. puts() 函数显示字符串,参数可以是字符数组或指针

    注意puts() 函数也是stdio.h 头文件里的输入输出函数,puts() 函数只显示字符串且自动在字符串末尾加上换行符。

    // strings1.c --使用字符串
    #include<stdio.h>
    #define MSG "I am a symbolic string constant"
    #define MAXLENGTH 81
    int main(int argc, char const *argv[])
    {
        char words[MAXLENGTH] = "I am a string in an array.";
        const char* pt1 = "Something is pointing at me.";
        puts("Here are some strings:");
        puts(MSG);
        puts(words);
        puts(pt1);
        words[8] = 'p';
        puts(words);
    
        return 0;
    }
    
    

    result:

    Here are some strings:
    I am a symbolic string constant
    I am a string in an array.
    Something is pointing at me.
    I am a spring in an array.
    
    // strptr.c -- 将字符串看做指针
    #include <stdio.h>
    int main(int argc, char const *argv[])
    {
        printf("%s ,%p,%c\n", "We", "are", *"space");
        return 0;
    }
    
    

    result:

    We ,0000000000404000,s
    
  • 字符串的绝大数的操作通过指针完成。即让指针指向字符串来修改。

  • 字符串输入时要先给字符串分配空间,可用数组显式指明数组大小。或者用其他C库函数分配内存。

    • 使用gets() 函数,读取整行输入,直到遇到换行符,然后丢弃换行符,在最后添加一个空字符结束;gets() 经常和puts() 配合使用,puts() 显示字符串并自动换行相当于python的print()。

      // getsputs.c -- 使用gets() 和 puts()
      #include<stdio.h>
      #define STLEN 81
      int main(int argc, char const *argv[])
      {
          char words[STLEN];
          puts("Enter a string ,please.");
          gets(words);
          printf("Your string twice:\n");
          printf("%s\n",words);
          puts(words);
          puts("Done!");
          
          return 0;
      }
      
      

      result:

      Enter a string ,please.
      hello world
      Your string twice:
      hello world
      hello world
      Done!
      

      如果给定的初始空间过小,不能容纳字符串,会爆分段错误;意思是该程序试图访问未分配的内存。所以这可能会造成系统的安全问题,C99建议不要使用,但是保留了,可以说是一把双刃剑,使用合理就比较方便。C11就不客气的删除了gets() 函数。C11 使用get_s() 代替。

      fget() 函数(和fputs())

      fgets() 通过第二参数指明了读入字符的最大数量,用于处理文件传输。

      fgets() 读到一个换行符会把它存储在字符串中。这个和gets() 不同,因为gets() 只是单行读取,会丢弃换行符。

      第三个参数指明要读入的文件。

    // fgets1.c -- 使用fgets() 和 fputs()
    #include <stdio.h>
    #define STRLEN 14
    int main(int argc, char const *argv[])
    {
        char words[STRLEN];
        puts("输入一个字符串!");
        // 如果要从键盘读取输入用stdin作为参数
        fgets(words, STRLEN, stdin);
        printf("Your string twice (puts(),then fputs()):\n");
        puts(words);
        // 如果要显示在计算机显示器上使用stdout作为参数
        fputs(words, stdout);
    
        puts("输入另一个字符串。");
        fgets(words, STRLEN, stdin);
        printf("Your string twice (puts(),then fputs()):\n");
        puts(words);
        fputs(words, stdout);
        puts("Done!");
    
        return 0;
    }
    
    

    result:

    输入一个字符串!
    aaa
    Your string twice (puts(),then fputs()):
    aaa
    
    aaa
    输入另一个字符串。
    aaaaaaaaaaaaaaaaaaaaa
    Your string twice (puts(),then fputs()):
    aaaaaaaaaaaaa
    aaaaaaaaaaaaaDone!
    

    注意puts() 会在带输出字符串末尾添加一个换行符,而fputs() 不会。

    以上的第一个输出便是有两个换行符,fgets() 不会抛弃换行符所以读取到了便保留了下来,第二个没有读取到换行就没有空行。

    // fgets2.c -- 使用fgets() 和 fputs()
    #include <stdio.h>
    #define STLEN 10
    int main(int argc, char const *argv[])
    {
        char words[STLEN];
        puts("输入字符串(空行退出):");
        while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n')
        {
            /* code */
            fputs(words, stdout);
        }
        puts("Done!");
    
        return 0;
    }
    
    

    result:

    输入字符串(空行退出):
    by the way ,the gets()
    by the way ,the gets()
    also sadja k
    also sadja k
    sdaksdas
    sdaksdas
    
    Done!
    

    如果需要删除存储在字符串中的换行符,或丢弃数组装不下的字符:

    // fgets3.c
    #include <stdio.h>
    #define STLEN 10
    int main(int argc, char const *argv[])
    {
        char words[STLEN];
        int i;
    
        puts("输入一个字符串空行退出:");
        while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n')
        {
            /* code */
            i = 0;
            while (words[i] != '\n' && words[i] != '\0')
            {
                i++;
            }
            if (words[i] == '\n')
            {
                words[i] = '\0';
            }else
            {
                while (getchar()!='\n')
                {
                    /* code */
                    continue;
                }
            }
            puts(words);
        }
        puts("Done!");
    
        return 0;
    }
    
    

    result:

    输入一个字符串空行退出:
    this
    this
    progran sdada
    progran s
    dsakkasa ldk
    dsakkasa
    
    Done!
    

    遍历字符串遇到换行符或者空字符就将其替换为空字符,如果先遇到空字符就丢弃剩余的字符。

  • 注意空指针和空字符的区别:都可以用0表示,但是两者所占字节不同,一个是字符占1字节,一个是指针占4字节。

  • gets_s() 函数和fgets() 类似,但是不会保存换行符。

  • scanf() 函数注意读取的缓冲区

  • puts() 函数独占一行

  • fputs() 不保留换行符。

    #include <stdio.h>
    int main()
    {
        char line[81];
        while (fgets(line, 81, stdin))
        {
            /* code */
            fputs(line, stdout);
        }
        puts("Done!");
        return 0;
    }
    
    

    result:

    hello
    hello
    das
    das
    ^Z
    Done!
    
    • 熟悉以下的判断手法

      while(*string)
      

      当指针指向空字符时为0即假。

    // put2.c -- 统计打印的字符数
    #include <stdio.h>
    int put2(const char *string);
    int main(int argc, char const *argv[])
    {
        int count = 0;
        char *string = "hello";
        count = put2(string);
        printf("字符数量:%d\n", count);
        return 0;
    }
    int put2(const char *string)
    {
        int count = 0;
        while (*string)
        {
            /* code */
            putchar(*string++);
            count++;
        }
        putchar('\n');
    
        return count;
    }
    

    result:

    hello
    字符数量:5
    
  • 字符串函数 string.h 头文件

    strlen() 统计字符串长度,修改字符串时注意不要使用const

  • strcat() 连接两个字符串,将第二个字符串附加到字符串末尾,返回第一个参数的地址。

  • strncat() 函数 有第三个参数指定了两个字符合并时在加到第n个字符时停止。

  • strcmp() 函数两个字符串比较

  • strcpy() 拷贝整个字符串,相当于字符串赋值运算符。

    // copy2.c -- 使用strcpy()
    #include <stdio.h>
    #include <string.h>
    #define WORDS "beast"
    #define SIZE 40
    int main(int argc, char const *argv[])
    {
        const char *orig = WORDS;
        char copy[SIZE] = "Be the best that you can be.";
        char *ps;
    
        puts(orig);
        puts(copy);
        ps = strcpy(copy + 7, orig);
        puts(copy);
        puts(ps);
    
        return 0;
    }
    
    

    result:

    beast
    Be the best that you can be.
    Be the beast
    beast
    

    image-20201027132625444

  • 使用strncpy() 拷贝字符串较安全。
    如果目标空间可以容纳字符串的副本,那么从字符串拷贝的空字符便是副本的结尾,如果装不下副本就将最后一个元素设置为空字符。

  • sprintf() 函数声明在stdio.h 中,和printf类似,但是它是把数据写入字符串一个字符串数组。

  • 利用strcmp 来进行字符串排序。

  • ctype.h 字符函数和字符串

    1. toupper() 将字符串转换为大写
    2. ispunct() 统计字符串的标点符号个数
    3. strchr() 处理fgets() 读入字符串的换行符
  • 命令行参数 是允许编译后的程序同一行的附加项例如:

    fuss -r Ginger
    

    一个C程序可以读取并使用这些附加项,例如通过main() 函数读取这些附加项

    // repear.c -- 带参数的main()
    #include <stdio.h>
    int main(int argc, char const *argv[])
    {
        int count;
        printf("The command line has %d aargument:\n", argc - 1);
        for (count = 1; count < argc; count++)
        {
            /* code */
            printf("%d:%s\n", count, argv[count]);
        }
        printf("\n");
    
        return 0;
    }
    
    

    result:

    C:\Git\c-primer-plus-notes\code>repear.c.exe a b c
    The command line has 3 aargument:
    1:a
    2:b
    3:c
    

    其中 repear.c.exe 是编译后的可执行程序,可以附带参数运行。

    C编译器允许main() 没有参数或者有两个参数(有些标准扩展还可以有更多的参数),当有两个参数时,第一个参数是命令行中的字符串数量,用空格表示字符串的结束和下一个字符串的开始。

    例如:repear.c.exe a b c 的argc 为4;

    将每个字符串存储在指针数组,放在第二个参数中。

    可以用atoi() 函数将字符串转为对应的整数,

    // hello.c -- 把命令行参数转换为数字
    #include <stdio.h>
    #include <stdlib.h>
    int main(int argc, char *argv[])
    {
        int i, times;
        if (argc < 2 || (times = atoi(argv[1])) < 1)
        {
            /* code */
            printf("Usage:%s positive-number\n", argv[0]);
        }
        else
        {
            for (i = 0; i < times; i++)
            {
                /* code */
                printf("Hello,good looking!\n");
            }
        }
    
        return 0;
    }
    
    

    result:

    C:\Git\c-primer-plus-notes\code>hello.c.exe 3
    Hello,good looking!
    Hello,good looking!
    Hello,good looking!
    ----------------------
    C:\Git\c-primer-plus-notes\code>hello.c.exe a
    Usage:hello.c.exe positive-number
    

}
else
{
for (i = 0; i < times; i++)
{
/* code */
printf(“Hello,good looking!\n”);
}
}

  return 0;

}


result:

```bash
C:\Git\c-primer-plus-notes\code>hello.c.exe 3
Hello,good looking!
Hello,good looking!
Hello,good looking!
----------------------
C:\Git\c-primer-plus-notes\code>hello.c.exe a
Usage:hello.c.exe positive-number
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值