c primer plus 专题11:字符串

1 表示字符串和字符串IO

1 字符串是以空字符( \0 )结尾的 char 类型数组。

#include <stdio.h>   
#define MSG			"I am a symbolic string constant"
#define MAX_LENGTH	81
int main(void)
{
	char words[MAX_LENGTH] = "I am a string in array.";
	const char * pt1 = "Something is pointing at me.";
	puts("Hear are some strings:");
	puts(MSG);
	puts(words);
	puts(pt1);
	words[8] = 'p';
	puts(words);

	return 0;
}

和 printf() 函数一样,puts() 函数也属于 stdio.h 系列的输入 / 输出函数。不同的是,puts() 函数只用来显示字符串,而且自动在显示的字符串末尾加上换行符。

值得注意的是,这条语句声明了 char 指针,那么字符串保存在哪里?

const char * pt1 = "Something is pointing at me.";

下面是调试过程:

变量值

内存值

可以看到,pt1 本质上只是一个char指针,而在内存空间保存了这整条的字符串,pt1 指向了字符串的首地址。

2 在程序中定义字符串

1 字符串常量

/* strptr.c -- 把字符串看作指针 */
#include <stdio.h>   
int main(void)
{
	/**
	 * %s 打印字符串
	 * %p 打印地址,如果"are"代表一个地址,printf()打印该字符串首字符的地址
	 * %c 解引用,打印字符串的首字符
	 */
	printf("%s %p %c\n", "We", "are", *"space farers");

	return 0;
}
// 执行结果
We 00E37CD0 s

2 字符串数组和初始化

不指定,自动确定数组大小

字符串首地址与字符串数组

3 数组和指针

1 占用空间

非常重要的程序

程序结果分析:多次使用的相同字符串常量(包括宏定义),只使用一个存储位置

2 数组和指针的区别

数组名是常量,指针是变量,只有指针能进行自增、自减等操作

总结一下:数组的元素是变量,但数组名不是变量

3 指针指向字符串时,最好加 const 限定

为什么?因为编译器将多次使用的相同字符串,只使用一个存储位置。如果不加 const 限定,一旦使用指针修改了字符串,其他所有相同的字符串,全部被修改!!!

推荐用法:const char * pl = "hello world"

4 字符串数组

程序的执行结果和分析

两种字符串存储方式的区别:

3 字符串输入

1 分配空间

2 gets() 函数读取输入字符串

gets() 函数存在的问题:无法检查数组是否装的下输入行,可能会导致缓冲区溢出而不安全。

3 gets() 函数的替代品 fgets()

4 fgets() 函数的返回值:返回指向 char 的指针,如果一切顺利,该函数返回的地址与传入的第1个参数相同。但是,如果函数读到文件结尾,它将返回一个特殊的指针:空指针,一般用宏定义 NULL 标识。

从键盘输入的数据流中循环读取并打印

丢弃掉多余的超出长度的字符

#include <stdio.h>
#define STLEN	10
int main(void)
{
	char words[STLEN];
	int i, ch;

	puts("Enter string(empty line to quit):");
	// fgets() 从缓冲区读取9个字节
	while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n')
	{
		i = 0;
		while (words[i] != '\n' && words[i] != '\0')
			i++;
		if (words[i] == '\n')
			words[i] = '\0';
		else	// 如果word[i] == '\0',则执行下面的程序
			while ((ch = getchar()) != '\n')
			{
				// putchar() 从缓冲区第10个字节开始继续读取
				putchar(ch);		
				putchar('\n');
			}		
		puts(words);
	}
	puts("Done");

	return 0;
}

执行结果

5 空字符和空指针

6 scanf 函数

scanf 函数也能读取字符串。与gets() 函数类似,如果输入行过长,scanf 函数也会导致数据溢出。不过,在 %s 转换说明中使用字段宽度可以防止溢出。

4 字符串输出

1 puts() 函数

puts() 函数很容易使用,只需把字符串的地址作为参数传递给它即可。puts() 函数在字符串显示时,会自动在末尾添加换行符。puts() 函数如何知道在何处停止?该函数在遇到空字符 '\0' 时就自动停止,所以必须确保有空字符。

char name[100];

puts(name);    // puts输出

2 fputs() 函数

char name[100];

fputs(name, stdout);     // fputs输出

3 printf 函数

4 自定义输入输出函数

5 字符串函数

包含的头文件 string.h

1 strlen 函数  统计字符串的长度

下面的程序可以缩短字符串长度

