一个讨论的例子 [英] An Example for Discussion

查看:71
本文介绍了一个讨论的例子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自1999年以来,我一直远离C编程,而且我最近又把它带回了
。下面是我今天早上写的一个字符串函数,它将进入我自己开发的字符串函数库中。

。我从PL / SQL中的同名函数中提出了它的概念。我认为

在我的C库中会很方便。我的不同之处在于源字符串

参数被修改并从函数返回。


使用C字符串一直存在问题因为你可能会崩溃

a节目比你说的快杰克'你是叔叔!如果你不是小心的话。我的一些字符串函数我采用strcpy()方法和

将修改后的字符串中的副本复制到目标指针中,你只能将
希望指向足够大的东西在你的程序的数据中

空间。和其他人一起修改源字符串并返回一个

指针。有了这个功能,我觉得修改字符串

是安全的,因为最坏的情况是一个字符会被改为另一个字符和

充其量该字符将被从源中删除字符串,所以

没有机会溢出缓冲区。当然,有人会尝试使用字符串常量来表示字符串常量(即这是一个字符串)。

我以为我会发布代码和看看专家们说的话。对于

reference" strtools.h"是我的本土字符串的头文件

函数,chrsubst()用于替换字符串中的字符,

和str_rmchars()从一个字符中删除一组字符字符串。


/ **功能******************************** ******** ******************** /

/ *姓名:* /

/ * translate()。 * /

/ * * /

/ *简介:* /

/ * #include< strings.h> * /

/ * #include" strtools.h" * /

/ * char * translate(char * src,char * fromstr,char * tostr); * /

/ * * /

/ *说明:* /

/ *翻译功能将翻译出现的字符* /

/ *。如果fromstr字符* /

/ *在tostr字符串中具有相应的值,则src字符串中的所有字符* /

/ *将被转换为*的字符串/

/ *对应的tostr字符。如果tostr字符串中没有对应的* /

/ *字符,则字符将从源字符串中删除* /

/ *。 * /

/ * * /

/ *参数:* /

/ * char * source - 要检查和翻译的字符串。 * /

/ * char * fromstr-要在源中翻译的字符。 * /

/ * char * tostr - 源* /

/ *字符转换为的相应字符。 * /

/ * * /

/ *返回值:* /

/ *源字符串的起始地址。 * /

/ * * /

/ *************************** *********************** **********功能** /


char *

translate(char * p_source,char * p_from_string,char * p_to_string)

{

unsigned x_sub = 0,l_len = strlen(p_to_string );


while(* p_from_string){


if(strchr(p_source,* p_from_string)!= NULL){

if(x_sub< l_len)

chrsubst(p_source,* p_from_string,p_to_string [x_sub]);

else {

char l_ch [] ="" ;;

l_ch [0] = * p_from_string;

str_rmchars(p_source,l_ch);

}

}


x_sub ++;

p_from_string ++;


}


返回p_source;

}

I''ve been away from C programming since 1999 and I''ve recently taken it
up again. Below is a string function I wrote this morning that will be
going into my home-grown library of string functions. I brought the
idea of it from a function of the same name in PL/SQL. I thought it
would be handy in my C library. Mine differs in that the source string
argument is modified and returned from the function.

Working with C strings has always been problematic because you can crash
a program faster than you can say "Jack''s you''re uncle!" if you are not
careful. Some of my string functions I take the strcpy() approach and
copy in the modified string into a destination pointer that you can only
hope is pointing to something big enough and in your program''s data
space. With others I modify the source string in place and return a
pointer to it. With this function I felt it safe to modify the string
in place because at worst one character would be changed to another and
at best the character would be removed from the source string, so there
is no chance of overflowing the buffer. Of course, someone will try to
use a string constant for the sorce string (i.e. "This is a string").
I thought I would post the code and see what the experts had to say. For
reference "strtools.h" is my header file for my homegrown string
functions, and chrsubst() is used to substitute characters in a string,
and str_rmchars() removes a set of characters from a string.

/**FUNCTION**************************************** ********************/
/* Name: */
/* translate(). */
/* */
/* Synopsis: */
/* #include <strings.h> */
/* #include "strtools.h" */
/* char *translate(char *src, char *fromstr, char *tostr); */
/* */
/* Description: */
/* The translate function will translate characters that appear */
/* in both the src and fromstr strings. If the fromstr character */
/* has a corresponding value in the tostr string all characters */
/* in the src string will be translated to that of the */
/* corresponding tostr character. If there is no corresponding */
/* character in the tostr string the character will be removed */
/* from the source string. */
/* */
/* Arguments: */
/* char *source - The string to be examined and translated. */
/* char *fromstr- The characters to translate in the source. */
/* char *tostr - The corresponding characters the source */
/* characters are translated to. */
/* */
/* Return Value: */
/* The starting address of the source string. */
/* */
/************************************************** **********FUNCTION**/

char *
translate ( char *p_source, char *p_from_string, char *p_to_string )
{
unsigned x_sub = 0, l_len = strlen( p_to_string );

while ( *p_from_string ) {

if ( strchr( p_source, *p_from_string ) != NULL ) {
if ( x_sub < l_len )
chrsubst( p_source, *p_from_string, p_to_string[x_sub] );
else {
char l_ch[] = "";
l_ch[0] = *p_from_string;
str_rmchars( p_source, l_ch );
}
}

x_sub++;
p_from_string++;

}

return p_source;
}

推荐答案

