C语言 第九章 字符串

专栏指路

C语言笔记汇总

文章目录

  • 1 字符串定义
  • 2 字符数组和字符串
    • 2.1 一维字符数组的定义和初始化
    • 2.2 二维字符数组的定义和初始化
  • 3 字符串输入输出函数
    • 3.1 通用
    • 3.2 专用
      • 3.2.1 单个字符输入输出
        • 字符输入函数getchar()/getch()
        • 字符输出函数putchar()
      • 3.2.2 字符串输入输出
        • 字符串输入函数 gets()
        • 字符串输入函数 fgets()
        • 字符串输出函数 puts( )
  • 4 字符串处理函数
    • 字符串长度计算-strlen
    • 字符串复制函数-strcpy
    • 字符串链接函数-strcat
    • 字符串比较函数-strcmp
  • 5 应用举例
    • 5.1 字符变换
    • 5.2 顺序颠倒
    • 5.3 凯撒密码
    • 5.4 进制转换

1 字符串定义

一串以’\0’结尾的字符在C语言中被看作字符串
用双引号括起的一串字符是字符串常量,C语言自动为其添加’\0’结束符,比如“hello world”
'\0'等价于0,不是’0’

0 ‘\0’ ‘0’三者的关系:
0为int型,占4个字符;//在数值上是与’\0’的ASCII相等的。
‘\0’为转义字符,这是个八进制数,转化成十进制数为其对应的ASCII码值,即0
‘0’ 为字符,其ASCII码值为48

2 字符数组和字符串

C语言没有字符串数据类型,C语言中的字符串是以字符数组的形式来实现的。
字符数组,即数据类型是字符的数组char str[80];

2.1 一维字符数组的定义和初始化

  1. 字符型数据对数组进行初始化

char str[6] = {‘C’,‘h’,‘i’,‘n’,‘a’,‘\0’};
char str[10] = {‘C’, ‘H’, ‘I’, ‘N’, ‘A’};
如果数组没有’\0’,则数组不能当做字符串来处理

  1. 字符串常量直接对数组初始化

char str[6] = {“China”};
char str[6] = “China”;
用字符串初始化数组时最后自动添加’\0’

  1. 注意:
    • 数组的长度必须比字符串的元素个数多1,用以存放字符串结束标志’\0’。例如:char c[5] = "CHINA"; /*错误*/
    • 常用:用字符串初始化字符数组时,可以默认数组长度的定义,例如:char c[ ] = "CHINA"; /*数组大小默认为6*/
    • 数组名是地址常量(它表示C语言编译系统分配给该数组连续存储空间的首地址),不能将字符串直接赋给数组名。例如:char c[6]; c = "CHINA";/*错误*/
      C语言 第九章 字符串_第1张图片

2.2 二维字符数组的定义和初始化

二维数组可以看成特殊的一维数组,这个特殊的一维数组的元素又是一个一维数组。
C语言 第九章 字符串_第2张图片

C语言 第九章 字符串_第3张图片

3 字符串输入输出函数

3.1 通用

  • 单个字符的输入/输出:格式符 %c

e.g. char ch;
scanf(“%c”, &ch);
printf(“%c”, ch);

  • 字符串的整体输入/输出:格式符 %s

e.g.char str[81];
scanf(“%s”, str);
printf(“%s”, str);

  • 注意:1.参数为数组名,即数组首地址。2.scanf()函数%s格式不能读入空格、Tab、回车符,遇到空格、Tab、回车符,终止字符串输入,并写入字符串结束标志’\0’

3.2 专用

  • 单个字符的输入输出:格式符 %c

getchar() getch()(不回显在屏幕)
putchar()

  • 字符串的输入输出:格式符 %s

gets() fgets()
puts()

3.2.1 单个字符输入输出

字符输入函数getchar()/getch()
  • 举例:
#include 
int main()
{
    char line[81];
    char ch;
    int i = 0;

    printf("输入一行英文句子,以回车结束\n");
    do
    {
        ch = getchar(); /* 使用getchar函数读取字符 */
        line[i] = ch;   /* 放到字符数组line中 */
        i++;
    } while (ch != '\n'); /* 按回车键结束 */
    line[i - 1] = '\0';   /* 字符串结束标志 */

    printf("\n %s\n", line); /* 输出字符串line */

    return 0;
}

转载一篇好文getch getche getchar的区别和缓冲区的概念

字符输出函数putchar()

putchar()函数用于向终端输出字符,使用形式如下:
putchar(字符);

