《C Primer Plus》第 11 章复习题和编程练习

目录

一、复习题

1. 下面字符串的声明有什么问题?

cpp 复制代码
int main(void)
{
	char name[] = {'F', 'e', 's', 's'};
	...
}

答:字符串是以空字符('\0')结尾的一系列字符,上述代码声明的是一个字符数组,并不是字符串。

2. 下面的程序会打印什么?

c 复制代码
#include <stdio.h>

int main(void)
{
	char note[] = "See you at the snack bar.";
	char *ptr;

	ptr = note;
	puts(ptr);
	puts(++ptr);
	note[7] = '\0';
	puts(note);
	puts(++ptr);
	return 0;
}

答:结果如下:

See you at the snack bar.

ee you at the snack bar.

See you

e you

3. 下面的程序会打印什么?

c 复制代码
#include <stdio.h>
#include <string.h>
int main(void)
{
	char food[] = "Yummy";
	char *ptr;

	ptr = food + strlen(food);
	while (--ptr >= food)
		puts(ptr);
	return 0;
}

答:结果如下:

y

my

mmy

ummy

Yummy

4. 下面的程序会打印什么内容?

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
	char goldwyn[40] = "art of it all";
	char samuel[40] = "I read p";
	const char *quote = "the way through.";

	strcat(goldwyn, quote);
	strcat(samuel, goldwyn);
	puts(samuel);
	return 0;
}

答:该程序先把字符串 quote 拼接在字符串 goldwyn 后面,再把字符串 goldwyn 拼接在字符串 samuel 后面,(注意数组是否能容纳)。结果如下:

I read part of it all the way through.

5. 下面的练习涉及字符串、循环、指针和递增指针。首先,假设定义了下面的函数。

c 复制代码
#include <stdio.h>

char *pr(char *str)
{
	char *pc;

	pc = str;
	while (*pc)
		putchar(*pc++)
	do
	{
		putchar(*--pc);
	} while (pc - str);
	return (pc);
}

考虑下面的函数调用:
x = pr("Ho Ho Ho!");
a. 将打印什么?
b. x 是什么类型?
c. x 的值是什么?
d. 表达式 *--pc 是什么意思?与 --*pc 有何不同?
e. 如果用 *pc-- 替换 *--pc,会打印什么?
f. 两个 while 循环用来测试什么?
g. 如果 pr() 函数的参数是空字符串,会怎么样?
h. 必须在主调函数中做什么,才能让 pr() 函数正常运行?

答:
a. 将打印如下内容:

Ho Ho Ho!!oH oH oH

b. char*,即字符指针

c. 字符串 "Ho Ho Ho!" 的首地址

d. 表达式 *--pc 先对指针 pc 减 1,然后解引用;而 --*pc 先对指针 pc 解引用,然后对解引用后的值减 1

e. 少打印一个 'H',即打印结果为:Ho Ho Ho!!oH oH o

f. 第 1 个 while 循环用来测试是否到达字符串末尾的空字符('\0'),第 2 个 while 循环用来测试是否到达该字符串的首字符

g. 由于 *pc 为空字符('\0'),所以不会进入第 1 个 while 循环,而第二个 while 循环先对 pc 递减,则表达式 pc - str 永远为负,该循环一直进行。

h. 主调函数需要声明该函数 char* pr(char str); ,且主调函数需要声明指针变量 x,即 char* x 。

6. 假设有如下声明:

c 复制代码
char sign = '$';

sign 占用多少字节的内存?'' 占用多少字节的内存?"" 占用多少字节的内存?

答:sign 是 char 变量,占 1 个字节的内存。'' 是 char 字面值常量,占 1 个字节内存,而 "" 是字符串字面值,末尾还有空字符('\0'),占 2 个字节内存。

7. 下面的程序会打印什么?

c 复制代码
#include <stdio.h>
#include <string.h>
#define M1 "How are ya, sweetie? "
char M2[40] = "Beat the clock.";
char *M3 = "chat";
int main()
{
	char words[80];
	printf(M1);
	puts(M1);
	puts(M2);
	puts(M2 + 1);
	strcpy(words, M2);
	strcat(words, " Win a toy.");
	puts(words);
	words[4] = '\0';
	puts(words);
	while (*M3)
		puts(M3++);
	puts(--M3);
	puts(--M3);
	M3 = M1;
	puts(M3);
	return 0;
}

