C Primer Plus (第五版) 第十一章 字符串和字符串函数 编程练习

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

编程练习

  1. 设计并测试一个函数,可以输入读取n个字符(包括空格、制表符、换行符),把结果存储在一个数组中,这个数组的地址通过参数来传递。
#include <stdio.h>
#define LEN 80

char * getch(char a[], int n);

int main(void)
{
	char a[LEN];

	if (getch(a, 4))
		puts(a);
	else
		printf("没有读取\n");

	return 0;
}
char * getch(char a[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		a[i] = getchar();
		if (EOF == a[i])
		{
			a[i] = ‘\0‘;
			break;
		}
	}
	a[i] = ‘\0‘;
	if (!a[0])
		return NULL;

	return a;
}

2.修改编程练习1中的函数,使得可以在N个字符后,或第一个空格、制表、换行符后停止读取输入,由上述情况中最先满足的那个终止读取(不能用scanf()函数)。

#include <stdio.h>
#include <ctype.h>

#define LEN 80

char * getch(char a[], int n);

int main(void)
{
	char a[LEN];

	if (getch(a, 6))
		puts(a);
	else
		printf("没有读取\n");

	return 0;
}
char* getch(char a[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		a[i] = getchar();
		if (EOF == a[i] || isspace(a[i]))
		{
			a[i] = ‘\0‘;
			break;
		}
	}
	a[i] = ‘\0‘;
	if (‘\0‘ == a[0])
		return NULL;

	return a;
}

3.设计并测试一个函数,其功能是读取输入行里的第一个单词到数组,并丟掉该行中其它的字符。

一个单词的定义是一个字符串,其中不含空格、制表符和换行符

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>	//不支持bool,可以返回int类型 0 或 1 

bool getword(char * );

int main(void)
{
	char array[20];
	if (getword(array))
		puts(array);
	else
		puts("没有读取到单词。");

	return 0;
}

bool getword(char * array)
{
	char ch;
	int a = 0;
	char * p = array;
	while ((ch = getchar()) != ‘\n‘)
	{
		//怱略一行开始处的空格。
		if (a == 0 && isspace(ch))
			continue;
		else
			a = 1;

		if (!isspace(ch))
			*array++ = ch;
		else
			break;
	}
	*array = ‘\0‘;
	if (*p == ‘\0‘)
		return false;
	return true;
}

4.设计并测试一个函数,其功能是搜索由第一个参数指定的字符串,在其中查找由函数的第二个参数指定的字符的第一次出现的位置。如果找到,返回指向这个字符的指针;如果没找返回空字符(这种方式和strchr()函数的功能一样)。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

#include <stdio.h>
#define LEN 80

char * search(char *str, char ch);

int main(void)
{
	char ch;
	char target[LEN];
	char * pstr;
	puts("请输入字符串(在一行的开始处输入回车结束):");
	while (gets(target) && target[0] != ‘\0‘)
	{
		puts("请输入字符:");
		ch = getchar();
		while (getchar() != ‘\n‘)
			;
		pstr = search(target, ch);
		if (pstr == NULL)
			printf("字符%c不在字符串中\n", ch);
		else
			printf("找到字符%c,它的地址为%p\n", ch, pstr);

		puts("请输入下一个字符串(在一行的开始处输入回车结束:");
	}

	return 0;
}

char * search(char *str, char ch)
{
	while (*str != ‘\0‘)
	{
		if (*str++ == ch)
			return str;
	}

	return NULL;
}

5.编写一个函数is_within(),它接受两个参数,一个是字符,另一个是字符串指针。其功能是如果字符在字符串中,就返回一个非0值(真);如果字符不在字符串中,就返回0值(假)。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

#include <stdio.h>
#define LEN 80

int search(char *str, char ch);

int main(void)
{
	char ch;
	char target[LEN];

	puts("请输入源字符串(在一行的开始处输入回车结束):");
	while (gets(target) && target[0] != ‘\0‘)
	{
		puts("请输入目标字符:");
		ch = getchar();
		while (getchar() != ‘\n‘)
			;
		if (search(target, ch))
			printf("字符%c在字符串中\n", ch);
		else
			printf("字符%c不在字符串中\n", ch);

		puts("请输入下一个源字符串(在一行的开始处输入回车结束:");
	}

	return 0;
}

int search(char *str, char ch)
{
	while (*str != ‘\0‘ &&  *str != ch)
		str++;
	return *str;
}