Stan Milam< st **** *@swbell.net>写道:
Stan Milam <st*****@swbell.net> wrote:
我自1999年以来一直远离C编程,我最近又把它取回了
。下面是我今天早上写的字符串函数,它将进入我自己开发的字符串函数库。我从PL / SQL中的同名函数中提出了它的概念。我认为它在我的C库中会很方便。我的不同之处在于源字符串
参数被修改并从函数返回。
使用C字符串一直存在问题,因为你可以比你说杰克你是叔叔更快地崩溃一个程序!如果你不小心。我的一些字符串函数我采用strcpy()方法并将修改后的字符串复制到目标指针中,你只能希望它指向一个足够大的东西并且在程序的数据中<空间。和其他人一起修改源字符串并返回一个
指针。有了这个功能,我觉得修改字符串
是安全的,因为最坏的情况是一个字符会被改为另一个字符,并且最好将字符从源字符串中删除,所以有
没有机会溢出缓冲区。当然,有人会尝试为字符串使用字符串常量(即这是一个字符串)。
我想我会发布代码并看看专家们要说些什么。对于
参考strtools.h是我自己开发的字符串
函数的头文件,chrsubst()用于替换字符串中的字符,
和str_rmchars()从字符串中删除一组字符。
/ **功能**************************************** ** ****************** /
/ *姓名:* /
/ * translate()。 * /
/ * * /
/ *剧情简介:* /
/ * #include< strings.h> * /
/ * #include" strtools.h" * /
/ * char * translate(char * src,char * fromstr,char * tostr); * /
/ * * /
/ *说明:* /
/ *翻译功能将翻译src和fromstr字符串中出现* /
/ *的字符。如果fromstr字符* /
/ *在tostr字符串中有相应的值,则src字符串中的所有字符* /
/ *将被转换为* /
/ *对应的字符tostr字符。如果tostr字符串中没有相应的* /
/ *字符,则字符将从源字符串中删除* /
/ *。 * /
/ * * /
/ *参数:* /
/ * char * source - 要检查和翻译的字符串。 * /
/ * char * fromstr-要在源中翻译的字符。 * /
/ * char * tostr - 源* /
/ *字符转换为的相应字符。 * /
/ * * /
/ *返回值:* /
/ *源字符串的起始地址。 * /
/ * * /
/ *********************************** *************** ********** FUNCTION ** /
char *
translate(char * p_source,char * p_from_string,char * p_to_string)
{
unsigned x_sub = 0,l_len = strlen(p_to_string);


由于strlen()返回一个size_t类型,我认为保持'x_sub'和'的类型是谨慎的。 'l_len''。

while(* p_from_string){
if(strchr(p_source,* p_from_string)!= NULL){
if(x_sub< l_len)
chrsubst(p_source,* p_from_string,p_to_string [x_sub]);
else {
char l_ch [] ="" ;;


在这里你创建一个包含1个元素的数组。

l_ch [0] = * p_from_string;


现在''l_ch''不再是字符串了(最后''\ 0''缺失了)但是

只是一个数组( with on char)

str_rmchars(p_source,l_ch);


因为你传递一个数组作为第二个参数,但你不能确定被调用函数中的
多长时间(你既没有超过长度也没有

有你传给它的最后一个''\ 0'')这闻起来非常可疑,至少如果我假设你不会b
当函数只对单个字符进行操作时,传递一组字符



}
}
x_sub ++;
p_from_string ++;
}
返回p_source;
}
I''ve been away from C programming since 1999 and I''ve recently taken it
up again. Below is a string function I wrote this morning that will be
going into my home-grown library of string functions. I brought the
idea of it from a function of the same name in PL/SQL. I thought it
would be handy in my C library. Mine differs in that the source string
argument is modified and returned from the function. Working with C strings has always been problematic because you can crash
a program faster than you can say "Jack''s you''re uncle!" if you are not
careful. Some of my string functions I take the strcpy() approach and
copy in the modified string into a destination pointer that you can only
hope is pointing to something big enough and in your program''s data
space. With others I modify the source string in place and return a
pointer to it. With this function I felt it safe to modify the string
in place because at worst one character would be changed to another and
at best the character would be removed from the source string, so there
is no chance of overflowing the buffer. Of course, someone will try to
use a string constant for the sorce string (i.e. "This is a string").
I thought I would post the code and see what the experts had to say. For
reference "strtools.h" is my header file for my homegrown string
functions, and chrsubst() is used to substitute characters in a string,
and str_rmchars() removes a set of characters from a string. /**FUNCTION**************************************** ********************/
/* Name: */
/* translate(). */
/* */
/* Synopsis: */
/* #include <strings.h> */
/* #include "strtools.h" */
/* char *translate(char *src, char *fromstr, char *tostr); */
/* */
/* Description: */
/* The translate function will translate characters that appear */
/* in both the src and fromstr strings. If the fromstr character */
/* has a corresponding value in the tostr string all characters */
/* in the src string will be translated to that of the */
/* corresponding tostr character. If there is no corresponding */
/* character in the tostr string the character will be removed */
/* from the source string. */
/* */
/* Arguments: */
/* char *source - The string to be examined and translated. */
/* char *fromstr- The characters to translate in the source. */
/* char *tostr - The corresponding characters the source */
/* characters are translated to. */
/* */
/* Return Value: */
/* The starting address of the source string. */
/* */
/************************************************** **********FUNCTION**/ char *
translate ( char *p_source, char *p_from_string, char *p_to_string )
{
unsigned x_sub = 0, l_len = strlen( p_to_string );
Since strlen() returns a size_t type I would think that it''s
prudent to keep that type for both ''x_sub'' and ''l_len''.
while ( *p_from_string ) { if ( strchr( p_source, *p_from_string ) != NULL ) {
if ( x_sub < l_len )
chrsubst( p_source, *p_from_string, p_to_string[x_sub] );
else {
char l_ch[] = "";
Here you create an array with 1 element.
l_ch[0] = *p_from_string;
Now ''l_ch'' isn''t a string anymore (the final ''\0'' is missing) but
just an array (with on char)
str_rmchars( p_source, l_ch );
Since you pass an array as the second argument but you can''t determine
in the called function how long it is (you neither pass the length nor
has what you pass to it a final ''\0'') this smells extremely fishy, at
least if I assume correctly that you wouldn''t pass it an array of chars
when the function only operates on a single char.
} } x_sub++;
p_from_string++; } return p_source;
}




关于效率的一些评论:


a)当''x_sub''相等时你可以立即停止你的主循环

到l_len'' - 在这种情况下,所有左边都是用什么来调用str_rmchar

' 'p_from_string''然后指向(你必须测试chars

是否在函数中的''p_source''才能找到它们,

so在callin

函数中也没有太多意义。


b)因为你还需要在chrsubstr()中找到它你需要替换的功能是你自动测试它是否存在,所以

也为此你不需要strstr()打电话给来电者。 Act $

ally,chrsubst()可能就是那么简单,你可以避免

fucntion呼叫开销。


所以我想你可以将整个功能减少到(未经测试!)


char *

translate(char * p_source,char * p_from_string,char * p_to_string)

{

size_t x_sub = 0,

from_len = strlen(p_from_string),

to_len = strlen(p_to_string) ;


if(from_len> to_len)

{

str_rmchars(p_source,p_from_string + to_len);

from_len = to_len;

}


for(; x_sub< from_len; x_sub ++,p_from_string ++)

{

char * where = p_source;

while((where = strchr(where,* p_from_string))!= NULL)

*其中++ = p_to_string [x_sub];

}


返回p_source;

}


再次假设str_rmchar()删除了通过

