[编程练习与总结2] 根据关键字进行字符串拷贝

分析总结:

这道题有几个需要注意的地方。

第一,keyword可能含有空格(题中未说不含空格),不能用scanf("%s",...)直接读取,而是需要读取一整行,哪怕其中包含空格。

第二,如果在指定的字符串中未找到关键字,应该如何处理,这题目中居然没有说!经过多方试验,没有找到关键字的情况下,被认为正确的解决方案是完整拷贝源字符串。这一点是出题的纰漏之处,我已经用红色的字体把这一点加入到描述中。

第三,注意源字符串的结束,将它的长度加入循环判断(或者将字符不为'/0'加入循环判断)。

 

在这里需要巩固一下的知识点是如何正确的使用scanf函数族读取一行

1. scanf("%[^n]/n", ...)可以读取输入流中下一个'/n'之前的所有字符。

2. 需要确保上一次scan的时候,已经处理了上一个'/n',否则读取的会是一个空字符串。

例如:

有以下输入:

a

b c

如果用scanf("%s", ...)来读取"a",然后试图用 scanf("%[^n]/n", ...)读取"b c"是会失败的,因为"a"这一行的换行符还没有处理。

正确的做法是用scanf("%s/n", ...)来读取"a",然后用 scanf("%[^n]/n", ...)读取"b c".

 

关于scanf的详细使用方法以后再详解解说。

 

 

原题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3753

 

描述:

把源字符串拷贝到目的字符串,如果指定关键字,则以该关键字结束(不包括关键字本身),如果拷贝失败,则得到空串。如果源字符串中未找到关键字,则相当于strncpy。
具体要求:实现如下函数原型SafeStrcpy2KeyWord(),并在代码中调用该函数实现上述功能。该函数的实现要考虑各种可能的参数取值,以确保程序不出现崩溃。

 

C语言:
int SafeStrcpy2KeyWord( char * pDestBuffer , //拷贝的目的地地址

                         char * pSourceString , //拷贝的源地址

                         int nDestBufferSize , //拷贝的目的地缓冲区长度

                         char * szKeyWord); //指定关键字符串


返回值:所拷贝的字符串长度。如果拷贝失败,则返回0。

 

输入:

输入包含多组数据,以EOF结束
每组数据第一行为不含空格的源字符串,长度小于256;接下来的一行或多行都是关键字串(长度小于16),一直到END结束。"NULL"表示关键字串为空,此时输出的拷贝后的长度应为0,拷贝后的字符串为空串(也用"NULL"表示,见下文)。

 

输出:

对于每组数据输出拷贝的长度和拷贝后的目的字符串,以空格分隔。如果该目的字符串为空,则用"NULL"表示。

 

提示:

 

性能要求:

时间限制: 1秒 内存限制: 65536K

 

样本输入:

/home/tony/work_server/1/rtest/relayer.out
/
/t
/1/r
.
NULL
END

 

样本输出:

0 NULL
5 /home
22 /home/tony/work_server
38 /home/tony/work_server/1/rtest/relayer
0 NULL

 

 

源代码:

C语言:
#include <stdio.h>
#include <string.h>

#define STR_NULL "NULL"
#define STR_END     "END"

int SafeStrcpy2KeyWord( char * pDestBuffer ,    //拷贝的目的地地址

               char * pSourceString ,    //拷贝的源地址

               int nDestBufferSize ,    //拷贝的目的地缓冲区长度

               char * szKeyWord);            //指定关键字符串


int SafeStrcpy2KeyWord( char * pDestBuffer , char * pSourceString , int nDestBufferSize , char * szKeyWord)
{
    int ret = 0 , i;
    char * pFound = NULL;
   
    if( ! pDestBuffer ||! pSourceString|| nDestBufferSize <= strlen( pSourceString) ||! szKeyWord ||
        ! strcmp( szKeyWord , STR_NULL))
    {
        pDestBuffer = '/0';
        ret = 0;
    }
    else
    {
        pFound = strstr( pSourceString , szKeyWord);
        for( i = 0; i < strlen( pSourceString); i ++)
        {           
            if( pFound !=& pSourceString [ i ])
            {
                pDestBuffer [ i ] = pSourceString [ i ];
            }
            else
            {       
                ret = i;
                break;
            }           
        }
        if( i == strlen( pSourceString))
        {
            ret = i;
        }
        pDestBuffer [ i ] = '/0';
       
    }

    return( ret);
}

int main()
{
    char source [ 256 ] = "";                    /* R2  */
    char keyword [ 16 ] = "";                    /* R3  */
    char output [ 256 ] = "";                    /* R5-1*/
    int charcnt = 0;

    while( scanf( "%s /n " , source) != EOF)    /* R1 */
    {
        scanf( "%[^ /n ] /n " , keyword);    /* R3, R3-1 */
        while( strcmp( keyword , STR_END))    /* R3 */
        {
            if(( charcnt = SafeStrcpy2KeyWord( output , source , sizeof( output ), keyword)) > 0)
            {
                printf( "%d %s /n " , charcnt , output);
            }
            else
            {
                printf( "%d %s /n " , 0 , STR_NULL);
            }
            scanf( "%[^ /n ] /n " , keyword);    /* R3, R3-1 */
        }       
    }

}


/* in code document */
/*
    requirements:
    R1: 输入包含多组数据,以EOF结束
    R2: 每组数据第一行为不含空格的源字符串,长度小于256
    R3: 接下来的一行或多行都是关键字串(长度小于16),一直到END结束。
        R3-1: 注意没有说关键字串能否有空格
    R4: “NULL”表示关键字串为空,此时输出的拷贝后的长度应为0。
    R5: 对于每组数据输出拷贝的长度和拷贝后的目的字符串,以空格分隔。       
    R6: 如果该目的字符串为空,则用”NULL”表示。
   
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值