4.1 闰年判断语句(先处理最为特殊的情况)
if( year % 400 == 0 )
leap_year = 1;
else if( year % 100 == 0 )
leap_year = 0;
else if( year % 4 == 0 )
leap_year = 1;
else
leap_year = 0;
4.2 计算一个正数的平方根
#include <stdio.h>
#include <stdlib.h>
int
main()
{
float new_guess, last_guess, num;
printf( "Enter a number: " );
scanf( "%f", &num );
if( num < 0 ){
printf( "Cannot compute the square root of a "
"negative number!\n" );
return EXIT_FAILURE;
}
new_guess = 1;
do {
last_guess = new_guess;
new_guess = ( last_guess + num / last_guess ) / 2;
printf( "%.15e\n", new_guess );
} while( new_guess != last_guess );
printf( "Square root of %g is %g\n", num, new_guess );
return EXIT_SUCCESS;
}
这个函数的返回值是把value的二进制位模式从左到右变换一下后的值。编写函数时要注意不要让它依赖于你的机器上整型值的长度。
unsigned int
reverse_bits( unsigned int value )
{
unsigned int answer, i;
answer = 0;
/*
** 只要i不是0就继续进行。这就使循环与机器的字长无关,从而避免了可移植性问题。
*/
for( i = 1; i != 0; i << 1 ){
answer << 1;
if(value & 1)
answer |= 1;
value >> 1;
}
return answer;
}
6.1 编写函数reverse_string,它的原型如下:
void reverse_string( char *string );
函数把参数字符串中的字符反向排列。请使用指针而不是数组下标,不要使用任何C函数库中用于操纵字符串的函数。提示:不要声明一个局部数组来临时存储参数字符串。
void reverse_string( char *str )
{
char *last_char;
for( last_char = str; *last_char != '\0'; last_char++ )
;
last_char--;
while( str < last_char ){
char temp;
temp = *str;
*str++ = *last_char;
*last_char-- = temp;
}
}
8.1 编写一个函数,用于执行两个矩阵的乘法。函数的原型应该如下:
void matrix_multiply( int *m1, int *m2, int *r, int x, int y, int z );
void matrix_multiply( int *m1, int *m2, register int *r, int x, int y, int z )
{
register int *m1p;
register int *m2p;
register int k;
int row;
int column;
for( row = 0; row < x; row += 1 ){
for( column = 0; column < y; column += 1 ){
m1p = m1 + row * y;
m2p = m2 + column;
*r = 0;
for( k = 0; k < y; k += 1 ){
*r += *m1p * *m2p;
m1p += 1;
m2p += z;
}
r++;
}
}
}
9.1 编写一个程序,对标准输入进行扫描,并对单词“the”出现的次数进行计数。进行比较时应该区分大小写,所以“The”和“THE”并不计算在内。你可以认为各单词由一个或多个空格字符分隔,而且输入行在长度上不会超过100个字符。计数结果应该写到标准输出上。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char const whitespace[] = " \n\r\f\t\v";
int
main()
{
char buffer[101];
int count = 0;
while( gets( buffer ) ){
char *word;
for( word = strtok( buffer, whitespace );
word != NULL;
word = strtok( NULL, whitespace ) ){
if( strcmp( word, "the" ) == 0 )
count++;
}
}
printf( "%d\n", count );
return EXIT_SUCCESS;
}
9.2 标准I/O库并没有提供一种机制,在打印大整数时用逗号进行分隔。在这个练习中,你需要编写一个程序,为美元数额的打印提供这个功能。函数把一个数字字符串(代表以美分为单位的金额)转换为美元形式,下面是函数的原型:
void dollars( char *dest, char const *str );
#include <stdio.h>
void
dollars( register char *dst, register char const *src )
{
int len;
if( dst == NULL || src == NULL )
return;
*dst++ = '$';
len = strlen( src );
if( len >= 3 ){
int i;
for( i = len - 2; i > 0; ){
*dst++ = *src++;
if( --i > 0 && i % 3 == 0 )
*dst++ = ',';
}
}
else
*dst++ = '0';
*dst++ = '.';
*dst++ = len < 2 ? '0' : *src++;
*dst++ = len < 1 ? '0' : *src;
*dst = 0;
}
11.1 编写一个函数,从标准输入读取一列整数,把这些值存储于一个动态分配的数组中并返回这个数组。函数通过观察EOF判断输入列表是否结束。数组的第1个数是数组包含的值的个数,它的后面就是这些整数值。
#include <stdio.h>
#include <malloc.h>
#define DELTA 100
int *
readints()
{
int *array;
int size;
int count;
int value;
size = DELTA;
array = malloc( ( size + 1 ) * sizeof( int ) );
if( array == NULL )
return NULL;
count = 0;
while( scanf( "%d", &value ) == 1 ){
count++;
if( count > size ){
size += DELTA;
array = realloc( array, ( size + 1 ) * sizeof( int ) );
if( array == NULL )
return NULL;
}
array[ count ] = value;
}
if( count < size ){
array = realloc( array, ( count + 1 ) * sizeof( int ) );
if( array == NULL )
return NULL;
}
array[ 0 ] = count;
return array;
}
13.1 编写一个程序,从标准输入读取一些字符,并根据下面的分类计算各类字符所占的百分比:
控制字符
空白字符
数字
小写字母
大写字母
标号字母
不可打印字母
这些字符的分类是根据ctype.h中的函数定义的。不能使用一系列的If语句。
#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 ] ) )
char *label[] = {
"control",
"whitespace",
"digit",
"lower case",
"upper case",
"punctuation",
"non-printable"
};
int count[ N_CATEGORIES ];
int total;
int
main()
{
int ch;
int category;
while( ( ch = getchar() ) != EOF ){
total++;
for( category = 0; category < N_CATEGORIES; category++ ){
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++ ){
printf( "%3.0f%% %s characters\n",
count[ category ] * 100.0 / total,
label[ category ] );
}
}
return EXIT_SUCCESS;
}
15.1 UNIX的fgrep程序从命令行接受一个字符串和一系列文件名作为参数。然后,它逐个查看每个文件的内容。对于文件中每个包含命令行中给定字符串的文本行,程序将打印出它所在的文件名、一个冒号和包含该字符串的行。编写这个程序。首先出现的是字符串参数,它不包含任何换行字符。然后是文件名参数。如果没有给出任何文件名,程序应该从标准输入读取。在这种情况下,程序所打印的行不包括文件名和冒号。你可以假定个文件所有文本行的长度都不会超过510个字符。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 512
void
search( char *filename, FILE *stream, char *string )
{
char buffer[ BUFFER_SIZE ];
while( fgets( buffer, BUFFER_SIZE, stream ) != NULL ){
if( strstr( buffer, string ) != NULL ){
if( filename != NULL )
printf( "%s:", filename );
fputs( buffer, stdout );
}
}
}
int
main( int ac, char **av )
{
char *string;
if( ac <= 1 ){
fprintf( stderr, "Usage: fgrep string file ...\n" );
exit( EXIT_FAILURE );
}
string = *++av;
if( ac <= 2 )
search( NULL, stdin, string );
else{
while( *++av != NULL ){
FILE *stream;
stream = fopen( *av, "r" );
if( stream == NULL )
perror( *av );
else{
search( *av, stream, string );
fclose( stream );
}
}
}
return EXIT_SUCCESS;
}