传递的所有字符cond argument。

问候,Jens

-

\ Jens Thoms Toerring ___ Je *********** @ physik.fu-berlin.de

\\ \\ __________________________ http://www.toerring.de




2005年3月4日星期五,Stan Milam写道:

On Fri, 4 Mar 2005, Stan Milam wrote:

我从1999年开始离开C编程最近又把它拿了起来。下面是我今天早上写的一个字符串函数,它将进入我自己开发的字符串函数库。我从PL / SQL中的同名函数中提出了它的想法。


这是一个C组,而不是一个Oracle组,不应该期望

读者知道PL / SQL库。我去追踪它了。 PL / SQL中的''TRANSLATE''函数基本上与* nix中的''tr''

命令的默认情况相同:给定一个来自的列表字符和

匹配的to列表字符,替换每个from [i]用to [i]在

给定的字符串。

使用C字符串一直存在问题,因为你可以比你说杰克更快地崩溃一个
程序你是叔叔!如果你不小心。


足够真实。

我以为我会发布代码,看看专家们要说些什么。对于
参考strtools.h是我自己开发的字符串函数的头文件,
和chrsubst()用于替换字符串中的字符,
str_rmchars()从字符串中删除一组字符。


这不是很具描述性。而且,我认为你的侵略性是模块化。最终会损害清晰度和性能---并且

不仅仅是因为奇怪的函数名称!


(上面和下面的批评都是针对的最好的精神,

当然。我希望它对你有用。现在,解剖!)


/ **功能* *********************************** *********** ********* /
/ *姓名:* /
/ * translate()。 * /


说真的,如果读者不能从代码中说出这么多,那么你是不是想要他阅读它?整个评论块太多了

详细;它几乎比功能更长,并且它/将会比我用它完成后的功能更长一些!

/ * * /
/ *剧情简介:* /
/ * #include< strings.h> * /


您从未解释过上述标题是什么。这可能是一个错字吗?

为什么读者会关心这个函数的依赖关系?这是实现者的工作 - 确保源文件定义

这个函数#includes< strings.h> (或者< string.h>)在顶部。有没有理由在这里重复任何这些东西。

/ * #include" strtools.h" * /
/ * char * translate(char * src,char * fromstr,char * tostr); * /


这是双重奇怪的:首先,因为读者应该能够自己阅读原型而不会看到它两次;第二,因为

上面的原型使用完全不同的变量名来自你在源代码中实际使用的

。他们应该匹配;没有

他们不应该这样做。

/ * * /
/ *描述:* /
/ *翻译函数将在src和fromstr字符串中翻译出现* /
/ *的字符。如果fromstr字符* /
/ *在tostr字符串中有相应的值,则src字符串中的所有字符* /
/ *将被转换为* /
/ *对应的字符tostr字符。如果tostr字符串中没有相应的* /
/ *字符,则字符将从源字符串中删除* /
/ *。 * /


这既密集又模糊。在我阅读SQL / PL手册中的相应页面之前,我不明白它是什么尝试

。当然

有一个更好的方式来描述这个程序! (事实上​​,你的b $ b b问题的一部分是读者不能立即从源代码中告诉我们:b
。一旦我们澄清代码,该算法将显而易见,因此需要较少的散文解释。)

/ *参数:* /
/ * char * source - 字符串被检查和翻译。 * /
/ * char * fromstr-要在源中翻译的字符。 * /
/ * char * tostr - 源* /
/ *字符转换为的相应字符。 * /
/ * * /
/ *返回值:* /
/ *源字符串的起始地址。 * /
/ * * /
/ *********************************** *************** **********功能** /

char *
翻译(char * p_source,char * p_from_string,char * p_to_string)


匈牙利表示法。做错了。从什么时候开始p代表

" string"?这三个参数都不是指针。任何数据

抽象意义上的类型;他们都是弦乐。如果您打算使用任何匈牙利语前缀,那么您将使用s:''s_source'','s_from'',

和等等。 (''s_from_string''将是一个愚蠢的名字,因为我相信你可以

看。)

删除混淆符号。