char ch = ‘X’;
/* 输出字符变量ch的值 ‘X’*/
putchar(ch);		
/* 等价于 printf("%c", ch);*/
putchar(‘\n’)	 /* 换行 */

3.2.2 字符串输入输出

字符串输入函数 gets()
  • 函数原型:char *gets(char *str);

  • 功能:读入一串以回车结束的字符,顺序存入到以str为首地址的内存单元,最后写入字符串结束标志’\0’。

  • gets()函数和scanf()函数一样,存在潜在的安全隐患。

  • 举例:

#include 

int main(void)
{
    char name[10]; /*定义字符数组*/

    printf("Enter your name:");
    gets(name); /*使用gets函数输入字符串*/

    printf("Hello %s!\n", name); /*输出*/

    return 0;
}

  • 隐患:因为由于gets()无法知道字符串的大小,必须遇到换行字符或文件尾才会结束输入,因此容易造成缓存溢出的安全性问题,给黑客攻击以可乘之机。可以通过fgets来代替。

字符串输入函数 fgets()
  • 函数原型:
    char *fgets(char *buf, int bufsize, FILE *stream);

  • 参数说明:

*buf: 字符型指针,指向用来存储所得数据的地址。
bufsize: 整型数据,指明buf指向的字符数组的大小
*stream: 文件结构体指针,指向将要读取的文件流。标准键盘输入流为stdin

  • 函数功能:从stream流读取以’\n’结尾的一行字符(包括’\n’在内)存到缓冲区buf中,读取字符的个数最多为bufsize-1。在读取字符的末尾添加一个'\0'组成完整的字符串。
  • 如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。
  • 举例
#include 

int main(void)
{
    char name[10]; /*定义字符数组*/

    printf("Enter your name:");

    fgets(name, sizeof(name), stdin);

    printf("Hello %s!\n", name); /*输出*/

    return 0;
}

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

C语言 第九章 字符串_第4张图片

原因分析:
- 当用户输入“zhang junqiang”时,超过限制大小,最多接受sizeof(name)-1个字符到字符数组中,再自动添加’\0’组成完整字符串。结果为“zhang jun”
- 当用户输入“li si”,fgets()函数会将包括在最后的回车符在内的所有字符读入,最后自动添加’\0’组成完整字符串,所以感叹号到了下一行。

字符串输出函数 puts( )
  • 函数原型:puts(char* str)
  • 功能:输出内存中从地址str起的若干字符,直到遇到’\0’为止,最后输出一个换行符。
  • puts()函数与printf()函数以格式符%s输出字符串的区别:前者逐个输出字符到’\0’结束时自动输出一个换行符,后者逐个输出字符到’\0’结束,不会自动输出换行符。

4 字符串处理函数

  • C语言提供了一系列字符串函数,包括字符串的
    输入\输出、连接、拷贝、比较、转换等运算。
  • 使用这些函数需要在程序中包含相应的头文件string.h
    C语言 第九章 字符串_第5张图片

字符串长度计算-strlen

格式:strlen(字符串);

char str[10] = {“China”};
printf(“%d”, strlen(str));
答应出来的是实际长度5,不包括’\0’
可以用strlen()长度控制字符串输出

len = strlen(str);
for (i=0; i<len; i++)
{
	  putchar(str[i]);
}
putchar('\n');

字符串复制函数-strcpy

str copy
格式:strcpy(目的字符串,源字符串);
注意:

  • 字符串不能用”=“整体复制,比如str2 = str1;是不成立的,因为str2代表数组地址,是地址常量,不能被赋值。
  • 要保证目的字符串足够大。考试常考
  • 调用strcpy函数时,第一个参数必须是数组名第二个参数可以是字符数组名也可以是一个字符串常量。比如:strcpy(str1, "China");
  • 复制字符串时连同源字符串尾部的’\0’一并复制到目标字符串中。复制完后,目的字符串原来的相应部分会被覆盖,目的字符串更长的部分还会保留。
  • 用一个小小的test.c来检验一下
#include 
#include 

int main()
{
    char s[10] = "njtechhh";
    //printf("%lu\n", strlen(s));
    printf("%s\n", s);
    for (unsigned long int i = 0; i < sizeof(s) / sizeof(char); i++)
    {
        printf("%c\n", s[i]); //用%d可以更加直观
    }

    strcpy(s, "Good");

    printf("%s\n", s);

    for (unsigned long int i = 0; i < sizeof(s) / sizeof(char); i++)
    {
        printf("%c\n", s[i]); //用%d可以更加直观,覆盖掉了五个位置
    }
    return 0;
}

