1. 编写一个程序,从标准输入读取一些字符,并根据下面的分类计算各类字符所占的百分比。
控制字符
空白字符
数字
小写字母
大写字母
不可打印字符
这些字符的分类是根据ctype.h中的函数定义的。不能使用一系列的if语句。
解析:
这个问题是在第9章给出的,但那里没有对if语句施加限制。这个限制的意图是促进你考虑其他实现方法。函数is_not_print的结果是isprint函数返回值的负值,它避免了主循环处理特殊情况的需要,每个函数保存了函数指针、标签以及每种类型的计数值。
/*
** 计算从标准输入的几类字符的百分比。
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/*
** 定义一个函数,判断一个字符是否为可打印字符。这可以消除下面代码中这种类型的特殊情况。
*/
int is_not_print( int ch ){
return !isprint( ch );
}
/*
** 用于区别每种类型的分类函数的跳转表。
*/
static int(*test_func[])( int ) = {
iscntrl,
isspace,
isdigit,
islower,
isupper,
ispunct,
is_not_print
};
#define N_CATEGORIES (sizeof(test_func) / sizeof(test_func[0]))
/*
** 每种字符类型的名字。
*/
const char *label[] = {
"control",
"whitespace",
"digit",
"lower case",
"upper case",
"punctuation",
"non_printable"
};
/*
** 目前见到的每种类型的字符数以及字符的总量。
*/
int count[N_CATEGORIES];
int total;
int main( void ){
int ch;
int category;
/*
** 读取和处理每个字符。
*/
while( (ch = getchar()) != EOF ){
total += 1;
/*
** 为这个字符调用每个测试函数。如果结果为真,增加对应计数器的值。
*/
for( category = 0; category < N_CATEGORIES; category += 1 ){
if( test_func[category]( ch ) ){
count[category] += 1;
}
}
}
/*
** 打印结果。
*/
if( total == 0 ){
printf( "No characters in the input!\n" );
} else{
for( category = 0; category < N_CATEGORIES; category += 1 ){
printf( "%3.0f%% %s characters\n", count[category] * 100.0 / total, label[category] );
}
}
return EXIT_SUCCESS;
}
输出:
2. 编写一个通用目的函数,用于遍历一个单链表。它应该接受两个参数:一个指向链表第一个节点的指针和一个指向一个回调函数的指针。回调函数应该接受单个参数,也就是指向一个链表节点的指针。对于链表中的每个节点,都应该调用一次这个回调函数。这个函数需要知道链表节点的什么信息?
解析:
需要知道这个节点是否为空,不为空则打印列表信息。
#include <stdio.h>
#include <stdlib.h>
#define ELEMENT_TYPE int
typedef struct NODE{
ELEMENT_TYPE value;
struct NODE *link;
} Node;
void print( void const *node );
void traverse( Node *first, void (*pf)( void const * ) );
int main( void ){
Node third;
Node second;
Node first;
third = (Node){ 3, NULL };
second = (Node){ 2, &third };
first = (Node){ 1, &second };
printf( "traverse the single linked list:\n" );
traverse( &first, print );
return EXIT_SUCCESS;
}
void print( void const *node ){
printf( "%d ", ((Node*)node)->value );
}
void traverse( Node *first, void (*pf)( void const * ) ){
while( first ){
pf( first );
first = first->link;
}