答:输出结果如下:

How are ya, sweetie? How are ya, sweetie?

Beat the clock.

eat the clock.

Beat the clock. Win a toy.

Win

chat

hat

at

t

t

at

How are ya, sweetie?

8. 下面的程序会打印什么?

c 复制代码
#include <stdio.h>
int main()
{
	char str1[] = "gawsie";
	char str2[] = "bletonism";
	char *ps;
	int i = 0;
	for (ps = str1; *ps != '\0'; ps++)
	{
		if (*ps == 'a' || *ps == 'e')
			putchar(*ps);
		else
			(*ps)--;
		putchar(*ps);
	}
	putchar('\n');
	while (str2[i] != '\0')
	{
		printf("%c", i % 3 ? str2[i] : '*');
		++i;
	}
	return 0;
}

答:结果如下:

faavrhee

*le*on*sm

9. 本章定义的 s_gets() 函数,用指针表示法代替数组表示法便可减少一个变量 i。请改写该函数

答:
程序设计分析: 指针表示法需要让该指针往后走,直到遇到换行符或者空字符。

代码如下:

c 复制代码
char * s_gets(char * st, int n)
{
	char * ret_val;

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

10. strlen() 函数接受一个指向字符串的指针作为参数,并返回该字符串的长度。请编写一个这样的函数。

答:
程序设计分析: 使用 int 变量进行计数,直到查找到该字符串末尾的空字符(空字符不计入)。该函数返回类型为 int,接受一个 char 类型的指针

代码如下:

c 复制代码
int my_strlen(char* s)
{
	int n = 0;
	while (*s++)
		++n;
	return n;
}

11. 对于本章定义的 s_gets() 函数,可以用 strchr() 函数代替其中的 while 循环来查找替换换行符。请改写该函数。

答:
程序设计分析: 使用 strchr() 函数,需要包含头文件 string.h

代码如下:

c 复制代码
// 头文件
#include <string.h>

char * s_gets(char * st, int n)
{
	char * ret_val;
	char * find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
			*find = '\0';
		else
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}	

12. 设计一个函数,接受一个指向字符串的指针,返回指向该字符串中第一个空格字符的指针,如果未找到空格字符,则返回空指针。

答:
程序设计分析: 使用循环逐个字符查找,若遇到空格则停止返回,若遇到空字符,则返回空指针。

代码如下:

c 复制代码
char* find_blank(char* s)
{
	while (*s && *s != ' ')
		++s;
	// 判断
	if (*s)
		return s;
	else
		return null;
}

13. 重写程序清单 11.21,使用 ctype.h 头文件中的函数,需求无论用户选择大写还是小写,该程序都能正确识别答案。

答:
程序设计分析: 设计一个函数,该函数接受一个字符串,然后把该字符串的字母都编程大写。然后再输入答案之后,执行该函数。

代码如下:

c 复制代码
// 头文件
#include <stdio.h>
#include <string.h>

// 常量声明
#define ANSWER "Grant"
#define SIZE 40

// 函数声明
char * s_gets(char * st, int n);
void upper(char* str);

int main()
{
	char try[SIZE];

	puts("Who is buried in Grant's tomb?");
	s_gets(try, SIZE);
	upper(try);
	while (strcmp(try, ANSWER) != 0)
	{
		puts("No, that's wrong. Try again.");
		s_gets(try, SIZE);
		upper(try);
	}
	puts("That's right);

	return 0;
}

// 函数定义
char * s_gets(char * st, int n)
{
	char * ret_val;
	char * find;

	ret_val = fgets(st, n, stdin);
	if (ret_val)
	{
		find = strchr(st, '\n');
		if (find)
			*find = '\0';
		else
			while (getchar() != '\n')
				continue;
	}
	return ret_val;
}

void upper(char* str)
{
	while (*str)
	{
		*str = toupper(*str);
		++str;
	}
}	

二、编程练习

1. 设计并测试一个函数,从输入中获取 n 个字符(包括空白、制表符、换行符),把结果存储在一个数组里,它的地址被传递作为一个参数。

答:
程序设计分析: 该函数的返回类型为 void,接受一个字符指针和 int 值作为参数。

代码如下:

c 复制代码
#include <stdio.h>

// 常量声明
#define SIZE 100

// 函数声明
void get_n_char(char* arr, int n);

int main()
{
	// 所需变量
	char arr[100] = { 0 };
	int n = 0;

	// 输入
	printf("请输入带输入的字符数量:");
	scanf("%d", &n);
	get_n_char(arr, n);

	return 0;
}

// 函数定义
void get_n_char(char* arr, int n)
{
	int i = 0;
	do
	{
		arr[i] = getchar();
	} while (arr[i] != EOF && ++i < n);
}

2. 修改编程练习 1 的函数,在 n 个字符后停止,或在督导第 1 个空白、制表符或换行符时停止,那个先遇到哪个停止。不能只使用 scanf()。

答:
程序设计分析: 读取字符后检查是否为空白,若为空白则使用 break 跳出循环。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 常量声明
#define SIZE 100

// 函数声明
void get_n_char(char* arr, int n);

int main()
{
	// 所需变量
	char arr[100] = { 0 };
	int n = 0;

	// 输入
	printf("请输入带输入的字符数量:");
	scanf("%d", &n);
	get_n_char(arr, n);

	return 0;
}

// 函数定义
void get_n_char(char* arr, int n)
{
	int i = 0;
	do
	{
		arr[i] = getchar();
		// 是空白就跳出循环
		if (isspace(arr[i]))
			break;
	} while (arr[i] != EOF && ++i < n);
}

3. 设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第 1 个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。

答:
程序设计分析: 该函数检验两次空白,第 1 次检验直到单词开头,第 2 次检验直到单词末尾。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 常量声明
#define SIZE 100

// 函数声明
char* get_word(char* arr);

int main()
{
	// 所需变量
	char arr[SIZE] = { 0 };

	// 输入一个单词
	get_word(arr);

	// 输出验证
	puts(arr);

	return 0;
}

// 函数定义
char* get_word(char* arr)
{
	char temp[SIZE] = { 0 };
	char* p = temp;
	// 读取一行输入
	fgets(temp, SIZE, stdin);
	// 删除前面的空白
	while (isspace(*p) && *p)
		++p;
	// 读取单词
	while (!isspace(*p) && *p)
		*arr++ = *p++;

	return arr;
}

4. 设计并测试一个函数,它类似于编程练习 3 的描述,只不过它通过第 2 个参数指明可以读取的最大字符数。

答:
程序设计分析: 只不过在上一题的代码中添加一个输入字符限制的条件罢了。函数声明、函数调用和函数定义做相关修改。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 常量声明
#define SIZE 100
#define LIT 5

// 函数声明
char* get_word(char* arr, int n);

int main()
{
	// 所需变量
	char arr[SIZE] = { 0 };

	// 输入一个单词
	get_word(arr, LIT);

	// 输出验证
	puts(arr);

	return 0;
}

// 函数定义
char* get_word(char* arr, int n)
{
	char temp[SIZE] = { 0 };
	char* p = temp;
	int i = 0;
	// 读取一行输入
	fgets(temp, SIZE, stdin);
	// 删除前面的空白
	while (isspace(*p) && *p)
		++p;
	// 读取单词
	while (!isspace(*p) && *p)
	{
		*arr++ = *p++;
		// 检测是否超出限制
		if (++i >= n)
			break;
	}

	return arr;
}

5. 设计并测试一个函数,搜索第 1 个函数形参指定的字符串,在其中查找第 2 个函数形参指定的字符首次出现的位置。如果成功,则返回该字符的指针,如果在字符串中未找到指定字符,则返回空指针(该函数的功能与 strchar() 函数相同)。在一个完整的程序中测试该函数,使用一个循环给函数输入值。

答:
程序设计分析: 该函数返回类型为 char*,接受一个 char* 值和 char 值。在该函数中使用循环遍历字符串,查找目标字符首次出现的位置。

代码如下:

c 复制代码
#include <stdio.h>

// 常量声明
#define SIZE 40

// 函数声明
char* find_char(char* str, char ch);

int main()
{
	// 所需变量
	char temp[SIZE] = { 0 };
	char ch = 'c';

	// 输入
	printf("请输入一段字符:");
	while (fgets(temp, SIZE, stdin) && temp[0] != '\n')
	{
		char* position = find_char(temp, ch);
		if (position)
			printf("%c 字符首次出现的地址为:%p\n", ch, position);
		else
			printf("未找到字符 %c\n", ch);

		// 下一个
		printf("请输入下一段字符:");
	}

	return 0;
}

// 函数定义
char* find_char(char* str, char ch)
{
	while (*str)
	{
		if (*str == ch)
			return str;
		else
			++str;
	}
	return NULL;
}

6. 编写一个名为 is_within() 的函数,该函数以一个字符和一个指向字符串的指针作为两个函数的形参。如果指定的字符在字符串中,该函数返回一个非零值(即为真);否则,返回 0(即为加)。在一个完整的函数中测试该函数,使用一个循环给函数提供输入值。

答:
程序设计分析: 该题目和上一题几乎完全一样,只不过返回值用 0 或非 0 值代替了。

代码如下:

c 复制代码
#include <stdio.h>

// 常量声明
#define SIZE 40

// 函数声明
int is_within(char ch, char* str);

int main()
{
	// 所需变量
	char temp[SIZE] = { 0 };
	char ch = 'c';

	// 输入
	printf("请输入一段字符:");
	while (fgets(temp, SIZE, stdin) && temp[0] != '\n')
	{
		if (is_within(ch, temp))
			printf("该字符串中包含字符 %c\n", ch);
		else
			printf("该字符串中没有字符 %c\n", ch);

		// 下一个
		printf("请输入下一段字符:");
	}

	return 0;
}

// 函数定义
int is_within(char ch, char* str)
{
	while (*str)
	{
		if (*str == ch)
			return 1;
		else
			++str;
	}
	return 0;
}

7. strncpy(s1, s2, n) 函数把 s2 中的 n 个字符复制至 s1 中,截断 s2,或者根据需要在末尾添加空字符。如果 s2 的长度是 n 或者大于 n,目标字符串不能以空字符结尾。该函数返回 s1.自己编写一个这样的函数,使用一个循环给函数提供输入值。

答:
程序设计分析: 该函数需要对源字符串的长度和限制拷贝的长度进行比较,来判断是否需要在末尾添加换行符。

代码如下:

c 复制代码
#include <stdio.h>

// 常量声明
#define SIZE 100

// 函数声明
char* my_strncpy(char* t, char* s, int n);

int main()
{
	// 所需变量
	char source[SIZE] = { 0 };
	char target[SIZE] = { 0 };
	int n = 0;

	do
	{
		printf("请输入要拷贝的字符串:");
		fgets(source, SIZE, stdin);
		// 输入空行退出循环
		if (source[0] == '\n')
			break;
		printf("请输入需要拷贝的字符数:");
		scanf("%d", &n);
		// 清理换行符
		while (getchar() != '\n')
			continue;
		// 拷贝输出
		my_strncpy(target, source, n);
		puts(target);

	} while (1);

	return 0;
}

// 函数定义
char* my_strncpy(char* t, char* s, int n)
{
	char* ret = t;
	int i = 0;

	while (s[i] && i < n)
	{
		t[i] = s[i];
		++i;
	}

	if (i < n)
		t[i] = '\0';

	return ret;
}

**8. 编写一个名为 string_in() 的函数,该函数以两个指向字符串的指针作为参数。如果第 2 个字符串包含第 1 个字符串,该函数将返回第 1 个字符串开始的地址。例如,string_in("hats", "at") 将返回 hats 中 a 的地址。否则,返回空指针。在一个完整的程序中测试该函数,使用一个循环给该函数提供值。

**

答:
程序设计分析: 使用 string.h 头文件中的 strchar() 函数,找到目标字符串的首字符,然后使用 strcnmp() 函数进行比较。若不是,则往后继续如此。

代码如下:

c 复制代码
#include <stdio.h>
#include <string.h>

// 常量声明
#define SIZE 40

// 函数声明
char* string_in(char* s, char* t);

int main()
{
	// 所需变量
	char source[SIZE] = { 0 };
	char target[SIZE] = { 0 };
	char* p = NULL;

	// 输入
	do
	{
		printf("输入源字符串:");
		fgets(source, SIZE, stdin);
		// 如果输入空行结束循环
		if (source[0] == '\n')
			break;
		printf("输入需要找的字符串:");
		scanf("%s", target);
		// 清理换行符
		while (getchar() != '\n')
			continue;

		// 查找
		p = string_in(source, target);
		if (p)
			printf("地址:%p\n", p);
		else
			printf("没有\n");
	} while (1);

	return 0;
}

// 函数定义
char* string_in(char* s, char* t)
{
	int len = strlen(t);
	while (s = strchr(s, *t))
	{
		if (!strncmp(s, t, len))
			return s;
		else
			++s;
	}

	return NULL;
}

9. 编写一个函数把字符串的内容用其反序字符串代替。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

答:
程序设计分析: 该函数实现字符串的逆序,使用 strlen() 函数,找到字符串的末尾,然后与开头一个一个对调。

代码如下:

c 复制代码
#include <stdio.h>
#include <string.h>

// 常量声明
#define SIZE 100

// 函数声明
void reverse_str(char* str);

int main()
{
	// 所需变量
	char str[SIZE] = { 0 };

	// 输入
	do
	{
		printf("请输入字符串: ");
		fgets(str, SIZE, stdin);

		// 空行结束循环
		if (str[0] == '\n')
			break;

		// 把字符串 str 中的换行符删掉
		int len = strlen(str);
		if (str[len - 1] == '\n')
			str[len - 1] = '\0';

		reverse_str(str);
		printf("逆序后的结果: ");
		fputs(str, stdout);
		putchar('\n');
	} while (1);

	return 0;
}

// 函数定义
void reverse_str(char* str)
{
	char* begin = str;
	char* end = str + strlen(str) - 1;
	char temp = 0;

	while (begin < end)
	{
		temp = *begin;
		*begin = *end;
		*end = temp;

		// 下一对字符
		++begin;
		--end;
	}
}

10. 编写一个函数,该函数以一个字符串作为参数,并可以删除字符串中的空格。在一个程序中测试该函数,使用循环读取输入行,直到用户输入一个空行。该程序应该应用该函数读取每个输入的字符串,并显示处理后的结果。

答:
程序设计分析: 该函数返回 int 值,若读取空行返回 0,否则返回 1。使用循环遍历该字符串,找到空格并删除,然后把后面的字符往前面移动。

代码如下:

c 复制代码
#include <stdio.h>

// 常量声明
#define SIZE 100

// 函数声明
int delete_bs(char* str);

int main()
{
	// 所需变量
	char str[SIZE] = { 0 };

	// 进入循环
	while (delete_bs(str))
	{
		// 输出
		printf("删除空格后的:");
		fputs(str, stdout);
	}

	return 0;
}

// 函数定义
int delete_bs(char* str)
{
	// 输入
	printf("请输入字符串:");
	fgets(str, SIZE, stdin);
	// 判断是否为空行
	if (str[0] == '\n')
		return 0;
	// 删除空格
	while (*str)
	{
		// 如果是空格,就把后面的字符往前面挪
		if (*str == ' ')
		{
			char* p = str + 1;
			char* b = str;
			while (*p && *p == ' ')
				++p;
			// 如果到末尾
			if (*p == '\0')
				*str = '\0';
			// 挪移
			while (*p)
			{
				*b++ = *p++;
			}
			*b = *p;
		}
		// 下一个字符
		++str;
	}

	return 1;
}

11. 编写一个程序,读入 10 个字符串或者在读到 EOF 时停止。该程序为用户提供一个有 5 个选项的菜单,5 个选项分别是打印原始字符串列表,以 ASCII 码中的顺序打印字符串,按长度递增顺序打印字符串,按字符串中第一个单词的长度打印字符串,退出。菜单可以循环显示,除非用户选择"退出"选项。当然,该程序要能真正实现菜单中各选项的功能。

答:
程序设计分析: 上述前四个选项各设计为一个函数,然后还有一个打印原字符串函数和菜单函数。(作者的代码有许多冗余的部分,可以试着拆成一个函数,缩减代码的行数)

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>
#include <string.h>

// 常量声明
#define NUM 10
#define SIZE 100

// 函数声明
void menu();
void print_origin(char str[][SIZE], int n);
void print_ascii(char str[][SIZE], int n);
void print_length(char str[][SIZE], int n);
void print_first_word(char str[][SIZE], int n);
void swap(char** s1, char** s2);
int first_word(char* str);


int main()
{
	// 所需变量
	int i = 0, select = 0;
	char str[NUM][SIZE] = { 0 };

	// 输入
	printf("Please input 10 strings seperate by enter.\n");
	for (i = 0; i < NUM; ++i)
	{
		fgets(str[i], SIZE, stdin);
	}

	// 进入循环
	do
	{
		// 显示菜单
		menu();
		// 选择
		scanf("%d", &select);
		switch (select)
		{
		case 1 :
			print_origin(str, NUM);
			break;
		case 2 :
			print_ascii(str, NUM);
			break;
		case 3 :
			print_length(str, NUM);
			break;
		case 4 :
			print_first_word(str, NUM);
			break;
		default :
			printf("Input error, retry.\n");
		}
	} while (select != 5);

	return 0;
}

// 函数定义
void menu()
{
	printf("*******************************************************\n");
	printf("1)print_origin                   2)print_ascii\n");
	printf("3)print_length                   4)print_first_word\n");
	printf("5)quit\n");
	printf("*******************************************************\n");
}

void print_origin(char str[][SIZE], int n)
{
	int i;
	for (i = 0; i < n; ++i)
		fputs(str[i], stdout);
}

void print_ascii(char str[][SIZE], int n)
{
	char* pstr[NUM] = { 0 };
	int i;
	for (i = 0; i < NUM; ++i)
		pstr[i] = str[i];

	// 排序
	for (i = 0; i < NUM - 1; ++i)
	{
		int j;
		for (j = 0; j < NUM - 1 - i; ++j)
		{
			if (strcmp(pstr[j], pstr[j + 1]) > 0)
			{
				swap(&pstr[j], &pstr[j + 1]);
			}
		}
	}

	// 输出
	printf("Length:\n");
	for (i = 0; i < NUM; ++i)
		fputs(pstr[i], stdout);
}

void print_length(char str[][SIZE], int n)
{
	char* pstr[NUM] = { 0 };
	int i;
	for (i = 0; i < NUM; ++i)
		pstr[i] = str[i];

	// 排序
	for (i = 0; i < NUM - 1; ++i)
	{
		int j;
		for (j = 0; j < NUM - 1 - i; ++j)
		{
			if (strlen(pstr[j]) > strlen(pstr[j + 1]))
			{
				swap(&pstr[j], &pstr[j + 1]);
			}
		}
	}

	// 输出
	printf("Length:\n");
	for (i = 0; i < NUM; ++i)
		fputs(pstr[i], stdout);
}

void print_first_word(char str[][SIZE], int n)
{
	char* pstr[NUM] = { 0 };
	int i;
	for (i = 0; i < NUM; ++i)
		pstr[i] = str[i];

	// 排序
	for (i = 0; i < NUM - 1; ++i)
	{
		int j;
		for (j = 0; j < NUM - 1 - i; ++j)
		{
			if (first_word(pstr[j]) > first_word(pstr[j + 1]))
			{
				swap(&pstr[j], &pstr[j + 1]);
			}
		}
	}

	// 输出
	printf("Length:\n");
	for (i = 0; i < NUM; ++i)
		fputs(pstr[i], stdout);
}


void swap(char** s1, char** s2)
{
	char* temp = *s1;
	*s1 = *s2;
	*s2 = temp;
}

int first_word(char* str)
{
	int len = 0;
	// 删除前面的空白
	while (*str && isspace(*str))
		++str;

	// 计算长度
	while (*str && !isspace(*str))
	{
		++len;
		++str;
	}

	return len;
}

12. 编写一个程序,读取输入,直到读到 EOF,报告读入的单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用 ctype.h 头文件中的函数。

答:
程序设计分析: 需要额外使用变量来判断是否为一个单词。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

int main()
{
	// 所需变量
	int ch = 0;
	int is_word = 0;
	int words = 0, u_words = 0, l_words = 0, puncts = 0, digits = 0;

	// 输入
	while ((ch = getchar()) != EOF)
	{
		// 单个字符判断
		if (isdigit(ch))
			++digits;
		else if (isupper(ch))
			++u_words;
		else if (islower(ch))
			++l_words;
		else if (ispunct(ch))
			++puncts;

		// 判断是否为一个单词
		if (isspace(ch) && is_word)
		{
			++words;
			is_word = 0;
		}
		if (!isspace(ch) && !is_word)
			is_word = 1;
	}

	// 输出
	printf("单词数:%d\n", words);
	printf("大写字母数:%d\n", u_words);
	printf("小写字母数:%d\n", l_words);
	printf("标点符号数:%d\n", puncts);
	printf("数字字符数:%d\n", digits);


	return 0;
}

13. 编写一个程序,反序显示命令行参数中的单词。例如,命令行参数是 see you later,该程序打印 later you see。

答:
程序设计分析: 该反序只是把命令行的参数倒过来打印。

代码如下:

c 复制代码
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc < 2)
		printf("Error! not enough parameter to display!\n");
	else
	{
		for (int i = argc; i > 1; --i)
		{
			printf("%s ", argv[i - 1]);
		}
		putchar('\n');
	}
}

