C和指针 第9章 字符串、字符和字节 9.14 编程练习

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_

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40186813

你的能量无可限量。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值