1. 编写一个程序,从标准输入读取一些字符,并统计下列各类字符所占的百分比。
控制字符
空白字符
数字
小写字母
大写字母
标点符号
不可打印的字符
请使用在ctype.h头文件中定义的字符分类函数:
解析:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main( void ){
int ch;
int cntrl = 0;
int space = 0;
int digit = 0;
int lower = 0;
int upper = 0;
int punct = 0;
int unprint = 0;
int total = 0;
while( (ch = getchar()) != EOF ){
if( iscntrl( ch ) ){
cntrl++;
}
if( isspace( ch ) ){
space++;
}
if( isdigit( ch ) ){
digit++;
}
if( islower( ch ) ){
lower++;
}
if( isupper( ch ) ){
upper++;
}
if( ispunct( ch ) ){
punct++;
}
if( !isprint( ch ) ){
unprint++;
}
total++;
}
double cntrl_pec, space_pec, digit_pec, lower_pec, upper_pec, punct_pec, unprint_pec;
cntrl_pec = (double)cntrl / total * 100;
space_pec = (double)space / total * 100;
digit_pec = (double)digit / total * 100;
lower_pec = (double)lower / total * 100;
upper_pec = (double)upper / total * 100;
punct_pec = (double)punct / total * 100;
unprint_pec = (double)unprint / total;
printf( "cntrl_pec = %.2f%%, space_pec = %.2f%%, digit_pec = %.2f%%,\n"
"lower_pec = %.2f%%, upper_pec = %.2f%%, punct_pec = %.2f%%, unprint_pec = %.2f%%\n",
cntrl_pec, space_pec, digit_pec, lower_pec, upper_pec, punct_pec, unprint_pec );
return EXIT_SUCCESS;
}
输出:
2. 编写一个名叫my_strlen的函数。它类似于strlen函数,但它能够处理由于使用strn---函数而创建的未以NUL字节结尾的字符串。需要向函数传递一个参数,它的值就是这样一个数组的长度,即这个数组保存了需要进行长度测试的字符串。
解析:
非常不幸!标准函数库并没有提供这个函数。
/*
** 安全的字符串长度函数。它返回一个字符串的长度,即使字符串并未以NUL字节结尾。
** 'size'是存储字符串的缓冲区的长度。
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#define ARR_SIZE 10
size_t my_strlen( char const *string, int size );
int main( void ){
char string[ARR_SIZE] = {'\0'};
char string2[ARR_SIZE] = {'\0'};
char string3[ARR_SIZE] = {'\0'};
char string4[ARR_SIZE] = {'\0'};
char string5[ARR_SIZE] = {'\0'};
char string6[ARR_SIZE] = {'\0'};
char string7[ARR_SIZE * 2] = {'\0'};
size_t str_len;
printf( "condition: the length of string src is more than or equal to len:\n" );
printf( "the size of dst is smaller than len:\n" );
/*
** the string stored in dst is more than the size limit of dst,
** so the result of my_strlen function is wrong.
*/
/*
** wrong answer.
*/
strncpy( string, "abcdefghijk", ARR_SIZE + 1 );
printf( "string = %s\n", string );
str_len = my_strlen( string, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
/*
** the string stored in dst is smaller than or equal to the size limit of dst,
** so the result of my_strlen is correct. When the number of string stored in dst
** is equal to len, the string stored in dst doesn't ends with a '\0', otherwise
** ends with a '\0'.
*/
/*
** correct answer.
*/
printf( "the size of dst is equal to len:\n" );
strncpy( string2, "abcdefghijk", ARR_SIZE );
printf( "string2 = %s\n", string2 );
str_len = my_strlen( string2, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
/*
** correct answer.
*/
printf( "the size of dst is more than len:\n" );
strncpy( string3, "abcdefghijk", ARR_SIZE - 1 );
printf( "string3 = %s\n", string3 );
str_len = my_strlen( string3, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
printf( "condition2: the length of string src is smaller than len:\n" );
printf( "the size of dst is smaller than len:\n" );
/*
** the string stored in dst is more than the size limit of dst,
** if the size of dst is smaller than the length of string stored in src, dst[ARR_SIZE-1]
** is not '\0', the result of my_strlen is wrong. If the size of dst is equal to the length of
** string stored in src, dst[ARR_SIZE-1] is not also '\0', but the result of my_strlen is correct,
** If the size of dst is more than the length of string stored in src, dst[ARR_SIZE-1] is '\0'.
*/
/*
** wrong answer.
*/
printf( "the size of dst is smaller than the length of the string stored in the src:\n" );
strncpy( string4, "abcdefghijk", ARR_SIZE + 2 );
printf( "string4 = %s\n", string4 );
str_len = my_strlen( string4, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
/*
** correct answer.
*/
printf( "the size of dst is equal to the length of the string stored in the src:\n" );
strncpy( string5, "abcdefghij", ARR_SIZE + 2 );
printf( "string5 = %s\n", string5 );
str_len = my_strlen( string5, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
/*
** correct answer.
*/
printf( "the size of dst is larger than the length of the string stored in the src:\n" );
strncpy( string6, "abcdefghi", ARR_SIZE + 2 );
printf( "string6 = %s\n", string6 );
str_len = my_strlen( string6, ARR_SIZE );
printf( "str_len = %zd\n", str_len );
printf( "the size of dst is more than or equal to len:\n" );
/*
** the string stored in dst is smaller than the size limit of string,
** so the result of my_strlen is always correct. dst[ARRSIZE-1] is always '\0'.
*/
strncpy( string7, "abcdefghi", ARR_SIZE + 2 );
printf( "string7 = %s\n", string7 );
str_len = my_strlen( string7, ARR_SIZE * 2 );
printf( "str_len = %zd\n", str_len );
return EXIT_SUCCESS;
}
size_t my_strlen( char const *string, int size ){
register size_t length;
for( length = 0; length < size; length += 1 ){
if( *string++ == '\0' ){
break;
}
}
return length;
}
输出:
3. 编写一个名叫my_strcpy的函数,它类似于strcpy函数,但不会溢出目标数组。复制的结果必须是一个真正的字符串。
解析:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARR_SIZE 10
/*
** If elements copyed is more than or equal to dst_size,
** this function only copy dst_size - 1 elements to dst.
** Otherwise copy copy_size elements to dst.
*/
char *my_strcpy( char *dst, char const *src, size_t dst_size, size_t copy_size );
int main( void ){
char dst[ARR_SIZE];
char const *src = "hello";
my_strcpy( dst, src, ARR_SIZE, strlen( src ) );
printf( "after my_strcpy( dst, \"%s\", ARR_SIZE, strlen( \"%s\" ) ), dst = %s\n", src, src, dst );
return EXIT_SUCCESS;
}
char *my_strcpy( char *dst, char const *src, size_t dst_size, size_t copy_size ){
int arr_size;
int i;
int counter;
const char *psrc = src;
/*
** compute the character number in the src.
*/
counter = 0;
while( *psrc++ ){
counter++;
}
/*
** update the value of copy_size.
*/
if( counter < copy_size ){
copy_size = counter;
}
/*
** compute the number of value copyed.
*/
if( dst_size <= copy_size ){
arr_size = dst_size - 1;
} else{
arr_size = copy_size;
}
char *pdst = dst;
for( i = 0; i < arr_size; ++i ){
*pdst++ = *src++;
}
*pdst = '\0';
return dst;
}
输出:
4. 编写一个名叫my_strcat的函数。它类似于strcat函数,但不会溢出目标数组。它的结果必须是一个真正的字符串。
解析:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#define ARR_SIZE 10
/*
** If the sum of the length of the string stored in dst and copy_size is more than and equal to dst_size,
** the copy_size is changed into the value of dst_size substracts the sum of the length of the string stored
** in dst and one. because '\0' needs to occupy one byte in dst.
*/
char *my_strcat( char *dst, char const *src, size_t dst_size, size_t strcat_size );
int main( void ){
char dst[ARR_SIZE] = "hello" ;
char const *src = ",world!";
my_strcat( dst, src, ARR_SIZE, strlen( src ) );
printf( "after my_strcat( dst, \"%s\", ARR_SIZE, strlen( \"%s\" ) ), dst = %s\n", src, src, dst );
return EXIT_SUCCESS;
}
char *my_strcat( char *dst, char const *src, size_t dst_size, size_t strcat_size ){
size_t dst_counter;
char *pdst;
/*
** compute the length of string stored in dst.
*/
pdst = dst;
dst_counter = 0;
while( *pdst++ ){
dst_counter++;
}
/*
** the reason of pdst-- is *pdst++,
** leads to pdst add one again.
*/
pdst--;
/*
** update the copy_size to make dst because a string.
*/
if( dst_counter + strcat_size - 1 > dst_size ){
strcat_size = dst_size - dst_counter - 1;
}
printf( "strcat_size = %d\n", strcat_size );
/*
** concatenate strcat_size elements in src to the behind of the end of dst.
*/
int i;
for( i = 0; i < strcat_size; ++i ){
*pdst = *src;
src++;
pdst++;
}
*pdst = '\0';
return dst;
}
输出:
5. 编写下面的函数:
void my_strncat( char *dest, char *src, int dest_len );
它用于把src中的字符串连接到dest中原有字符串的末尾,但保证不会溢出长度为dest_len的dest数组。和strncat函数不同,这个函数也会考虑原先存在于dest数组的字符串长度,因此能够保证不会超越数组边界。
解析:
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 12
void my_strncat( char *dest, char *src, int dest_len );
int main( void ){
char dst[ARR_SIZE] = "hello" ;
char src[] = ",world!";
my_strncat( dst, src, ARR_SIZE );
printf( "after my_strncat( dst, \"%s\", %d ), dst = %s\n", src, ARR_SIZE, dst );
return EXIT_SUCCESS;
}
void my_strncat( char *dest, char *src, int dest_len ){
size_t dst_counter;
char *pdst;
/*
** compute the length of string stored in dst.
*/
pdst = dest;
dst_counter = 0;
while( *pdst++ ){
dst_