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

来源:互联网 发布:企业软件定制 编辑:程序博客网 时间:2024/06/06 02:06

分析总结:

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

第一,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”表示。
   
*/

原创粉丝点击