6.strncpy(s1, s2, n)函数从s2复制n个字符给s1,并在必要时截断s2或为其填充额外的空字符。如果s2的长度等于或大于n,目标字符串没有标志结束的空字符。函数返回s1。自己编写这个函数,并在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

#include <stdio.h>
#define LEN 80

char * strncpy1(char *, char *, int);

int main(void)
{
	char str1[LEN], str2[LEN];
	int n;

	printf("请输入要复制的字符串:");
	while (gets(str2))
	{
		printf("请输入要复制的字符个数:");
		scanf("%d", &n);
		strncpy1(str1, str2, n);
		printf("复制的字符串:");
		puts(str1);
		printf("请输入要复制的字符串:");
		while (getchar() != ‘\n‘)
			;
	}

	return 0;
}

#include <string.h>
char * strncpy1(char *str1, char *str2, int n)
{
	int l = strlen(str2);
	int i;

	if (l > n)
		n = l;
	for (i = 0; i < n; i++)
		str1[i] = str2[i];
	str1[i] = ‘\0‘;

	return str1;
}

7.编写一个函数string_in(),它接受两个字符串指针参数。如果第二个字符串被包含在第一个字符串中,函数就返回被包含的字符串开始的地址。例如,string_in("hats", "at")返回hats中a的地址,否则,函数返回空指针。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

#include <stdio.h>
#define LEN 80

char * string_in(char *, char *);

int main(void)
{
	char str1[LEN], str2[LEN];
	char * pstr;

	printf("请输入被查找的字符串:");
	while (gets(str1))
	{
		printf("请输入要查找的字符串:");
		gets(str2);
		pstr = string_in(str1, str2);
		if (pstr != NULL)
		{
			printf("字符串已找到在内存中的地址为%p\n", pstr);
		}
		else
		{
			printf("未找到字符串。\n");
		}
		printf("请输入被查找的字符串:");
	}
	printf("结束!");

	return 0;
}

#include <string.h>
char * string_in(char * str1, char * str2)
{
	int len2 = strlen(str2);
	int match;
	int len1 = strlen(str1);
	int i = len1 - len2 + 1;
	if (i > 0)
	{
		while ((match = strncmp(str1, str2, len2)) && i-- )
		{
			str1++;
		}
	}
	if(match)
		return NULL;
	else
		return str1;
}

8.编写一个函数,其功能是使输入字符串反序。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。

#include <stdio.h>
#define LEN 80

char * antitone(char * pstr);

int main(void)
{
	char str[LEN];

	printf("请输入要反序的字符串:");
	while (gets(str))
	{
		printf("反转后的字符串:");
		puts(antitone(str));
		printf("请输入要反序的字符串:");
	}
	printf("结束!\n");

	return 0;
}

#include <string.h>
char * antitone(char * pstr)
{
	int len = strlen(pstr) - 1;
	int i;
	char temp;

	for (i=0,  i<len - i; i++)
	{
		temp = pstr[len - i];
		pstr[len - i] = pstr[i];
		pstr[i] = temp;
	}

	return pstr;
}

9.编写一个函数,其参数为一个字符串,函数删除字符串中的空格。在一个可以循环读取的程序中进

行测试,直到用户输入空行。对于任何输入字符串,函数都应该适用并可以显示结果

#include <stdio.h>
#define LEN 80

char * del_space(char * pstr);

int main(void)
{
	char str[LEN];

	printf("请输入要删空格的字符串:");
	while (gets(str) && str[0] != ‘\0‘)
	{
		printf("删掉空格后的字符串:");
		puts(del_space(str));
		printf("请输入要删空格的字符串:");
	}
	printf("结束!\n");

	return 0;
}

#include <ctype.h>
char * del_space(char * pstr)
{
	char * temp = pstr;
	char * temp1;

	while (*temp)
	{
		if (isspace(*temp))
		{
			temp1 = temp;
			do
			{
				*temp1 = *(temp1 + 1);
			}
			while(*++temp1)	;
		}
		else 
		{
			temp++;
		}
	}

	return pstr;
}

10,编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。这个程序可以为用户提供一个有5个选项的菜单:输出字符串列表、按ASCII顺序输出字符串、长度递增顺序输出字符串、按字符串中第一个单词的长度输出字符串、退出。菜单可以循环直到用户输入退出请求。当然,程序要能真正完成菜单中的各项功能。