14. 编写一个通过命令行参数运行的程序,用来计算幂。第 1 个命令行参数是浮点数,可作为幂的底数,第 2 个参数是整数,可作为幂的指数。

答:
程序设计分析: 该程序和普通的幂函数计算一样,只是使用了命令行参数。

代码如下:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	if (argc != 3)
	{
		printf("Error argument. Please retry.\n");
		return 0;
	}
	float f = atof(argv[1]);
	int n = atoi(argv[2]);

	float result = 1;

	// 计算幂
	int i;
	for (i = 0; i < n; ++i)
	{
		result *= f;
	}

	// 输出
	printf("该幂为:%.1lf\n", result);

	return 0;
}

15. 使用字符分类函数实现 atoi() 函数。如果输入的字符串不是纯数字,该函数返回 0。

答:
程序设计分析: 该函数接受一个字符串,把该字符串转换为数字,若包含非数字则返回 0。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 函数声明
int myatoi(char* str);

int main()
{
	char temp[50] = { 0 };
	printf("请输入一串数字:");
	scanf("%s", temp);
	printf("该数字为:%d\n", myatoi(temp));

	return 0;
}

// 函数定义
int myatoi(char* str)
{
	int result = 0;
	while (*str)
	{
		if (isdigit(*str))
			result = result * 10 + (*str - '0');
		else
			return 0;

		// 下一个字符
		++str;
	}

	return result;
}