#include <stdio.h>
#include <string.h>

void fit(char * pstring, unsigned int size);

int main(void)
{
	char mesg[] = "12345_qwer hello, world!";
	puts(mesg);
	fit(mesg, 20);
	puts(mesg);
	fit(mesg, 5);
	puts(mesg);

	return 0;
}

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

执行结果

12345_qwer hello, world!
12345_qwer hello, wo
12345

2 strcat 函数  拼接字符串

获取整行输入字符串,并进行拼接的程序

考虑存储空间,毫无疑问,strcat() 函数也存在溢出的问题。当拼接后的字符串超过字符串1的内存空间时,就会发生溢出,此时可能会导致程序崩溃。

3 strncat() 函数

使用 strncat() 函数进行安全粘贴的程序

#include <stdio.h>
#include <string.h>

#define SIZE		30
#define BUGSIZE		13
char * s_gets(char * st, int n);

int main(void)
{
	char flower[SIZE];
	char addon[] = " smell like old shoes.";
	char bug[BUGSIZE];
	int avaliable;

	puts("What's your favorite flower?");
	s_gets(flower, SIZE);		/* 读取字符,最多SIZE字节,然后清空缓冲区 */
	if ((strlen(flower) + strlen(addon) + 1) <= SIZE)
		strcat(flower, addon);	/* 空间足够,进行粘贴 */
	else
		puts("Array don't have enough memory, strcat failed!");
	puts(flower);
	puts("What's your favorite bug?");
	s_gets(bug, BUGSIZE);
	avaliable = BUGSIZE - strlen(bug) - 1;	/* 计算 bug 数组的剩余字节数 */
	strncat(bug, addon, avaliable);			/* 最多拷贝 avaliable 字节,防止溢出 */
	puts(bug);

	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;
}

执行结果

4 strcmp 函数 比较字符串

strcmp 函数是用来比较2个字符串的函数,如 srcmp(字符串1,字符串2),从第一个字符开始比较,如果到最后两个字符串完全相同,则strcmp()函数输出的值为0;若开始出现不同的字符,根据这个字符ASCII码进行比较,若字符串1的ASSCII值大于2,则输出值大于0;反之,输出值小于 0;

#include <stdio.h>
#include <string.h>

#define ANSWER		"Grant"
#define SIZE		40
char * s_gets(char * st, int n);

int main(void)
{
	char try[SIZE];

	puts("Who is buried in Grant's tomb?");
	s_gets(try, SIZE);
	/* 读取键盘输入字符串,与 "Grant" 比较 */
	while (strcmp(try, ANSWER) != 0)	
	{
		puts("No, that's wrong. Try again.");
		s_gets(try, SIZE);
	}
	puts("That's right!");

	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;
}

执行结果

strcmp 函数的介绍

5 strncmp 函数:比较 n 个字符

6 strcpy() 函数 拷贝字符串

#include <stdio.h>
#include <string.h>

#define SIZE	40
#define LIM		5
char * s_gets(char * st, int n);

int main(void)
{
	/* 字符串二维数组,保存输入中以 q 开头的单词 */
	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 beginning with q!\n", temp);
		else
		{
			strcpy(qwords[i], temp);
			i++;
		}
	}
	puts("Here are the words accept:");
	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		/* 丢弃输入缓冲流的剩余字符 */
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

void lower_letter(char * ptr)
{
	const int diff = 'a' - 'A';

	while (*ptr != '\0')
	{
		if ('A' <= *ptr && *ptr <= 'Z')
			*ptr = *ptr + diff;
		ptr++;
	}
}

strcpy() 函数拷贝程序执行结果

strcpy() 函数的其他属性

和之前一样,strcpy 函数也存在数据溢出的风险。

7 strncpy() 函数 拷贝n个字节

8 strchr() 函数

char *strchr(const char *s, int c) 
功能: 查找字符串s中首次出现c字符的位置

说明: 返回首次出现c的位置的指针,返回的地址是被查找的字符串指针开始的第一个与c相同字符的指针,若s中不存在c则返回NULL。

返回值: 成功返回要查找的字符第一次出现的位置,否则返回NULL。

9 sprintf 函数

6 命令行参数

下面是获取输入参数的程序:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
	int i;

	printf("We get %d parameters.\n", argc);
	for (i = 0; i <= argc; i++)
		printf("argv[%d]: %s\n", i, argv[i]);

	return 0;
}

程序执行结果如下

参考链接:

https://blog.csdn.net/dingyc_ee/article/details/103023888

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值