/*
*	10,编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。
*	这个程序可以为用户提供一个有5个选项的菜单:输出字符串列表、按ASCII顺序输出字符串、
*	长度递增顺序输出字符串、
*	按字符串中第一个单词的长度输出字符串、退出。菜单可以循环直到用户输入退出请求。
*	当然,程序要能真正完成菜单中的各项功能。
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define ROWS 10
#define COLS 81

void menu(void);			//显示菜单
char get_char(void);		//读取用户输入的正确选项
int in_str(char str[][COLS]);					//输入字符串,返回字符串的个数
void show_str(const char * str[], int n);		//输出参数传递过来字符串
void show_ascii(char * str[], int n);			//按ASCII顺序输出
void show_strlen(char * str[], int n);			//按字符串长度输出
void show_wordlen(char  * str[], int n);		//按字符串第一个单词的长度输出
int wordlen(char * str);	//求字符串第一个单词找度

int main(void)
{
	char str[ROWS][COLS];		//保存输入的原始字符串,值不做改变,方便用户循环选择时,任何时候都能输出原始值。
	char str_copy[ROWS][COLS];	//原始数据的备份可改变
	char * pstr[ROWS];			//声明指针做为函数参数传送
	char * pcopy[ROWS];
	char ch;					//菜单选项
	int i;			//字符串的个数
	int j;			//用于数组赋值

	i = in_str(str);
	for (j = 0; j < i; j++)
	{	//数组赋值
		pstr[j] = str[j];
		pcopy[j] = str_copy[j];
		strcpy(pcopy[j],pstr[j]);
	}

	menu();
	while ((ch = get_char()) != ‘q‘)
	{
		switch (ch)
		{
		case ‘a‘: show_str(pstr, i);
			break;
		case ‘b‘: show_ascii(pcopy, i);
			break;
		case ‘c‘: show_strlen(pcopy, i);
			break;
		case ‘d‘: show_wordlen(pcopy, i);
			break;
		default: printf("Error!");
		}
		menu();
	}

	return 0;
}
int wordlen(char * str)
{	//首单词字母个数
	int count = 0;
	char ch;

	while (ch = *str++)
	{
		if (isspace(ch) && count == 0) continue;
		if (isspace(ch) && count != 0) break;
		if (!isspace(ch)) count++;
	}

	return count;
}
void show_wordlen(char *str[], int n)
{	//按照首单词字母长度排序后输出
	char * temp;
	int i, j;

	for (i = 0; i < n - 1; i++)
	for (j = i; j < n; j++)
	if (wordlen(str[i]) > wordlen(str[j]))
	{
		temp = str[i];
		str[i] = str[j];
		str[j] = temp;
	}
	show_str(str, n);
}
void show_strlen(char *str[], int n)
{	//按照字符串长度排序后输出
	char * temp;
	int i, j;
	for (i = 0; i < n - 1; i++)
	for (j = i; j < n; j++)
	if (strlen(str[i]) > strlen(str[j]))
	{
		temp = str[i];
		str[i] = str[j];
		str[j] = temp;
	}
	show_str(str, n);
}
void show_ascii(char *str[], int n)
{	//按照字符ASCII编码顺序排序后输出
	char * temp;
	int i, j;
	for (i = 0; i < n - 1; i++)
	for (j = i; j < n; j++)
	if (strcmp(str[i], str[j]) > 0)
	{
		temp = str[i];
		str[i] = str[j];
		str[j] = temp;
	}
	show_str(str, n);
}
void show_str(const char *str[], int n)
{	//输出字符串数组
	int i = 0;
	while (i < n)
		puts(str[i++]);
}
int in_str(char(*str)[COLS])
{	//输入字符串
	int i = 0;

	do
	{
		printf("请输入字符串%d(输入EOF结束): ", i + 1);
	} while (gets(str[i]) && ++i < ROWS);
	puts("输入结束。");

	return i;
}
void menu(void)
{	//显示菜单
	puts("请选择字符串输出方式:");
	puts("  a)输出字符串列表");
	puts("  b)按ASCII顺序输出字符串");
	puts("  c)长度递增顺序输出字符串");
	puts("  d)按字符串中第一个单词的长度输出字符串");
	puts("  q)退出");

}
char get_char(void)
{	//确认输入符合要求
	char ch;
	while (ch = getchar())
	{
		while (getchar() != ‘\n‘)
			;
		if (!strchr("abcdq", ch))
			puts("请输入正确的选项,(如:a b c d q):");
		else
			break;
	}
	return ch;
}

11.编写一个程序。功能是读取输入,直到遇到EOF,并报告单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h系列函数。

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
	int count_word = 0;
	int count_lower = 0;
	int count_upper = 0;
	int count_digit = 0;
	int count_punct = 0;
	bool sign = false;
	char ch;
	while ((ch = getchar()) != EOF)
	{
		if (islower(ch)) count_lower++;
		else if (isupper(ch)) count_upper++;
		else if (isdigit(ch)) count_digit++;
		else if (ispunct(ch)) count_punct++;
		if (!isspace(ch) && !sign)
		{	//单词的界定为单个非空格字符和不包含空格字符的字符串,
			count_word++;
			sign = true;
		}
		else if (isspace(ch) && sign)
		{
			sign = false;
		}
	}
	puts("统计结果:");
	printf("单词数:%d\n", count_word);
	printf("小写字母数:%d\n", count_lower);
	printf("大写字母数:%d\n", count_upper);
	printf("标点符号数:%d\n", count_punct);
	printf("数字个数:%d\n", count_digit);

	return 0;
}

12.编写一个程序,按照相反的单词顺序显示命令行参数。即,如果命令行参数是see you later,程序的显示应该为later you see。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 80
int main()
{
	char str[LEN] = "see you later";
	char temp;
	int len = strlen(str) - 1;
	int i, j, wordlen;
	puts(str);
	for (i = 0; i < len - i; i++)
	{
		temp = str[i];
		str[i] = str[len - i];
		str[len - i] = temp;
	}
	puts(str);

	wordlen = 0;
	i = 0;
	do 
	{
		if (!isspace(str[i]) && str[i] != ‘\0‘)
		//isspace()不能识别‘\0‘条件中要加上str[i] != ‘\0‘
			wordlen++;
		else
		{
			if (wordlen > 0)
			{
				for (j = 0; j < wordlen - j; j++)
				{
					temp = str[i -1 - j];	//i-1 位置在单词的最后一个了符
					str[i - 1 -j] = str[i - wordlen+j];	//[i - wordlen]位置在单词的第一个字符。
					str[i - wordlen+j] = temp;
				}
				wordlen = 0;
			}

		}
	} while (str[i++] != ‘\0‘);

	puts(str);

	return 0;
}

13.编写一个计算乘幂的基于命令行和程序。第一个命令行参数为double类型数,作为幂的底数;第二个参数为整数,作为幂的指数。

#include <stdio.h>
#include <stdlib.h>	//提供atof() 
#include <math.h>	//提供pow()

int main(int argc, char *argv[])
{
	double num, exp;

	if (argc != 3)
		printf("参数不符\n");
	else
	{
		num = atof(argv[1]);
		exp = atof(argv[2]);
		printf("%.2lf的%.0lf次幂为:%lf", num, exp, pow(num, exp));
	}
	return 0;
}

14.使用字符分类函数实现atoi()函数。

#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
	char str[20];
	while(gets(str))
		printf("%d\n", my_atoi(str));

	return 0;
}

int my_atoi(char * pstr)
{
	int sign = 1;
	int num = 0;

	//字符串不能为空
	if (pstr == NULL)
		return 0;
	//去掉空格
	while (isspace(*pstr))
		pstr++;
	//判数首位是否有符号
	if (*pstr == ‘-‘)
		sign = -1;
	if (*pstr == ‘-‘ || *pstr == ‘+‘)
		pstr++;
	//转换直到遇到非数字时结束。
	while (isdigit(*pstr))
	{
		num = (num * 10) + (*pstr - ‘0‘);
		pstr++;
	}
	//增加符号位
	num *= sign;

	return num;
}

15.编写一个程序,其功能是读取输入,直到遇到文件结尾,并把文件显示出来,要求程序可以识别并执行下面的命令行参数:

-p    按原样显示输入

-u    把输入全部转换为大写

-l    把输入全部转换为小写

#include <stdio.h>
#include <ctype.h>

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

	if (argc > 2)
	{
		printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
		printf("例如: %s [-p | -u | -l]\n", argv[0]);
	}
	else if (argc == 2)
	{
		if (argv[1][0] != ‘-‘)
		{
			printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
			printf("例如: %s [-p | -u | -l]\n", argv[0]);
		}
		else
			switch (argv[1][1])
		{
			case ‘p‘:while ((ch = getchar()) != EOF)
				putchar(ch);
				break;
			case ‘u‘:while ((ch = getchar()) != EOF)
				putchar(toupper(ch));
				break;
			case ‘l‘: while ((ch = getchar()) != EOF)
				putchar(tolower(ch));
				break;
			default: printf("%s不是正确的指令,请输入正确的指禽 -p -u 或-l\n", argv[1]);
				printf("例如: %s [-p | -u | -l]\n", argv[0]);
		}
	}

	return 0;
}
时间: 2024-10-11 03:37:13

C Primer Plus (第五版) 第十一章 字符串和字符串函数 编程练习的相关文章

C primer plus 第五版十二章习题

看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: 1 /* global.c --- 使用外部变量 */ 2 #include <stdio.h> 3 int units = 0; //一个外部变量 4 void critic(void); 5 int main(void) 6 { 7 extern int units; 8 9 printf ("How many pounds

