分析总结:
这道题有几个需要注意的地方。
第一,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(),并在代码中调用该函数实现上述功能。该函数的实现要考虑各种可能的参数取值,以确保程序不出现崩溃。
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
源代码:
#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”表示。
*/