{
unsigned x_sub = 0,l_len = strlen(p_to_string);

while(* p_from_string){


(我不同意你的意见)也是空白风格,但那是个人的b / b $ b b宗教问题。我之所以提到它只是因为我将使用自己的风格

以后,所以如果你想要查看我建议的样式,你现在应该向下滚动

。)

if(strchr(p_source,* p_from_string)!= NULL){
if(
chrsubst(p_source,* p_from_string,p_to_string [x_sub]);


我不知道这是做什么的,但我打赌它会扫描

整个字符串''p_source'',替换''的每个实例'' * p_from_string''

with''p_to_string [x_sub]''。你这样做''l_len''。这是一个很多原因的循环。我已经提到了可怜的

命名方案:''chrsubst''!?

else {
char l_ch [] ="" ;


这相当于

char l_ch [1] = {0};

以下两行让我相信也许这是另一个

错字,你的意思是''char l_ch [2]''。否则,为什么还要为单个字符制作

a副本?

l_ch [0] = * p_from_string;
str_rmchars(p_source,l_ch);
}

x_sub ++;
p_from_string ++;


任何时候你看到一个循环,在C中,以一个增量或一个
指针追逐赋值结束,它应该发出警告标志

有些东西没有被认为是正确的。在这里,它表明

你错过了''for''循环。见下文。

}

返回p_source;
}



这就是代码。现在这是我的整体分析。

你以一个增量结束''while''循环。这是''for''

循环的标志,正在努力摆脱。所以我们重写循环:


[...] unsigned x_sub;

for(x_sub = 0; * p_from_string; ++ x_sub,++ p_from_string ){
if(strchr(p_source,* p_from_string)!= NULL){
[...]}
}
[...]


接下来我注意到的是现在我们在increment子句中有一个'for for'循环,其中有两个增量
。这是我们依赖

循环变量需要重构的标志 - 事实上,我们确实使用

''x_sub''作为循环计数器,并且只是递增''p_from_string''以保持

它指向该数组的''x_sub''元素。所以我们合并了两个

因变量;产生

char * translate(char * p_source,char * p_from_string,char * p_to_string)
{
unsigned l_len = strlen(p_to_string);
unsigned x_sub;

for(x_sub = 0; p_from_string [x_sub]; ++ x_sub){
if(strchr(p_source,p_from_string [x_sub])!= NULL){
if(
chrsubst(p_source,p_from_string [x_sub],p_to_string [x_sub]);
else {
char l_ch [1];
l_ch [0] = p_from_string [x_sub];
str_rmchars(p_source,l_ch);
}
}

返回p_source;
}

I''ve been away from C programming since 1999 and I''ve recently taken it up
again. Below is a string function I wrote this morning that will be going
into my home-grown library of string functions. I brought the idea of it
from a function of the same name in PL/SQL.
This being a C group, and not an Oracle group, one shouldn''t expect the
readers to know the PL/SQL library. I went and tracked it down. It turns
out that the ''TRANSLATE'' function in PL/SQL does basically what the ''tr''
command in *nix does by default: given a list of "from" characters and a
matching list of "to" characters, replace each "from[i]" with "to[i]" in
the given string.
Working with C strings has always been problematic because you can crash a
program faster than you can say "Jack''s you''re uncle!" if you are not
careful.
True enough.
I thought I would post the code and see what the experts had to say. For
reference "strtools.h" is my header file for my homegrown string functions,
and chrsubst() is used to substitute characters in a string, and
str_rmchars() removes a set of characters from a string.
That''s not very descriptive. Moreover, I think your aggressive
"modularization" ends up hurting both clarity and performance --- and
not just because of the weird function names!

(All criticism above and below is intended in the best of spirits, of
course. I hope it''s useful to you. Now, on with the dissection!)

/**FUNCTION**************************************** ********************/
/* Name: */
/* translate(). */
Seriously, if the reader can''t tell this much from the code, do you
/really/ want him reading it? This entire comment block is much too
verbose; it''s almost longer than the function, and it /will/ be longer
than the function once I get through with it!
/* */
/* Synopsis: */
/* #include <strings.h> */
You never explained what the above header is. Is it a typo, perhaps?
And why should the reader care what dependencies this function has? That''s
the implementor''s job --- to make sure that the source file that defines
this function #includes <strings.h> (or <string.h>) at the top. There''s
no reason to repeat any of this stuff here.
/* #include "strtools.h" */
/* char *translate(char *src, char *fromstr, char *tostr); */
This is doubly weird: first, because again the reader ought to be able
to read a prototype himself without seeing it twice; and second, because
the prototype above uses completely different variable names from the
one you actually use in the source code. They should match; there''s no
reason they shouldn''t.
/* */
/* Description: */
/* The translate function will translate characters that appear */
/* in both the src and fromstr strings. If the fromstr character */
/* has a corresponding value in the tostr string all characters */
/* in the src string will be translated to that of the */
/* corresponding tostr character. If there is no corresponding */
/* character in the tostr string the character will be removed */
/* from the source string. */
This is both dense and vague. I didn''t understand what it was trying
to say until I read the appropriate page in the SQL/PL manual. Surely
there''s a better way to describe the procedure! (In fact, part of your
problem is that the reader can''t immediately tell from the source code
what''s going on. Once we clarify the code, the algorithm will be
obvious, and thus will need less prose explanation.)
/* Arguments: */
/* char *source - The string to be examined and translated. */
/* char *fromstr- The characters to translate in the source. */
/* char *tostr - The corresponding characters the source */
/* characters are translated to. */
/* */
/* Return Value: */
/* The starting address of the source string. */
/* */
/************************************************** **********FUNCTION**/

char *
translate ( char *p_source, char *p_from_string, char *p_to_string )
Hungarian notation. And done wrong. Since when does "p" stand for
"string"? None of those three parameters is a "pointer" to any data
type in the abstract sense; they''re all strings. If you were going to
use any Hungarian prefix, you''d be using "s": ''s_source'', ''s_from'',
and so on. (''s_from_string'' would be a stupid name, as I''m sure you can
see.)
Drop the obfuscatory notation.
{
unsigned x_sub = 0, l_len = strlen( p_to_string );

while ( *p_from_string ) {
(I disagree with your whitespace style, too, but that''s a personal
religious issue. I mention it only because I''ll be using my own style
later on, so if you want to see my suggested style, you should scroll
down now.)
if ( strchr( p_source, *p_from_string ) != NULL ) {
if ( x_sub < l_len )
chrsubst( p_source, *p_from_string, p_to_string[x_sub] );
I have no idea what this is doing, but I bet it scans through the
entire string ''p_source'', replacing each instance of ''*p_from_string''
with ''p_to_string[x_sub]''. And you do this ''l_len'' times. That''s a
lot of looping for little reason. And I''ve already mentioned the poor
naming scheme: ''chrsubst''!?
else {
char l_ch[] = "";
This is equivalent to
char l_ch[1] = {0};
The following two lines lead me to believe that perhaps this is another
typo, that you meant ''char l_ch[2]'' instead. Otherwise, why bother making
a copy of a single character?
l_ch[0] = *p_from_string;
str_rmchars( p_source, l_ch );
}
}

x_sub++;
p_from_string++;
Any time you see a loop, in C, which ends with an increment or a
pointer-chasing assignment, that should send up warning flags that
something hasn''t been thought out properly. Here, it indicates that
you''re missing a ''for'' loop. See below.
}

return p_source;
}

So that was the code. Now here''s my overall analysis.
You end a ''while'' loop with an increment. That''s the sign of a ''for''
loop struggling to get out. So we rewrite the loop:

[...] unsigned x_sub;

for (x_sub=0; *p_from_string; ++x_sub, ++p_from_string) {
if ( strchr( p_source, *p_from_string ) != NULL ) { [...] }
} [...]

The next thing I noticed was that now we have a ''for'' loop with two
increments in the increment clause. That''s a sign that we have dependent
loop variables that need refactoring --- and indeed, we are really using
''x_sub'' as a loop counter, and merely incrementing ''p_from_string'' to keep
it pointing at the ''x_sub''th element of that array. So we merge the two
dependent variables; that yields
char *translate(char *p_source, char *p_from_string, char *p_to_string)
{
unsigned l_len = strlen( p_to_string );
unsigned x_sub;

for (x_sub=0; p_from_string[x_sub]; ++x_sub) {
if (strchr(p_source, p_from_string[x_sub]) != NULL) {
if ( x_sub < l_len )
chrsubst(p_source, p_from_string[x_sub], p_to_string[x_sub]);
else {
char l_ch[1];
l_ch[0] = p_from_string[x_sub];
str_rmchars(p_source, l_ch);
}
}
}

return p_source;
}




突然,chrsubst调用中的并行结构脱颖而出!

我们已经对算法的一个关键部分进行了去混淆:我们现在显然

看到''p_from_string''中的字符只与

对应的字符相匹配'p_to_string''。


接下来,我更喜欢通过更改

第一个巨大的''如果'到条件''来删除一个级别的缩进继续'';与此同时,为了节省更多空间,我将转而采用更为理智的命名惯例。

这两个仅输入参数是正确的const限定的。这会产生

我认为是干净的您编写的程序版本:


/ *

翻译出现在| from |中的字符字符串到他们的

| to |中的相应字符串。如果|到|比|来自|来​​自|,|来自|,|来自|的比较短。

字符从| src |中删除。

覆盖| src |使用输出字符串,并返回新的| src |。

* /

char * translate(char * src,const char * from,const char * to)

{

size_t len_to = strlen(to);

size_t i;


for(i = 0;来自[i]!=''\'''; ++ i)

{

if(strchr(src,from [i])= = NULL)

继续;

if(i< len_to){

chrsubst(src,从[i]到[i] );

}

else {

char ch [1]; / *应该是char ch [2] = {0}; * /

ch [0] =来自[i];

str_rmchars(src,ch);

}

}


返回src;

}


但我们还没有完成!记住,我想摆脱那些奇怪的

库例程调用有两个原因:第一,为了清晰,第二,

的效率。没有理由通过

输入字符串扫描这么多次!更重要的是,我们可以通过简单来更好地阐明算法

。像这样的代码:


char * translate(char * src,const char * from,const char * to)

{

size_t in,out;

size_t len_to = strlen(to);

for(in = out = 0; src [in]!=''\ 0' '; ++ in)

{

/ *是| |中的当前字符阵列? * /

const char * t = strchr(from,src [in]);

/ * No;只需将它回显到输出字符串* /

if(t == NULL)

src [out ++] = src [in];

/ *是的;如果| to |匹配,则回显该条目。 * /

else if(t - from< len_to)

src [out ++] = to [t - from];

}


src [out] =''\ 0'';

返回src;

}

这个例程的一个版本使用''strpbrk''库函数

可能会很有趣,但是,尽管我怀疑它会是更清洁或更快的任何




无论如何,我希望你能得到这个想法---干净而简单。任何其他策略,任何一天都可以打得很好。我强烈推荐

编程风格的元素。 (Kernighan& Plauger)给任何想要学习的东西。

写(或批评!)源代码。


HTH,

-Arthur



Suddenly the parallel structure in the call to ''chrsubst'' stands out!
We have de-obfuscated a critical part of the algorithm: We now clearly
see that characters from ''p_from_string'' are matched only with the
corresponding characters from ''p_to_string''.

Next, I prefer to remove one level of indentation by changing that
first gigantic ''if'' to a conditional ''continue''; at the same time, to
conserve even more space, I''ll switch to a saner naming convention.
The two input-only parameters are properly const-qualified. This yields
what I consider the "clean" version of the procedure you wrote:

/*
Translates characters that appear in the |from| string to their
corresponding characters in the |to| string. If |to| is shorter
than |from|, the unmatched |from| characters are deleted from |src|.
Overwrites |src| with the output string, and returns the new |src|.
*/
char *translate(char *src, const char *from, const char *to)
{
size_t len_to = strlen(to);
size_t i;

for (i=0; from[i] != ''\0''; ++i)
{
if (strchr(src, from[i]) == NULL)
continue;
if (i < len_to) {
chrsubst(src, from[i], to[i]);
}
else {
char ch[1]; /* Should probably be char ch[2] = {0}; */
ch[0] = from[i];
str_rmchars(src, ch);
}
}

return src;
}

But we''re not done! Remember, I wanted to get rid of those weird
library-routine calls for two reasons: first, for clarity, and second,
for efficiency. There''s no reason to be scanning so many times through
the input string! What''s more, we can really elucidate the algorithm
much better with "simple" code like this:

char *translate(char *src, const char *from, const char *to)
{
size_t in, out;
size_t len_to = strlen(to);
for (in=out=0; src[in] != ''\0''; ++in)
{
/* Is the current character in the |from| array? */
const char *t = strchr(from, src[in]);
/* No; just echo it to the output string */
if (t == NULL)
src[out++] = src[in];
/* Yes; if it has a match in |to|, then echo that entry. */
else if (t - from < len_to)
src[out++] = to[t - from];
}

src[out] = ''\0'';
return src;
}
A version of this routine using the ''strpbrk'' library function
might be interesting to see, also, though I doubt it would be any
cleaner or quicker.

Anyway, I hope you get the idea --- "clean and simple" beats pretty
much any other strategy, any day. I highly recommend "The Elements of
Programming Style" (Kernighan & Plauger) to anyone who wants to learn
to write (or critique!) source code.

HTH,
-Arthur


Arthur J. O''Dwyer写道:
Arthur J. O''Dwyer wrote:

2005年3月4日星期五,Stan Milam写道:

这是一个C组,而不是Oracle组,不应该期望读者知道PL / SQL库。我去追踪它了。它转向了PL / SQL中的''TRANSLATE''函数基本上完成了* nix中默认的''tr''命令:给出一个from列表字符和
匹配列表to字符,替换每个from [i]用to [i]在给定的字符串中。


我在UNIX职业生涯中使用''tr''命令很少,但我发现PL / SQL翻译功能非常方便。

。我认为现在我用C语言实现一个是很有趣的,因为我再次用它来写(和/ b $ b PL / SQL一起)。几乎所有或多或少的标准C函数都是为了解决某些问题而设想的。他们中的很多人都有搞笑的名字

。但谁可以击败IEBR14(我认为这就是所谓的)和来自IBM大型机世界的IEBGENR?

On Fri, 4 Mar 2005, Stan Milam wrote:

This being a C group, and not an Oracle group, one shouldn''t expect the
readers to know the PL/SQL library. I went and tracked it down. It turns
out that the ''TRANSLATE'' function in PL/SQL does basically what the ''tr''
command in *nix does by default: given a list of "from" characters and a
matching list of "to" characters, replace each "from[i]" with "to[i]" in
the given string.
I have used the ''tr'' command very little in my UNIX career, but I found
the PL/SQL translate function very handy. I thought it would be fun to
implement one in C now that I am writing with it again (along with
PL/SQL). Pretty much all the more-or-less standard C functions were
conceived to solve some problem. And a lot of them have funny names
too. But who could beat IEBR14 (I think that is what it was called) and
IEBGENR from the IBM mainframe world?
我想我会发布代码,看看专家们要说些什么。
供参考strtools.h是我自己开发的字符串
函数的头文件,chrsubst()用于替换字符串中的字符,str_rmchars()从字符串中删除一组字符。
I thought I would post the code and see what the experts had to say.
For reference "strtools.h" is my header file for my homegrown string
functions, and chrsubst() is used to substitute characters in a
string, and str_rmchars() removes a set of characters from a string.



这不是很具描述性。而且,我认为你的侵略性模块化最终会损害清晰度和性能---而且不仅仅是因为奇怪的函数名称!


That''s not very descriptive. Moreover, I think your aggressive
"modularization" ends up hurting both clarity and performance --- and
not just because of the weird function names!




嗯,我认为它比什么更好很多次由其他

海报提供,这没什么。

(上面和下面的所有批评都是出于最好的精神,当然。我希望它对你有用。现在,解剖!)


好​​吧,公平。



Well, I thought it much better than what is many times provided by other
posters, which is nothing.

(All criticism above and below is intended in the best of spirits, of
course. I hope it''s useful to you. Now, on with the dissection!)

OK, fair enough.

/ **功能**************************************** *** ***************** /
/ *姓名:* /
/ * translate()。 * /
/**FUNCTION**************************************** ********************/
/* Name: */
/* translate(). */



说真的,如果读者不能从代码中说出这么多内容,那么你/他/真的/想要他阅读吗?这个整个评论块太冗长了;它比功能更长,而且/它/将比我使用它的功能更长!


Seriously, if the reader can''t tell this much from the code, do you
/really/ want him reading it? This entire comment block is much too
verbose; it''s almost longer than the function, and it /will/ be longer
than the function once I get through with it!




有一个我疯狂的方法。我在编写

函数时编写文档。这几乎就是文档。我使用shell

脚本来提取这些注释块并重新格式化以进行打印。



There is a method to my madness. I write the documentation when I write
the function. This is pretty much the documentation. I use a shell
script to extract these comment blocks an reformat them for printing.

/ * * /
/ *概要:* /
/ * #include< strings.h> * /

您从未解释过上述标题是什么。这可能是一个错字吗?
为什么读者应该关心这个函数的依赖关系?那是'实现者'的工作---确保定义
这个函数的源文件#includes< strings.h> (或者< string.h>)在顶部。有没有理由在这里重复这些东西。
/* */
/* Synopsis: */
/* #include <strings.h> */

You never explained what the above header is. Is it a typo, perhaps?
And why should the reader care what dependencies this function has? That''s
the implementor''s job --- to make sure that the source file that defines
this function #includes <strings.h> (or <string.h>) at the top. There''s
no reason to repeat any of this stuff here.




是的,我发了肥。它应该是< string.h>。再次,这变为

函数描述的书面文档。



Yep, I fat fingered it. It should be <string.h>. Again, this becomes
the written document for the function description.

/ * #include" strtools.h" * /
/ * char * translate(char * src,char * fromstr,char * tostr); * /

这非常奇怪:首先,因为读者应该能够自己阅读原型而不会看到它两次;第二,因为上面的原型使用了与源代码中实际使用的变量名完全不同的变量名。他们应该匹配;没有原因他们不应该这样做。
/* #include "strtools.h" */
/* char *translate(char *src, char *fromstr, char *tostr); */

This is doubly weird: first, because again the reader ought to be able
to read a prototype himself without seeing it twice; and second, because
the prototype above uses completely different variable names from the
one you actually use in the source code. They should match; there''s no
reason they shouldn''t.




这不是用户文档中的内容。他们不需要知道我在内部叫什么b $ b。




No this is what is in the user docs. They do not need to know what I
called them internally.


/ * * /
/ *说明:* /
/ * translate函数将翻译src和fromstr字符串中出现* /
/ *的字符。如果fromstr字符* /
/ *在tostr字符串中有相应的值,则src字符串中的所有字符* /
/ *将被转换为* /
/ *对应的字符tostr字符。如果tostr字符串中没有相应的* /
/ *字符,则字符将从源字符串中删除* /
/ *。 * /

这既密集又含糊。在我阅读SQL / PL手册中的相应页面之前,我不明白它在尝试说什么。当然
有一种更好的方式来描述这个程序! (事实上​​,你的部分问题是读者无法立即从源代码中了解到发生了什么。一旦我们澄清了代码,算法就会
显而易见,因此需要较少的散文解释。)
/* */
/* Description: */
/* The translate function will translate characters that appear */
/* in both the src and fromstr strings. If the fromstr character */
/* has a corresponding value in the tostr string all characters */
/* in the src string will be translated to that of the */
/* corresponding tostr character. If there is no corresponding */
/* character in the tostr string the character will be removed */
/* from the source string. */

This is both dense and vague. I didn''t understand what it was trying
to say until I read the appropriate page in the SQL/PL manual. Surely
there''s a better way to describe the procedure! (In fact, part of your
problem is that the reader can''t immediately tell from the source code
what''s going on. Once we clarify the code, the algorithm will be
obvious, and thus will need less prose explanation.)




谢谢。我会改写它。我一直在阅读太多的IBM文档!



Thanks. I''ll rewrite it. I''ve been reading too much IBM documentation!

/ *参数:* /
/ * char * source - 要检查和翻译的字符串。 * /
/ * char * fromstr-要在源中翻译的字符。 * /
/ * char * tostr - 源* /
/ *字符转换为的相应字符。 * /
/ * * /
/ *返回值:* /
/ *源字符串的起始地址。 */
/* */
/************************************************** **********FUNCTION**/

char *
translate ( char *p_source, char *p_from_string, char *p_to_string )

Hungarian notation. And done wrong. Since when does "p" stand for
"string"? None of those three parameters is a "pointer" to any data
type in the abstract sense; they’’re all strings. If you were going to
use any Hungarian prefix, you’’d be using "s": ’’s_source’’, ’’s_from’’,
and so on. (’’s_from_string’’ would be a stupid name, as I’’m sure you can
see.)
Drop the obfuscatory notation.
/* Arguments: */
/* char *source - The string to be examined and translated. */
/* char *fromstr- The characters to translate in the source. */
/* char *tostr - The corresponding characters the source */
/* characters are translated to. */
/* */
/* Return Value: */
/* The starting address of the source string. */
/* */
/************************************************** **********FUNCTION**/

char *
translate ( char *p_source, char *p_from_string, char *p_to_string )

Hungarian notation. And done wrong. Since when does "p" stand for
"string"? None of those three parameters is a "pointer" to any data
type in the abstract sense; they''re all strings. If you were going to
use any Hungarian prefix, you''d be using "s": ''s_source'', ''s_from'',
and so on. (''s_from_string'' would be a stupid name, as I''m sure you can
see.)
Drop the obfuscatory notation.




Ah, this is a holdover from my PL/SQL days. PL/SQL does not have

pointers so that did not even occur to me. No, it is not Hungarian

notation, it is Milam notation. I’’ve tried Hungarian and I have come to

truly despise it. The p_ prefix simply means it is a PARAMETER

variable, and the l_ prefix means it is a LOCAL variable. I use the

x_sub, y_sub etc... name for subscripts. Just a glance and I know what

I am dealing with.



Ah, this is a holdover from my PL/SQL days. PL/SQL does not have
pointers so that did not even occur to me. No, it is not Hungarian
notation, it is Milam notation. I''ve tried Hungarian and I have come to
truly despise it. The p_ prefix simply means it is a PARAMETER
variable, and the l_ prefix means it is a LOCAL variable. I use the
x_sub, y_sub etc... name for subscripts. Just a glance and I know what
I am dealing with.

{
unsigned x_sub = 0, l_len = strlen( p_to_string );

while ( *p_from_string ) {

(I disagree with your whitespace style, too, but that’’s a personal
religious issue. I mention it only because I’’ll be using my own style
later on, so if you want to see my suggested style, you should scroll
down now.)
{
unsigned x_sub = 0, l_len = strlen( p_to_string );

while ( *p_from_string ) {

(I disagree with your whitespace style, too, but that''s a personal
religious issue. I mention it only because I''ll be using my own style
later on, so if you want to see my suggested style, you should scroll
down now.)




I like mine. It has been a long time evolving. But thanks for the offer.



I like mine. It has been a long time evolving. But thanks for the offer.

if ( strchr( p_source, *p_from_string ) != NULL ) {
if ( x_sub < l_len )
chrsubst( p_source, *p_from_string, p_to_string[x_sub] );

I have no idea what this is doing, but I bet it scans through the
entire string ’’p_source’’, replacing each instance of ’’*p_from_string’’
with ’’p_to_string[x_sub]’’. And you do this ’’l_len’’ times. That’’s a
lot of looping for little reason. And I’’ve already mentioned the poor
naming scheme: ’’chrsubst’’!?
if ( strchr( p_source, *p_from_string ) != NULL ) {
if ( x_sub < l_len )
chrsubst( p_source, *p_from_string, p_to_string[x_sub] );

I have no idea what this is doing, but I bet it scans through the
entire string ''p_source'', replacing each instance of ''*p_from_string''
with ''p_to_string[x_sub]''. And you do this ''l_len'' times. That''s a
lot of looping for little reason. And I''ve already mentioned the poor
naming scheme: ''chrsubst''!?




When I wrote that function I was working with a compiler that only

allowed a length of 8 on external function names. So, that’’s been

awhile and I never changed the name. There are a lot of hold-over names

in software where the operating environment dictated constraints. I’’ll

create an alias name for chrsubst and mark it as deprecated.



When I wrote that function I was working with a compiler that only
allowed a length of 8 on external function names. So, that''s been
awhile and I never changed the name. There are a lot of hold-over names
in software where the operating environment dictated constraints. I''ll
create an alias name for chrsubst and mark it as deprecated.

else {
char l_ch[] = "";

This is equivalent to
char l_ch[1] = {0};
The following two lines lead me to believe that perhaps this is another
typo, that you meant ’’char l_ch[2]’’ instead. Otherwise, why bother making
a copy of a single character?
else {
char l_ch[] = "";

This is equivalent to
char l_ch[1] = {0};
The following two lines lead me to believe that perhaps this is another
typo, that you meant ''char l_ch[2]'' instead. Otherwise, why bother making
a copy of a single character?




Hey, you are right!谢谢! (I slap myself on the head and say "What

were you thinking?")



Hey, you are right! Thanks! (I slap myself on the head and say "What
were you thinking?")

l_ch[0] = *p_from_string;
str_rmchars( p_source, l_ch );
}
}

x_sub++;
p_from_string++;

Any time you see a loop, in C, which ends with an increment or a
pointer-chasing assignment, that should send up warning flags that
something hasn’’t been thought out properly. Here, it indicates that
you’’re missing a ’’for’’ loop. See below.
l_ch[0] = *p_from_string;
str_rmchars( p_source, l_ch );
}
}

x_sub++;
p_from_string++;

Any time you see a loop, in C, which ends with an increment or a
pointer-chasing assignment, that should send up warning flags that
something hasn''t been thought out properly. Here, it indicates that
you''re missing a ''for'' loop. See below.




Why should there be warning flags? Has the while keyword fallen into

disfavor? I see no advantage of one over the other. It is a matter of

preference.



Why should there be warning flags? Has the while keyword fallen into
disfavor? I see no advantage of one over the other. It is a matter of
preference.

}

return p_source;
}

So that was the code. Now here’’s my overall analysis.
You end a ’’while’’ loop with an increment. That’’s the sign of a ’’for’’
loop struggling to get out. So we rewrite the loop:

[...]
}

return p_source;
}
So that was the code. Now here''s my overall analysis.
You end a ''while'' loop with an increment. That''s the sign of a ''for''
loop struggling to get out. So we rewrite the loop:

[...]
unsigned x_sub;

for (x_sub=0; *p_from_string; ++x_sub, ++p_from_string) {
if ( strchr( p_source, *p_from_string ) != NULL ) {
unsigned x_sub;

for (x_sub=0; *p_from_string; ++x_sub, ++p_from_string) {
if ( strchr( p_source, *p_from_string ) != NULL ) {



[...]



[...]




See my comments above. This is like saying we should all write at the

same level, use the style. C is a language and it allows enough

latitude to express ourselves - however we feel on a given day.



See my comments above. This is like saying we should all write at the
same level, use the style. C is a language and it allows enough
latitude to express ourselves - however we feel on a given day.

}
}
[...]

The next thing I noticed was that now we have a ’’for’’ loop with two
increments in the increment clause. That’’s a sign that we have dependent
loop variables that need refactoring --- and indeed, we are really using
’’x_sub’’ as a loop counter, and merely incrementing ’’p_from_string’’ to
keep it pointing at the ’’x_sub’’th element of that array. So we merge the
two
dependent variables; that yields
}
}
[...]

The next thing I noticed was that now we have a ''for'' loop with two
increments in the increment clause. That''s a sign that we have dependent
loop variables that need refactoring --- and indeed, we are really using
''x_sub'' as a loop counter, and merely incrementing ''p_from_string'' to
keep it pointing at the ''x_sub''th element of that array. So we merge the
two
dependent variables; that yields
char *translate(char *p_source, char *p_from_string, char *p_to_string)
{
unsigned l_len = strlen( p_to_string );
unsigned x_sub;

for (x_sub=0; p_from_string[x_sub]; ++x_sub) {
if (strchr(p_source, p_from_string[x_sub]) != NULL) {
if ( x_sub < l_len )
chrsubst(p_source, p_from_string[x_sub],
p_to_string[x_sub]);
else {
char l_ch[1];
l_ch[0] = p_from_string[x_sub];
str_rmchars(p_source, l_ch);
}
}
}

return p_source;
}
char *translate(char *p_source, char *p_from_string, char *p_to_string)
{
unsigned l_len = strlen( p_to_string );
unsigned x_sub;

for (x_sub=0; p_from_string[x_sub]; ++x_sub) {
if (strchr(p_source, p_from_string[x_sub]) != NULL) {
if ( x_sub < l_len )
chrsubst(p_source, p_from_string[x_sub],
p_to_string[x_sub]);
else {
char l_ch[1];
l_ch[0] = p_from_string[x_sub];
str_rmchars(p_source, l_ch);
}
}
}

return p_source;
}




Yes that is an improvement.


Suddenly the parallel structure in the call to ’’chrsubst’’ stands out!
We have de-obfuscated a critical part of the algorithm: We now clearly
see that characters from ’’p_from_ string’’ are matched only with the
corresponding characters from ’’p_to_string’’.

Next, I prefer to remove one level of indentation by changing that
first gigantic ’’if’’ to a conditional ’’continue’’; at the same time, to
conserve even more space, I’’ll switch to a saner naming convention.
The two input-only parameters are properly const-qualified. This yields
what I consider the "clean" version of the procedure you wrote:


I’’ll go for that.

/*
Translates characters that appear in the |from| string to their
corresponding characters in the |to|串。 If |to| is shorter
than |from|, the unmatched |from| characters are deleted from |src|.
Overwrites |src| with the output string, and returns the new |src|.
*/
char *translate(char *src, const char *from, const char *to)
{
size_t len_to = strlen(to);
size_t i;

for (i=0; from[i] != ’’\0’’; ++i)
{
if (strchr(src, from[i]) == NULL)
continue;
if (i < len_to) {
chrsubst(src, from[i], to[i]);
}
else {
char ch[1]; /* Should probably be char ch[2] = {0}; */
ch[0] = from[i];
str_rmchars(src, ch);
}
}

return src;
}

But we’’re not done! Remember, I wanted to get rid of those weird
library-routine calls for two reasons: first, for clarity, and second,
for efficiency. There’’s no reason to be scanning so many times through
the input string! What’’s more, we can really elucidate the algorithm
much better with "simple" code like this:

char *translate(char *src, const char *from, const char *to)
{
size_t in, out;
size_t len_to = strlen(to);
for (in=out=0; src[in] != ’’\0’’; ++in)
{
/* Is the current character in the |from|阵列? */
const char *t = strchr(from, src[in]);
/* No; just echo it to the output string */
if (t == NULL)
src[out++] = src[in];
/* Yes; if it has a match in |to|, then echo that entry. */
else if (t - from < len_to)
src[out++] = to[t - from];
}

src[out] = ’’\0’’;
return src;
}

A version of this routine using the ’’strpbrk’’ library function
might be interesting to see, also, though I doubt it would be any
cleaner or quicker.

Anyway, I hope you get the idea --- "clean and simple" beats pretty
much any other strategy, any day. I highly recommend "The Elements of
Programming Style" (Kernighan & Plauger) to anyone who wants to learn
to write (or critique!) source code.

HTH,
-Arthur



Yes that is an improvement.


Suddenly the parallel structure in the call to ''chrsubst'' stands out!
We have de-obfuscated a critical part of the algorithm: We now clearly
see that characters from ''p_from_string'' are matched only with the
corresponding characters from ''p_to_string''.

Next, I prefer to remove one level of indentation by changing that
first gigantic ''if'' to a conditional ''continue''; at the same time, to
conserve even more space, I''ll switch to a saner naming convention.
The two input-only parameters are properly const-qualified. This yields
what I consider the "clean" version of the procedure you wrote:

I''ll go for that.
/*
Translates characters that appear in the |from| string to their
corresponding characters in the |to| string. If |to| is shorter
than |from|, the unmatched |from| characters are deleted from |src|.
Overwrites |src| with the output string, and returns the new |src|.
*/
char *translate(char *src, const char *from, const char *to)
{
size_t len_to = strlen(to);
size_t i;

for (i=0; from[i] != ''\0''; ++i)
{
if (strchr(src, from[i]) == NULL)
continue;
if (i < len_to) {
chrsubst(src, from[i], to[i]);
}
else {
char ch[1]; /* Should probably be char ch[2] = {0}; */
ch[0] = from[i];
str_rmchars(src, ch);
}
}

return src;
}

But we''re not done! Remember, I wanted to get rid of those weird
library-routine calls for two reasons: first, for clarity, and second,
for efficiency. There''s no reason to be scanning so many times through
the input string! What''s more, we can really elucidate the algorithm
much better with "simple" code like this:

char *translate(char *src, const char *from, const char *to)
{
size_t in, out;
size_t len_to = strlen(to);
for (in=out=0; src[in] != ''\0''; ++in)
{
/* Is the current character in the |from| array? */
const char *t = strchr(from, src[in]);
/* No; just echo it to the output string */
if (t == NULL)
src[out++] = src[in];
/* Yes; if it has a match in |to|, then echo that entry. */
else if (t - from < len_to)
src[out++] = to[t - from];
}

src[out] = ''\0'';
return src;
}
A version of this routine using the ''strpbrk'' library function
might be interesting to see, also, though I doubt it would be any
cleaner or quicker.

Anyway, I hope you get the idea --- "clean and simple" beats pretty
much any other strategy, any day. I highly recommend "The Elements of
Programming Style" (Kernighan & Plauger) to anyone who wants to learn
to write (or critique!) source code.

HTH,
-Arthur




Thanks. I have been sitting on the bench for a couple of years. I have

another life besides being a programmer and I decided to live it for a

while. The problem has been my skills are a bit rusty and I’’ve got to

get back "In The Zone."


Regards,

Stan Milam.



Thanks. I have been sitting on the bench for a couple of years. I have
another life besides being a programmer and I decided to live it for a
while. The problem has been my skills are a bit rusty and I''ve got to
get back "In The Zone."

Regards,
Stan Milam.


这篇关于一个讨论的例子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