16. 编写一个程序,用于读取输入,直至读到文件结尾,然后把字符串打印出来。该程序识别和实现下面的命令行参数:

答:
程序设计分析: 把上述操作三个操作分别定义成 3 个函数,然后根据命令行参数进行判断。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 常量声明
#define SIZE 256

// 函数声明
void print(char* str);
void print_upper(char* str);
void print_lower(char* str);

int main(int argc, char* argv[])
{
	char str[SIZE] = { 0 };
	char ch = 0;
	if (argc < 2)
		ch = 'p';
	else
		ch = argv[1][1];  // 忽略 - 号

	// 输入
	printf("Enter a string to convert:");
	fgets(str, SIZE, stdin);

	switch (ch)
	{
	case 'P':
	case 'p' :
		print(str);
		break;
	case 'u' :
	case 'U':
		print_upper(str);
		break;
	case 'L' :
	case 'l' :
		print_lower(str);
		break;
	}

	return 0;
}

// 函数定义
void print(char* str)
{
	printf("Original:\n");
	fputs(str, stdout);
}

void print_upper(char* str)
{
	char* p = str;

	while (*p)
	{
		*p = toupper(*p);
		++p;
	}

	printf("Upper:\n");
	fputs(str, stdout);
}

void print_lower(char* str)
{
	char* p = str;

	while (*p)
	{
		*p = tolower(*p);
		++p;
	}

	printf("Lower:\n");
	fputs(str, stdout);
}
相关推荐
_WndProc几秒前
C++ 日志输出
开发语言·c++·算法
qq_433554549 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
数据小爬虫@28 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.30 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy35 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
Hello.Reader43 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默1 小时前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_433618441 小时前
shell 编程(二)
开发语言·bash·shell