C Primer Plus 第六版 十一章笔记

11.1 表示字符串和字符串I/O

11.1.1 在程序中定义字符串

1.字符串字面量(字符串常量)

用双引号括起来的内容称字符串字面量(string literal),叫作字符串常量(string constant)

:如果要在字符串内部使用双引号,必须在双引号前面加上一个反斜杠(\)

字符串常量属于静态存储类别

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

    return 0;
}

输出结果如下:
在这里插入图片描述

*"space farers"表示该字符串所指向地址上存储的值,应该是字符串的首字符

2.字符串数组和初始化

定义字符串,必须让编译器知道需要多少空间 在指定数组大小时,要确数组的元素个数至少比字符串长度多1(容纳空字符)
0是指char形式的空字符,不是数字字符0
请添加图片描述
声明数组时必须是可求值的整数

字符数组名是该数组首元素的地址

在这里插入图片描述

3.数组和指针

字符串储存在静态存储区
const char ar1[ ] = “Something is pointing at me”

ar1是地址常量,不能更改ar1 可以进行ar1 + 1,但不允许进行++ar1的操作

:递增运算符只能在变量名前

#define MSG "I'm special"

#include <stdio.h>
int main(){
    char ar[] = MSG;
    const char *pt = MSG;
    printf("address of \"I'm special\":%p \n","I'm special");
    printf("        address ar:%p\n",ar);
    printf("        address pt:%p\n",pt);
    printf("      address of MSG:%p\n",MSG);
    printf("address of \"I'm special\":%p \n","I'm special");
    return 0;
}

输出结果如下:

在这里插入图片描述

4.数组和指针的区别

char heart[ ] = “I LOVE YOU”
const cahr *head = “I HATE YOU”

两者主要区别是:数组名heart是常量 指针名head是变量

数组的元素是变量,但是数组名不是变量

建议把指针初始化为字符串字面量时使用const限定符

如果不修改字符串,不要用指针指向字符串字面量

5.字符串数组

请添加图片描述
上方是数组 下方是指针

如果要改变字符串或为字符串输入预留空间,不要使用指向字符串字面量的指针

11.2 字符串输入

11.2.1 分配空间

最简单的方法是:在声明时显式指明数组的大小

11.2.2 gets( )

gets()简单易用,它读取整行输入,直至遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符的末尾添加一个空字符使其成为一个C字符串。它经常和 puts()函数配对使用,该函数用于显示字符串,并在末尾添加换行符。

11.2.3 gets( )的替代品

1.fgets( ) fputs( )
  • fgets( )的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets( ) 将读入n-1 个字符,或者读到遇到的第一个换行符为止。
  • 如果fgets( )读到一个换行符,会把它储存在字符串中。这点与gets( )不同,gets()会丢弃换行符。
  • fgets( )两数的第3个参数指明要读入的文件。如果读入从键盘输入的数据,则以stdin(标准输入)作为参数,该标识符定义在stdio.h中。

当puts( )显示该字符串时在末尾添加了换行符 而fputs( )不会这样做

  • 如何用fgets( )处理掉换行符?
    一个方法是在已储存的字符串中查找换行符 并将其替换成空字符
while(words[i] != '\n')
    i++;
words[i] = '\0';
  • 如果仍有字符串留在输入行怎么办?
    如果目标数组装不下一整行输入,丢弃那些多余字符
whilegetchar() != '\n'
	continue;
2.gets_s()
  • gets_s( )只从标准输入中读取数据,所以不需要第3个参数。
  • 如果gets_s()读到换行符,会丢弃它而不是储存它。
  • 如果gets_s( )读到最大字符数都没有读到换行符,会执行以下几步.首先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着,调用依赖实现的 “处理函数”(或你选择的其他函数),可能会中止或退出程序。

11.2.4 scanf( )函数

scanf( )更像是“获取单词”含糊 而不是获取字符串

scanf( ) 函数返回一个整数值 该值等于scanf( ) 成功读取的项数或EOF(读到文件结尾时返回EOF)

11.3 字符串输出

put( )、fputs( ) 、printf( )

11.3.1 puts函数
  • puts在显示字符串时会自动在末尾添加换行符
  • puts在遇到空字符时输出停止 所以必须确保有空字符