C++primer(第五版)第二章的学习笔记(也有对部分习题的解答和指出c++11特性)

算术类型分为两类:整型(字符和bool在内)和浮点型. C/C++算术类型 类型 含义 最小尺寸 bool 布尔类型 未定义 char 字符 8位 wchar_t 宽字符 16位 char16_t Unicode字符 16位 char32_t Unicode字符 32位 short 短整型 16位 int  整型 16位 long 长整型 32位 long long 长整型 64位 unsigned long 无符号长整型 32位 double 双精度浮点数 10位有效数字 long doubl

c++ primer(第五版)学习笔记及习题答案代码版(第十一章)关联容器

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,包含Chapter7.h头文件,读入文件包括./test ./rules .需要演示某一题直接修改 #define NUM****, 如运行11.23题为#define NUM1123: chapter 11 1.  关联容器不支持顺序容器的位置相关的操作,例如push_front或push_back.原因是关联容器中元素是根据关键字存储的,这些操作对 关联容器没有意义.而且关联容器也不支持构造函数或插入操作这些接收一个元素值和

C++ Primer【第五版】习题参考答案——第六章(函数)

本系列文章会不断更新,但是时间不能保证.另外基本上都是自己做的答案,仅供参考,如果有疑问欢迎交流. #include <iostream> #include <initializer_list> using namespace std; int test_Ex_6_27(std::initializer_list<int> li); int main() { cout << test_Ex_6_27({23,78,89,76,90}) << en

