• 11 字符串函数


    2 字符串输入

    如果想把一个字符串读入程序,首先必须预留储存该字符串的空间,然后用输入函数获取该字符串。

    2.1 分配空间

    在这里插入图片描述

    char *name;
    scanf("%s",name);
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述

    2.2 gets函数

    在这里插入图片描述
    程序11.6 getsputs.c

    /* getsputs.c -- using gets() and puts() */
    #include <stdio.h>
    #define STLEN 81
    
    int main(void){
     	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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    下面是该程序在某些编译器(至少是旧式编译器)中的运行示例:

    Enter a string, please.
    I want to learn about string theory!
    Your string twice:
    I want to learn about string theory!
    I want to learn about string theory!
    Done. 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    整行输入(除了换行符)

    2.3 gets的替代品

    在这里插入图片描述

    2.3.1 fgets函数(和fputs)

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    程序11.7 fgets1.c

    /* fgets1.c -- using fgets() and fputs() */
    #include <stdio.h>
    #define STLEN 14
    
    int main(void){
     	char words[STLEN];
     	
     	puts("Enter a string, please.");
     	fgets(words, STLEN, stdin);
     	printf("Your string twice (puts(), then fputs()):\n");
     	puts(words);
     	fputs(words, stdout);
     	puts("Enter another string, please.");
     	fgets(words, STLEN, stdin);
     	printf("Your string twice (puts(), then fputs()):\n");
     	puts(words);
     	fputs(words, stdout);
     	puts("Done.");
     	return 0;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    程序的输出示例如下:

    Enter a string, please.
    apple pie
    Your string twice (puts(), then fputs()):
    apple pie
     
    apple pie
    Enter another string, please.
    strawberry shortcake
    Your string twice (puts(), then fputs()):
    strawberry sh
    strawberry shDone. 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5.5 strcpy和strncpy函数

    如果pts1和pts2都是指向字符串的指针,那么下面语句拷贝的是字符串的地址而不是字符串本身:

    pts2=pts1;
    
    • 1

    如果希望拷贝整个字符串,要使用strcpy函数。程序11.25要求用户输入以q开头的单词。该程序把输入拷贝至一个临时数组中,如果第1个字母是1,程序调用strcpy把整个字符串从临时数组拷贝至目标数组中。strcpy函数相当于字符串赋值运算符。

    程序11.25 copy1.c

    /* copy1.c -- strcpy() demo */
    #include <stdio.h>
    #include <string.h> // declares strcpy()
    #define SIZE 40
    #define LIM 5
    
    char * s_gets(char * st, int n);
    
    int main(void){
     	char qwords[LIM][SIZE];
     	char temp[SIZE];
     	int i = 0;
     	printf("Enter %d words beginning with q:\n", LIM);
     	while (i < LIM && s_gets(temp, SIZE)){
     		if (temp[0] != 'q')
     			printf("%s doesn't begin with q!\n", temp);
     		else{
     			strcpy(qwords[i], temp);
     			i++;
     		}
     	}
     	puts("Here are the words accepted:");
     	for (i = 0; i < LIM; i++)
     	puts(qwords[i]);
     	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 // must have words[i] == '\0'
     			while (getchar() != '\n')
     				continue;
     	}
     	return ret_val;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    下面是该程序的运行示例:

    Enter 5 words beginning with q:
    quackery
    quasar
    quilt
    quotient
    no more
    no more doesn't begin with q!
    quiz
    Here are the words accepted:
    quackery
    quasar
    quilt
    quotient
    quiz 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    注意,只有在输入以q开头的单词后才会递增计数器i。

    strcpy函数将第二个参数(temp)指向的字符串拷贝至第一个参数(qword[i])指向的数组中。拷贝出来的字符串被称为目标字符串,最初的字符串被称为源字符串,即第一个参数是目标字符串,第二个参数是源字符串。

    如果以整型赋值的方式给字符串赋值,那么会报错:

    char target[20];
    int x;
    x = 50; /* assignment for numbers */
    strcpy(target, "Hi ho!"); /* assignment for strings */
    target = "So long"; /* syntax error */ 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    程序员有责任明确目标数组有足够的空间容纳源字符串的副本,下面的代码存在问题:

    char * str;
    strcpy(str, "The C of Tranquility"); // a problem
    
    • 1
    • 2

    strcy函数把"The C of Tranquility"拷贝到str指向的地址上,但是str未被初始化,所以该字符串有可能被拷贝到任意的地方。

    总之,strcpy接受两个字符串指针作为参数,可以把指向源字符串的第二个指针声明为指针、数组名或字符串常量;而指向源字符串副本的的第一个指针应指向一个数据对象(如,数组),且该对象有足够的空间存储源字符串的副本。记住,声明数组将分配储存数据的空间,而声明指针只分配储存一个地址的空间。

    5.5.1 strcpy的其他属性

    strcpy函数还有两个有用的属性。第一,strcpy函数的返回类型是char *,该函数返回的是第一个参数的值,即一个字符的地址。第二,第一个参数不必指向数组的开始。这个属性可用于拷贝数组的一部分。程序12.26演示了该函数的这两个属性:

    程序12.26 copy2.c

    /* copy2.c -- strcpy() demo */
    #include <stdio.h>
    #include <string.h> // declares strcpy()
    #define WORDS "beast"
    #define SIZE 40
    
    int main(void){
     	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;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    程序输出如下:

    beast
    Be the best that you can be.
    Be the beast
    beast 
    
    • 1
    • 2
    • 3
    • 4

    注意,strcpy函数把源字符串中的空字符也拷贝在内。在该例中,空字符覆盖了copy数组中that的第一个t,如图11.5所示。注意,由于第一个参数是copy+7,所以ps指向copy中的第八个元素(下标为7)。因此puts(ps)从该处开始打印字符串。

    在这里插入图片描述

    5.5.2 更谨慎的选择:strncpy

    在这里插入图片描述
    程序 11.27 copy3.c

    /* copy3.c -- strncpy() demo */
    #include <stdio.h>
    #include <string.h> /* declares strncpy() */
    #define SIZE 40
    #define TARGSIZE 7
    #define LIM 5
    
    char * s_gets(char * st, int n);
    
    int main(void){
     	char qwords[LIM][TARGSIZE];
     	char temp[SIZE];
     	int i = 0;
     	printf("Enter %d words beginning with q:\n", LIM);
     	while (i < LIM && s_gets(temp, SIZE)){
     		if (temp[0] != 'q')
     			printf("%s doesn't begin with q!\n", temp);
     		else{
     			strncpy(qwords[i], temp, TARGSIZE - 1);
     			qwords[i][TARGSIZE - 1] = '\0';
     			i++;
     		}
     	}
     	puts("Here are the words accepted:");
     	for (i = 0; i < LIM; i++)
     	puts(qwords[i]);
     	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 // must have words[i] == '\0'
    	 		while (getchar() != '\n')
     				continue;
     	}
     	return ret_val;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    下面是该程序的运行示例:

    Enter 5 words beginning with q:
    quack
    quadratic
    quisling
    quota
    quagga
    Here are the words accepted:
    quack
    quadra
    quisli
    quota
    quagga 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    strncpy(target,source,n)把source中的n个字符或空字符之前的字符拷贝到target中。因此,如果source中的字符数小于n,则拷贝整个字符串,包括空字符。但是,strncpy拷贝字符串的长度不会超过n,如果拷贝到第n个字符时还未拷贝完整个源字符串,就不会拷贝空字符。所以,拷贝的副本中不一定有空字符。鉴于此,该程序把n设置为比目标数组大小小1,然后把数组最后一个元素设置为空字符。

    这样做确保储存的是一个字符串。如果目标空间能容纳源字符串的副本,那么从源字符串拷贝的空字符串便是该副本的结尾;如果目标空间装不下副本,则把副本最后一个元素设置为空字符。

  • 相关阅读:
    如何用Java实现SpringCloud Alibaba Sentinel的熔断功能?
    PEOz-NPs-Cy 5.5 聚(2-乙基-2-噁唑啉)纳米粒子修饰荧光素5.5
    【第5章】pandas入门
    【CMU 15-445】Proj1 Buffer Pool Manager
    Redis的主从复制
    Packet Sniffing and Spoofing Lab(报文嗅探&欺骗SEED 实验)
    【计算机网络】以太网供电PoE - Power over Ethernet
    操作系统进程的概念、组成和特征
    《了解CV和RoboMaster视觉组》完结啦!
    RS笔记:深度推荐模型之Wide&Deep [2016.6 谷歌]
  • 原文地址:https://blog.csdn.net/kking_edc/article/details/125403619