11.3.2 fputs( )函数
  • fputs( )末尾部位添加换行符
  • 第2个参数指明要写入数据的文件
11.3.3 printf( )函数
  • printf( ) 不会自动在每个字符串末尾加上一个换行符 因此必须指明在哪里使用换行符

  • printf(“%s\n”,string)与puts(string)效果相同

11.4自定义输入/输出函数

  • 需求:类似puts( )但不会自动添加换行符的函数
#include <stdio.h>
void put1(const char *string){
    while(*string != '\0')
        putchar(*string++);
}

++优先级高于*

注意while(string)
当string指向空字符时,*string的值是0,即测试条件为假,while循环结束

  • 用户自定义输出函数:
#include <stdio.h>
void put1(const char*);
int put2(const char *);

int main(){
    put1("If I'd as much money");
    put1(" AS I could spend\n");
    printf("I count %d characters.\n",
        put2("I never would cry old chairs to mend"));

    return 0;
}

void put1(const char  *string){
    while (*string)
        putchar(*string++);
}
int put2(const char *string){
    int count = 0;
    while(*string){
        putchar(*string ++);
        count++;
    }
    putchar('\n');

    return(count);
}

11.5 字符串函数

11.5.1 strlen()函数

用于统计字符串的长度

下面的函数可以缩短字符串的长度