c++ primer(第五版)学习笔记及习题答案代码版(第十四章)重载运算与类型转换

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.h 和.cc 中,需要演示某一题直接修改 #define NUM****, 如运行14.30题为#define NUM1430: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful f

C++ Primer【第五版】习题参考答案——第五章(语句)

#include <iostream> #include <vector> #include <string> using namespace std; /******************************************************************* Ex_5_1: 空语句就是只含有一个分号的语句. 如果在程序的某个地方,语法上要求有一条语句,但是逻辑上不需要, 这时就需要一条空语句. Ex_5_2: 块就是由花括号包围的复合语句

c++ primer(第五版)学习笔记及习题答案代码版(第六章)函数

笔记较为零散,都是自己不熟悉的知识点. 习题答案至于一个.cc 中,编译需要包含Chapter6.h头文件. 需要演示某一题直接修改 #define NUM***, 如运行6.23题为#define NUM623: chapter 6 1. 形参初始化的机理与变量初始化一样. 当形参是引用类型时,它对应的实参被引用传递或者函数被传引用调用. 2. const和实参 void fcn(const int i){ /*fcn能够读取i,但是不能向i写值*/} void fcn(int i){ /*.

C++ Primer(第五版) 笔记 C01-02

C01 ++val; 优于 val++; 对数量不定的输入数据:while(cin>>value)... 遇到无效的输入或eof后,cin变为无效状态,条件变为假. 来自标准库的头文件用<>包围,不属于标准库的用""包围. 文件重定向工作:exename.exe <infile >outfile 点运算符:左侧运算对象是类类型的,右侧是该类型的成员. 参数 = 实参 = 值,形参指出调用函数可使用什么实参. 定义在函数内部的内置类型通常不初始化. C

《C++Primer》第五版习题详细答案--目录

作者:cosefy ps: 答案是个人学习过程的记录,仅作参考. <C++Primer>第五版习题答案目录 第一章:引用 第二章:变量和基本类型 第三章:字符串,向量和数组 第四章:表达式 原文地址:https://www.cnblogs.com/cosefy/p/12180771.html

C++ Primer Plus 第六版 第16章 string类和标准模板库

1.string实际上是模板具体化basic_string<char> 的一个typedef,有默认参数,所以省略了初始化参数 2.size_type是一个依赖于实现的整形 string将string::npos定义为字符串的最大长度 3.string类的构造函数P656 4.对于c-风格字符串,3种输入方法:cin>>   cin.getline(),cin.get 对于string   ,2种输入方法:cin>>,getline(cin,string对象) 5.st