发现"Good\0"总共五个字符覆盖掉了"njtechhh"的前五位,变成"Good\0hhh",字符串形式下显示为Good

字符串链接函数-strcat

str catenates
格式:strcat(目的字符串,源字符串);
C语言 第九章 字符串_第6张图片

  • 要保证目的字符串足够大,考试常考
  • 返回目的字符串首地址
  • 链接前两个字符串后都有’\0’,链接时会将s1后的’\0’覆盖,只在连接后的新字符串最后保留一个’\0’
  • 调用strcat函数时,第一个参数必须是数组名第二个参数可以是字符数组名也可以是一个字符串常量。比如:strcat(str1, "China");

字符串比较函数-strcmp

str comparison
格式:`strcmp(字符串1,字符串2)

  • 比的不是字符串长短!!!
  • 当出现第一对不相等的字符时,就由这两个字符决定所在字符串的大小,返回其ASCII码比较的结果值
    strcmp(s1,s2)
  • 当s1>s2时,函数返回值为正值
  • 当s1=s2时,函数返回值等于0
  • 当s1

5 应用举例

5.1 字符变换

//输入一行字符,将其中的小写字母转换成大写字母,
//大写字母转换为小写字母,其余字符统一变为星号'*'。

#include 

int main()
{
    char str[81];
    int i = 0;
    while ((str[i] = getchar()) != '\n')
        i++;
    str[i] = '\0';                   /*将最后的回车换行符改为结束标志*/
    for (i = 0; str[i] != '\0'; i++) /*逐个处理、输出字符*/
        { if (str[i] >= 'a' && str[i] <= 'z')
            str[i] -= 32;
    else if (str[i] >= 'A' && str[i] <= 'Z')
        str[i] += 32;
    else str[i] = '*';
    printf("%c", str[i]);
}
    return 0;
}

5.2 顺序颠倒

//输入一个字符串,逆序输出它

#include 
#include 

int main()
{
    char str[50],ch;
    int len;
    
    printf("请输入字符串:");
    fgets(str, sizeof(str), stdin);

    len = strlen(str);

    for (int i = 0, j = len-1; i < j; i++, j--)
    {
        ch = str[i];
        str[i] = str[j];
        str[j] = ch;
    }
    
    printf("逆序字符串为:%s\n", str);

    return 0;
    

}

5.3 凯撒密码

#include 
#include 

void encode(char code[], int n);

int main(void)
{
	char text[100];    /* 明文 */
	
	printf("明文:");
	fgets(text, sizeof(text), stdin);	/* 输入明文 */	

	/* 加密 */
	encode(text, 3);  /* 明文为text字符串,密钥为3 */

	/* 输出密文 */
	printf("密文:%s\n", text);

	return 0;
}

void encode(char code[], int n)
{
    int len=strlen(code);

    
    for (int i = 0; i < len-1; i++)
    {
        if (code[i] >= 'A' && code[i] <= 'Z' )
        {
            code[i] += n;
            if (code[i]>'Z' )
            {
                code[i] -= 26 ; 
            }
            
        }
        else if (code[i] >= 'a' && code[i] <= 'z' )
        {
            code[i] += n;
            if (code[i]>'z' )
            {
                code[i] -= 26 ; 
            }
        }
    }
    
}

5.4 进制转换

#include 
#include 

void change(long n, int base); /*原型说明*/

int main(void)
{
    long n;
    printf("input a number: ");
    scanf("%ld", &n);

    change(n, 2);  /*调用函数change,转换为2进制*/
    change(n, 8);  /*调用函数change,转换为8进制*/
    change(n, 16); /*调用函数change,转换为16进制*/

    return 0;
}

void change(long n, int base)
{
    char bit[] = "0123456789ABCDEF";
    /*初始化字符数组*/
    int data[64]; /*进制转换结果最长为64位*/
    int i = 0;
    do
    {
        data[i] = n % base; /*余数写入数组*/
        n /= base;
        i++;
    } while (n != 0); /*直到n为0为止*/

    if (base == 8)
        printf("0");
    else if (base == 16)
        printf("0x");

    for (--i; i >= 0; i--) /*倒序输出*/
    {
        printf("%c", bit[data[i]]);
    }
    printf("\n");
}

专栏指路

C语言笔记汇总

你可能感兴趣的:(c语言笔记,c语言,开发语言,后端)