void fit(char *string,unsigned int size){
	if(strlen(string) > size)
		string[size] = '\0';

string.h头文件包含了C字符串系列原型

11.5.2 strcat( )函数

strcat ( )(用于拼接字符串)接受两个字符串作为参数
该函数把第2个字符串的备份附加在第1个字符串末尾,并把拼接后形成的新字符串作为第1个字符串,第2个字符串不变。
strcat()函数的类型是 char * (即指向 char 的指針)
strcat ( ) 函数返回第1个参数,即拼接第2个字符串后的第1个字符串的地址。

#include <stdio.h>
#include <string.h>
#define SIZE 80
char * s_gets(char * st,int n);
int main(void){
    char flower[SIZE];
    char addon [] = "s smell like old shoes";

    puts("What is your favorite flower?");
    if(s_gets(flower,SIZE)){
        strcat(flower,addon);
        puts(flower);
        puts(addon);
    }else
        puts("End of file encountered!");
    puts("bye");

    return 0;
}
char * s_gets(char *st,int n){
    char *ret_val;
    int i = 0;

    ret_val = fgets(st,n,stdin);
    if(ret_val){
        while(st[i] != '\n' && st[i] != '\0')
            i++;
        if(st[i] == '\n')
            st[i] = '\0';
        else
            while(getchar() != '\n')
                continue;
    }
    return ret_val;
}
11.5.3 strncat( )函数

strncat( )函数的第三个参数指定了最大添加字符数

11.5.4 strcmp( )函数

通过比较运算符来比较字符串 就像比较数字一样 如果字符串参数相同就返回0 否则返回非0值

#include <string.h>
#include <stdio.h>
#define LISTSIZE 6
int main(){
    const char * list[LISTSIZE] =
            {"astronomy","astounding","astrophysics","ostracize","asterism","astrophobia"};
    int count = 0;

    for (int i = 0; i < LISTSIZE; i++) {
        if(strncmp(list[i],"astro",5) == 0){
            printf("Found :%s\n",list[i]);
            count ++;
        }
    }
    printf("The list contained %d words beginning"
           "with astro.\n",count);

    return 0;
}

输出结果如下:

在这里插入图片描述

11.5.5 strcpy( ) 、strncoy( )函数

如果pts1和pts2都是指向字符串的指针 那么拷贝的是字符串的地址而不是字符串本身
pts1 = pts2;
如果希望拷贝整个字符串,要是用strcpy( )函数

strcpy( )的属性

  1. 返回类型是char *,该函数返回的是第一个参数的值,即一个字符的地址
  2. 第1个参数不必指向数组的开始。这个属性可以用来拷贝数组的一部分

二、更谨慎的选择:strncpy( )

  • strncpy( )的第三个参数指明可拷贝的最大字符数
11.5.6 sprintf() 函数
  • sprintf( )两数声明在stdio.h中,而不是在string.h中。
  • sprintf( )的第1个参数是目标字符串的地址。其余参数和 printf( )相同,即格式字符串和待写入项的列表。

11.6字符串示例:字符串排序

#include <stdio.h>
#include <string.h>
#define SIZE 81 //限制字符串长度
#define LIM 20  /* 可读入的最多行数 */
#define HALT ""  /* 空字符停止输入*/
char * s_gets(char *st,int n); /*字符串排序函数*/
void stsrt(char *strings [],int num);
int main(void){
    char input[LIM][SIZE];/* 储存输入的数组 */
    char *ptstr[LIM]; /* 内含指针变量的数组 */
    int ct =0; /* 输入计数*/
    int k ;    /* 输出计数*/
    printf("Input up to %d lines,and I will sort them\n",LIM);
    printf("To stop,press the Enter key at a line's start\n");
    while (ct < LIM && s_gets(input[ct],SIZE) != NULL && input[ct][0] != '\0'){
        ptstr[ct] = input[ct];   //设置指针指向字符串
        ct ++;
    }
    stsrt(ptstr,ct); //字符串排序函数
    puts("\nHere is the sorted list:\n");
    for(k = 0;k < ct;k++){
        puts(ptstr[k]); //排序后的指针
    }
    return 0;
}

void stsrt(char *strings [],int num){
    char *temp;
    int top,seek;

    for (top = 0;top  < num - 1;top ++) {
        for(seek = top +1;seek <num ;seek ++)
            if(strcmp(strings[top],strings[seek]) > 0){
                temp = strings[top];
                strings[top] = strings[seek];
                strings[seek] = temp;
            }
    }
}
char * s_gets(char *st,int n){
    char *ret_val;
    int i = 0;

    ret_val = fgets(st,n,stdin);
    if(ret_val){
        while(st[i] != '\n' && st[i] != '\0')
            i++;
        if(st[i] == '\n')
            st[i] = '\0';
        else
            while(getchar() != '\n')
                continue;
    }
    return ret_val;
}
11.6.1排序指针而非字符串

请添加图片描述

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

include <string.h>
#include <stdio.h>
#include <ctype.h>
#define LIMIT 81
void ToUpper(char *);
int PunctCount(const char *);

int main(){
    char line[LIMIT];
    char *find;

    puts("Please enter a line: ");
    fgets(line,LIMIT,stdin);
    find = strchr(line,'\n');
    if(find)
        *find = '\0';
    ToUpper(line);
    puts(line);
    printf("That line has %d punctuation characters\n", PunctCount(line));

    return 0;
}

void ToUpper(char *str){
    while (*str){
        *str = toupper(*str);
        str++;
    }
}
int PunctCount(const char *str){
    int ct =0;
    while (*str){
        if(ispunct(*str))
            ct++;
        str++;
    }
    return ct;
}

输出结果如下:
在这里插入图片描述

11.9 字符换转换成数字

  • 转换十进制与十六进制
#include <stdio.h>
#include <stdlib.h>
#define LIM 30
char * s_gets(char *st,int n);

int main(){
    char number[LIM];
    char * end;
    long value;

    puts("Enter a number (empty to quit):");
    while (s_gets(number,LIM) && number[0] !='\0'){
        value = strtol(number,&end,10);//十进制
        printf("base 10 input,base 10 output:%ld,stopped at %s(%d)\n",value,end,*end);
        value = strtol(number,&end,16);//十六进制
        printf("base 16 input,base 10 output:%ld,stopped at %s(%d)\n",value,end,*end);
        puts("Next number:");

    } puts("Bye!\n");
    return 0;
}
char * s_gets(char *st,int n){
    char *ret_val;
    int i = 0;

    ret_val = fgets(st,n,stdin);
    if(ret_val){
        while(st[i] != '\n' && st[i] != '\0')
            i++;
        if(st[i] == '\n')
            st[i] = '\0';
        else
            while(getchar() != '\n')
                continue;
    }
    return ret_val;
}


strtol( )函数最多可以转换36进制 a~z都可以作数字

11.10 关键概念

字符串,无论是由字符数组、指针还是字符串常量标识,都储存为包含字符编码的一系列字节,并以空字符串结尾。C 提供库两数处理字符串,查找字符串并分析它们。尤其要牢记,应该使用 strcmp( ) 来代替符,当比较字符串时,应该使用strcpy( )或strncpy( )代替赋值运算符把字符串赋给字符数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值