K& R 2运动2-3 [英] K&R 2 exercise 2-3

查看:46
本文介绍了K& R 2运动2-3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨〜我自己已经学了几个月了,


如果有人能改进我的编码或纠正它,我会很感激。


以下是我对K& R练习的解决方案2-3


"写一个函数htoi(s),它转换一串十六进制数字

(包括可选的0x或0X)到它的等效整数值。

允许的数字是0到9,a到f和A到f。

// **************************************** ********** ************************


#include< stdio.h>


int isxdigit2(int c)

{

if((c> =''a' '&& c< =''f'')||(c> =''A''&& c< ='''F'')||(c> ='' 0''&& c< ='''9''))

返回1;

其他

返回0; < br $>
}


int tolower2(int c)

{

if (c> =''A''&& c< =''Z'')

返回c + 32;

其他

返回c;

}


int power2(int base,int num)

{

int sum;

for(sum = 1; num> 0; num - )

sum * = base;

返还金额;

}


int char_to_num(int c)

{

if(c> =''0''&& c< =''9'')br / >
{

返回c - 48;

}

其他

{

返回10 +(tolower2(c) - ''a'');

}

}


int htoi(char * c)

{

int i,k,prefix = 0;

size_t sum = 0;


if(c [0] ==''0''&& tolower2(c [1])==''x'')

prefix = 1;


for(i =(prefix == 1)?2:0; c [i]; i ++)

{

if(!isxdigit2(c [i]))

{

printf(错误的六进制数\ n);

返回0;

}

c [i] = char_to_num(c [i]);

}

for(k =(prefix == 1)?2:0; k< = i-1; ++ k)

{

sum + = c [k] * power2(16,i-1-k);

}


返回总和;

}


int main()

{

char c [] =" ; 0xAB" ;;

printf("%u",htoi(c));


返回0;

}


// ************************************ ************** ****************

当我将char c []改为时,
char * c在main(),

它显示错误,为什么?


谢谢..

解决方案

" Herrcho" <他********* @ kornet.net>在消息中写道

新闻:76 ************************* @ posting.google.co m ... < blockquote class =post_quotes>嗨〜我自己研究过C几个月了,


对你有好处。

和我'如果有人能改进我的编码或纠正它,请欣赏它。

以下是我对K& R练习的解决方案2-3


优秀,最后有人谁实际上显示了一些代码! ;-)

注意,我下面的许多评论都是尼特,但是在你需要忘记错误的习惯之前,现在学习好的习惯很好。和我一样。

"写函数htoi(s),它将一串十六进制数字(包括一个可选的0x或0X)转换成它的等效整数值。
允许的数字是0到9,a到f和A到F.


// **************** ********************************** **************** ********
#include< stdio.h>
int isxdigit2(int c)


标识符以'开头' '是''后跟一个小写字母保留

按C标准。使用像is_xdigit2这样的东西。

顺便说一句,已经有一个宏isxdigit了,你需要#include

< ctype.h>

{
if((c> =''''&& c< =''f'')||(c> =''A''&& c < =''F'')||(c> =''0''&& c< =
''9''))


这不保证在非ASCII系统上有效。范围''a'''''''和

''A''..'''''''不需要连续。保证大约''0'''''9'',

虽然。

返回1;
否则
返回0;
}


正确的缩进会使你的代码更容易阅读。

int tolower2(int c)
{
if(c> =''A''&& c< =''Z'')
返回c + 32;
否则
返回c;
}


与上述相同的评论。顺便说一句,以''到''开头的标识符也是保留



int power2(int base,int num)
{和/ ;
for(sum = 1; num> 0; num - )
sum * = base;
返回总和;
}
int char_to_num(int c)
{
if(c> =''0''&& c< ='''9'')
{
返回c - 48;


神奇数字48来自哪里? ITYM返回c - ''0'';

}
其他
{
返回10 +(tolower2(c) - ''a'');


再一次,只有当你确定''''''''''''是一个连续的套装时,这才有效。

}
}

int htoi(char * c)
{i /,int i,k,prefix = 0;
size_t sum = 0;

if(c [0] ==''0''&& tolower2(c [1])==''x'')
prefix = 1;


您确定c中有2个有效字符吗?当你打电话给htoi(7)时会发生什么?

尝试:


if(c [ 0]&& c [0] ==''0''&& c [1]&&(c [1] ==''x''|| c [1] ==' 'X''))

前缀= 1;


它的优点是不那么优雅但更安全。顺便说一下,你可以在没有变量前缀的情况下使用一个算法。它真的很简单,想一想

一点点。你需要的只是跳过c的前两个字符...

for(i =(prefix == 1)?2:0; c [i]; i ++)
{
if(!isxdigit2(c [i]))
{
printf("错误的hexa number \ n);


" Hexa"如在jinxed中? ;-)

返回0;
}
c [i] = char_to_num(c [i]);
}

(k =(前缀== 1)?2:0; k <= i-1; ++ k)
{
sum + = c [k] * power2(16,i-1 -k);


返回总和;

int main()
{
char c [] =" 0xAB";
printf("%u",htoi(c));


呃,不,先生。 printf()中的%u期望unsigned int,但是你提供了

htoi()的结果,返回int。严格来说这是一个未定义的行为,虽然可以肯定我还没有看到一个平台,其中它不起作用。在任何情况下,使用%d代替或改变你的htoi()到

返回unsigned int。

返回0;
}


看起来不错,虽然过于复杂。你可以使用已经可用的

宏isxdigit和tolower(都在ctype.h中定义),但坦率地说你

甚至不需要它们。你肯定不需要你的power2()。


想一想。什么是1986年的小数?

在你的算法中,它是1 * 10 ^ 3 + 9 * 10 ^ 2 + 8 * 10 ^ 1 + 1 * 10 ^ 0。 />
如何(((1)* 10 + 9)* 10 + 8)* 10 + 6?


现在尝试将其转换为C程序,任何(hexa)十进制数字,任意

位数。

// ******************** ****************************** ****************

当我将char c []更改为main()中的char * c时,
显示错误,为什么?


未定义的行为。你的htoi()试图改变它在

situ中给出的字符串。使用char c [] in main,字符串文字0xAB复制到本地

数组c,这没关系。但是当你将c声明为char *时,你将一个指针

传递给字符串文字到htoi()... oops!

谢谢..




HTH,


Peter


Herrcho写道:

嗨〜我自己已经学了几个月了,

如果有人能改进我的编码或纠正它,我会很感激。
<以下是我对K& R练习的解决方案2-3

写函数htoi(s),它转换一串十六进制数字
(包括一个可选的0x或0X)到它的等效整数值。
允许的数字是0到9,a到f,和A到F.



关闭,不是一个糟糕的尝试。但最大的问题是你已经假设ASCII字符集是b $ b。继续阅读以获得完整的评论...


// *************************** *********************** ************************ #include< stdio.h>


#include< string.h> / *''因为我要用strchr * /

int isxdigit2(int c)
{
if((c> ='''''&& ; c< =''f'')||(c> =''A''&& c< ='''F'')||(c> ='''0''< br&>&& c< =''9''))


这里你假设'''' - '''''和'''''' - F在

字符集中以连续的升序排列。这不一定是真的(是的,即使我不高兴知道

)。但请注意,''0' - ''9''保证按标准连续

升序。


那么,做什么我们的确是?很简单,我们保留一个包含有效十六进制字母的字符串和

查看要检查的字符是否出现在该字符串中:


static const char * hexalpha = abcdefABCDEF;


if((c> =''0''&& c< ='''9'')||(c&& ; strchr(hexalpha,c)))

返回1;

返回0;
}


或者,你可以使用isxdigit标准函数,但是那个'b $ b方式不那么有趣:-)

int tolower2(int c)
{
if(c> =''A''&& c< =''Z'')
返回c + 32;


哎哟!!再一次,你不仅假设A - Z是连续的,而且还假设A+ 32 ==''a '',

全部不一定是真的。你可以使用标准的tolower,或者:

static const char * uppercase =" ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;;

static const char * lowercase =" abcdefghijklmnopqrstuvwxyz" ;;


char * cptr = strchr(大写,c);

如果(cptr)返回小写[cptr - uppercase];

返回c;

其他
返回c;
}
int power2(int base,int num)
{
int sum;
for(sum = 1; num> 0; num - )
sum * = base;
返回总和;
}


嗯......太复杂了......看下面为什么不需要这个。

int char_to_num(int c)
{
if( c> =''0''&& c< ='''9'')
{
返回c - 48;


哎哟!!在这里你假设''''== 48,这不一定是真的。为什么不:

返回c - ''0'';

}
其他
{
返回10 +(tolower2(c ) - ''一个'');


再次,''a'' - ''f''不需要在字符集中连续提升。那么你可以做的
是:

static const char * hexalpha =" abcdef" ;;

返回10 +(strchr(hexalpha, tolower2(c)) - hexalpha);

}
}
int htoi(char * c)


这样:

unsigned int htoi(char * c)

{
int i,k,prefix = 0;
size_t sum = 0;
unsigned int sum;
if(c [0] ==''0''&& tolower2(c [1])==''x'')
prefix = 1;

for(i =(prefix == 1)?2:0; c [i]; i ++)
{
if(!isxdigit2(c [i] ))
{
printf(错误的六位数\ n);
返回0;
}
c [i] = char_to_num(c [i ]);
对于(k =(前缀== 1)?2:0; k <= i-1; ++ k)
{
sum + = c [k] * power2(16,i-1-k);


返回总和;
}


如果你认识到继续下去,你可以简单地解决问题

从字符串中从左到右是你能做的最好的事情。只需

乘以你所拥有的16并添加下一个数字就行了,瞧瞧

你最后有正确的转换。


if(c [0] ==''0''&&(c [1] ==''x''|| c [1] ==''X'')) />
c + = 2;

while(* c&& isxdigit2(* c)){

sum =(sum * 16)+ char_to_num (* c);

++ c;

}

if(* c){

fprintf( stderr,字符串\ n中的十六进制数字%c无效,* c);

sum = 0;

}

返回总和;

int main()
{
char c [] =" 0xAB";
printf("%u",htoi(c)) ;

返回0;
}

// *********************** *************************** ****************
当我在main()中将char c []更改为char * c时,
显示错误,为什么?


谁显示了什么错误?


-nrk。

谢谢..




-

删除电子邮件的devnull


Peter Pichler写道:

" Herrcho" ; <他********* @ kornet.net>在消息中写道
新闻:76 ************************* @ posting.google.co m ...

嗨〜我自己研究过C几个月了,
对你有好处。

如果有人能提高我的编码,我会很感激或者纠正它。

以下是我对K& R练习的解决方案2-3



非常好,最后有人实际上显示了一些代码! ;-)
请注意,我下面的许多评论都是尼特,但是在你需要忘记错误的习惯之前,现在学习好习惯是很好的。比如我自己。

"编写函数htoi(s),它将一串十六进制数字(包括可选的0x或0X)转换为其等效的整数值。允许的数字是0到9,a到f,和A tot
F。



// ***** ********************************************* ***** *******************


#include< stdio.h>

int isxdigit2(int c)



标准以''开头'后跟小写字母的标识符由C标准保留。请使用类似is_xdigit2的东西。
顺便说一句,已经有一个宏isxdigit,你需要#include
< ctype.h>

{
if((c> =''a''&& c< =''f'')||(c> =''A''&& c< =' 'F'')||(c> =''0''&& c
< =


''9''))

这不能保证在非ASCII系统上工作。范围''a''..'''''和A......F不需要是连续的。但是保证
''0''''''9'',

返回1;

返回0;
}



正确的缩进会让你的代码更容易阅读。




缩进'没关系'但他/她使用制表符而不是空格。 OP:你

应该使用空格来缩进你在usenet上发布的代码。

int tolower2(int c )
{
if(c> =''A''&& c< =''Z'')
返回c + 32;
else
return c;
}



与上述相同的评论。顺便说一句,标识符以''开头''也是保留的。

int power2(int base,int num)
{和/ ;
for(sum = 1; num> 0; num - )
sum * = base;
返回总和;
}
int char_to_num(int c)
{
if(c> =''0''&& c< ='''9'')
{
返回c - 48;



神奇的数字48来自哪里? ITYM返回c - ''0'';

}

{
返回10 +(tolower2(c) - ''a' ');



同样,只有当你确定''''''''''''是一个连续的集合时,这才有效。

}
}
int htoi(char * c)
{i /,int i,k,prefix = 0;
size_t sum = 0;

if(c [0] ==''0''&& tolower2(c [1])==''x'')
prefix = 1;



您确定c中有2个有效字符吗?例如,当你打电话给htoi(7)时会发生什么?




任何非空字符串在c [0]中都有有效值和c [1]。另外,

标准保证''\'''!=''0'':-)

尝试:

如果(c [0]&& c [0] ==''0''&& c [1]&&(c [1] ==''x''|| c [1] ==''X''))
前缀= 1;

它的优点不那么优雅但更安全。顺便说一句,你可以在没有变量前缀的算法上工作。它真的很简单,想一想它。你需要的只是跳过c的前两个字符...

for(i =(prefix == 1)?2:0; c [i]; i ++)
{
如果(!isxdigit2(c [i]))
{
printf("错误的六进制数\ n");



Hexa如在jinxed中? ;-)

return 0;
}
c [i] = char_to_num(c [i]);
}

for(k =(prefix == 1)?2:0; k <= i-1; ++ k)
{
sum + = c [k] * power2(16 ,i-1-k);
}
返回总和;
}
int main()
{
char c [] =" 0xAB";
printf("%u",htoi(c));



呃,不,先生。 printf()中的%u期望unsigned int,但是你提供了
htoi()的结果,返回int。严格来说,这是一种未定义的行为,虽然我还没有看到一个平台
它不起作用。在任何情况下,使用%d代替或更改你的htoi()
以返回unsigned int。

return 0;
}



看起来不错,虽然过于复杂。你可以使用已经可用的宏isxdigit和tolower(都在ctype.h中定义),但坦率地说你甚至不需要它们。你肯定不需要你的
power2()。

想一想。什么是1986年的十进制?
在你的算法中,它是1 * 10 ^ 3 + 9 * 10 ^ 2 + 8 * 10 ^ 1 + 1 * 10 ^ 0.
怎么样(((1)* 10 + 9)* 10 + 8)* 10 + 6?
现在尝试将其转换为C程序,对于任何(hexa)十进制数字
any位数。

// ******************************** ****************** ****************

当我将char c []改为main()中的char * c,
它显示错误,为什么??



未定义的行为。你的htoi()试图改变它在
原地给出的字符串。使用char c [] in main,字符串文字0xAB复制到
本地数组c,这没关系。但是当你将c声明为char *时,你将指向字符串文字的
指针传递给htoi()... oops!




Waah ...我错过了那个,不是吗?诡异的小兄弟......


-nrk。

谢谢..



HTH,

Peter




-

删除电子邮件的devnull


Hi~ i''ve studied C for a few months myself,

and i''d appreciate it if anyone could improve my coding or correct it.

the following is my solution to the K&R exercise 2-3

"Write the function htoi(s), which converts a string of hexademical digits
(including an optional 0x or 0X) into its equivalent integer value.
The allowable digits are 0 through 9, a through f, and A throught F."
//************************************************** ************************

#include <stdio.h>

int isxdigit2(int c)
{
if ( (c >= ''a'' && c <= ''f'') || (c >= ''A'' && c <= ''F'') || (c >= ''0'' && c <= ''9'') )
return 1;
else
return 0;
}

int tolower2(int c)
{
if (c >= ''A'' && c <= ''Z'')
return c+32;
else
return c;
}

int power2(int base, int num)
{
int sum;
for (sum = 1; num >0 ; num --)
sum *= base;
return sum;
}

int char_to_num(int c)
{
if (c >= ''0'' && c <= ''9'')
{
return c - 48;
}
else
{
return 10 + (tolower2(c) - ''a'');
}
}

int htoi(char *c)
{
int i, k, prefix = 0;
size_t sum = 0;

if (c[0] == ''0'' && tolower2(c[1]) == ''x'')
prefix = 1;

for (i = (prefix == 1)? 2:0 ; c[i] ;i++ )
{
if (!isxdigit2(c[i]) )
{
printf("Wrong hexa number\n");
return 0;
}
c[i] = char_to_num(c[i]);
}

for (k = (prefix == 1)? 2 : 0 ; k <= i-1 ; ++k )
{
sum += c[k] * power2(16, i-1-k);
}

return sum;
}

int main()
{
char c[] = "0xAB";
printf("%u", htoi(c));

return 0;
}

//************************************************** ****************

when i change char c[] to char *c in main(),
it shows error, why ??

Thanks..

解决方案

"Herrcho" <he*********@kornet.net> wrote in message
news:76*************************@posting.google.co m...

Hi~ i''ve studied C for a few months myself,
Good for you.
and i''d appreciate it if anyone could improve my coding or correct it.

the following is my solution to the K&R exercise 2-3
Excellent, finally someone who has actually shown some code! ;-)
Beware, many of my comments below are nits, but it is nice to learn the
good habits now before you''d need to unlearn the wrong ones, like myself.
"Write the function htoi(s), which converts a string of hexademical digits
(including an optional 0x or 0X) into its equivalent integer value.
The allowable digits are 0 through 9, a through f, and A throught F."

//************************************************** ************************
#include <stdio.h>

int isxdigit2(int c)
Identifiers starting with ''is'' followed by a lowercase letter are reserved
by the C standard. Use something like is_xdigit2 instead.
By the way, there already is a macro isxdigit, you need to #include
<ctype.h>
{
if ( (c >= ''a'' && c <= ''f'') || (c >= ''A'' && c <= ''F'') || (c >= ''0'' && c <= ''9'') )

This is not guaranteed to work on non-ASCII systems. The ranges ''a''..''f'' and
''A''..''F'' do not need to be consecutive. It is guaranteed about ''0''..''9'',
though.
return 1;
else
return 0;
}
Proper indentation would make your code easier to read.
int tolower2(int c)
{
if (c >= ''A'' && c <= ''Z'')
return c+32;
else
return c;
}
Same comments as above. BTW, identifiers starting with ''to'' are reserved
too.
int power2(int base, int num)
{
int sum;
for (sum = 1; num >0 ; num --)
sum *= base;
return sum;
}

int char_to_num(int c)
{
if (c >= ''0'' && c <= ''9'')
{
return c - 48;
Where does the magic number 48 come from? ITYM return c - ''0'';
}
else
{
return 10 + (tolower2(c) - ''a'');
Again, this only works if you are sure that ''a''..''f'' is a consecutive set.
}
}

int htoi(char *c)
{
int i, k, prefix = 0;
size_t sum = 0;

if (c[0] == ''0'' && tolower2(c[1]) == ''x'')
prefix = 1;
Are you sure that you have 2 valid characters in c? What happens when you
call htoi("7"), for example?
Try:

if (c[0] && c[0] == ''0'' && c[1] && (c[1] == ''x'' || c[1] == ''X''))
prefix = 1;

It''s admittably a bit less elegant but safer. By the way, you could work on
an algorithm without the variable prefix. It''s really simple, think about it
a little. All you need is to skip the first 2 characters of c...
for (i = (prefix == 1)? 2:0 ; c[i] ;i++ )
{
if (!isxdigit2(c[i]) )
{
printf("Wrong hexa number\n");
"Hexa" as in "jinxed"? ;-)
return 0;
}
c[i] = char_to_num(c[i]);
}

for (k = (prefix == 1)? 2 : 0 ; k <= i-1 ; ++k )
{
sum += c[k] * power2(16, i-1-k);
}

return sum;
}

int main()
{
char c[] = "0xAB";
printf("%u", htoi(c));
Err, no sir. %u in printf() expects unsigned int, but you provide it with
the result of htoi(), which returns int. This is strictly speaking an
undefined behaviour, although admittably I have yet to see a platform where
it does not work. In any case, use %d instead or change your htoi() to
return unsigned int.
return 0;
}
It looks OK, though overly complicated. You could use already available
macros isxdigit and tolower (both defined in ctype.h), but frankly you
should not even need them. And you certainly should not need your power2().

Think about it. What''s 1986 in decimal?
In your algorithm, it''s 1*10^3 + 9*10^2 + 8*10^1 + 1*10^0.
How about (((1)*10 + 9)*10 + 8)*10 + 6?

Now try converting it to a C program, for any (hexa)decimal number with any
number of digits.
//************************************************** ****************

when i change char c[] to char *c in main(),
it shows error, why ??
Undefined behaviour. Your htoi() tries to alter the string it is given in
situ. With char c[] in main, the string literal "0xAB" get copied to a local
array c, which is OK. But when you declare c as char *, you pass a pointer
to the string literal to htoi()... oops!
Thanks..



HTH,

Peter


Herrcho wrote:

Hi~ i''ve studied C for a few months myself,

and i''d appreciate it if anyone could improve my coding or correct it.

the following is my solution to the K&R exercise 2-3

"Write the function htoi(s), which converts a string of hexademical digits
(including an optional 0x or 0X) into its equivalent integer value.
The allowable digits are 0 through 9, a through f, and A throught F."


First off, not a bad attempt. But the biggest problem is that you''ve
assumed ASCII character set. Read on for the complete review...
//************************************************** ************************
#include <stdio.h>

#include <string.h> /* ''coz I am gonna use strchr */
int isxdigit2(int c)
{
if ( (c >= ''a'' && c <= ''f'') || (c >= ''A'' && c <= ''F'') || (c >= ''0''
&& c <= ''9'') )
Here you assume ''a''-''f'' and ''A''-''F'' are in contiguous ascending order in the
character set. This need not be true (yes, even I wasn''t happy to know
that). Note however that ''0''-''9'' are guaranteed to be in contiguous
ascending order by the standard.

So, what do we do? Simple, we keep a string with valid hex-alphabets and
see if the character to be checked occurs within that string:

static const char *hexalpha = "abcdefABCDEF";

if ( (c >= ''0'' && c <= ''9'') || (c && strchr(hexalpha, c)) )
return 1;
else
return 0;
}

Alternately, you could just use the isxdigit standard function, but that''s
way less fun :-)
int tolower2(int c)
{
if (c >= ''A'' && c <= ''Z'')
return c+32;
Ouch!! Once again, you''ve not only assumed that ''A''-''Z'' are contiguous
ascending, but also assumed that ''A''+32 == ''a'', which need not be true at
all. You could either use the standard tolower, or:
static const char *uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char *lowercase = "abcdefghijklmnopqrstuvwxyz";

char *cptr = strchr(uppercase, c);
if ( cptr ) return lowercase[cptr - uppercase];
return c;
else
return c;
}

int power2(int base, int num)
{
int sum;
for (sum = 1; num >0 ; num --)
sum *= base;
return sum;
}

Hmmm... way too complicated... see below for why this isn''t needed.
int char_to_num(int c)
{
if (c >= ''0'' && c <= ''9'')
{
return c - 48;
Ouch!! Here you assumed ''0'' == 48, which need not be true. Why not:
return c - ''0'';
}
else
{
return 10 + (tolower2(c) - ''a'');
Again, ''a''-''f'' need not be contiguous ascending in the character set. What
you can do instead is:
static const char *hexalpha = "abcdef";
return 10 + (strchr(hexalpha, tolower2(c)) - hexalpha);
}
}

int htoi(char *c)
Make that:
unsigned int htoi(char *c)
{
int i, k, prefix = 0;
size_t sum = 0; unsigned int sum;
if (c[0] == ''0'' && tolower2(c[1]) == ''x'')
prefix = 1;

for (i = (prefix == 1)? 2:0 ; c[i] ;i++ )
{
if (!isxdigit2(c[i]) )
{
printf("Wrong hexa number\n");
return 0;
}
c[i] = char_to_num(c[i]);
}

for (k = (prefix == 1)? 2 : 0 ; k <= i-1 ; ++k )
{
sum += c[k] * power2(16, i-1-k);
}

return sum;
}

You can simplify matters quite a bit if you recognize that proceeding
left-to-right in the string is the best thing that you can do. Simply
multiply whatever you have by 16 and add the next number in line, and voila
you have the correct conversion at the end.

if ( c[0] == ''0'' && (c[1] == ''x'' || c[1] == ''X'') )
c += 2;
while ( *c && isxdigit2(*c) ) {
sum = (sum * 16) + char_to_num(*c);
++c;
}
if ( *c ) {
fprintf(stderr, "Invalid hex digit %c in string\n", *c);
sum = 0;
}
return sum;
int main()
{
char c[] = "0xAB";
printf("%u", htoi(c));

return 0;
}

//************************************************** ****************

when i change char c[] to char *c in main(),
it shows error, why ??

Who shows what error?

-nrk.
Thanks..



--
Remove devnull for email


Peter Pichler wrote:

"Herrcho" <he*********@kornet.net> wrote in message
news:76*************************@posting.google.co m...

Hi~ i''ve studied C for a few months myself,
Good for you.

and i''d appreciate it if anyone could improve my coding or correct it.

the following is my solution to the K&R exercise 2-3



Excellent, finally someone who has actually shown some code! ;-)
Beware, many of my comments below are nits, but it is nice to learn the
good habits now before you''d need to unlearn the wrong ones, like myself.

"Write the function htoi(s), which converts a string of hexademical
digits (including an optional 0x or 0X) into its equivalent integer
value. The allowable digits are 0 through 9, a through f, and A throught
F."


//************************************************** ************************


#include <stdio.h>

int isxdigit2(int c)



Identifiers starting with ''is'' followed by a lowercase letter are reserved
by the C standard. Use something like is_xdigit2 instead.
By the way, there already is a macro isxdigit, you need to #include
<ctype.h>

{
if ( (c >= ''a'' && c <= ''f'') || (c >= ''A'' && c <= ''F'') || (c >= ''0'' && c
<=


''9'') )

This is not guaranteed to work on non-ASCII systems. The ranges ''a''..''f''
and ''A''..''F'' do not need to be consecutive. It is guaranteed about
''0''..''9'', though.

return 1;
else
return 0;
}



Proper indentation would make your code easier to read.



The indentation''s ok, but he/she used tabs instead of spaces. To OP: You
should use spaces to indent code that you post on the usenet.

int tolower2(int c)
{
if (c >= ''A'' && c <= ''Z'')
return c+32;
else
return c;
}



Same comments as above. BTW, identifiers starting with ''to'' are reserved
too.

int power2(int base, int num)
{
int sum;
for (sum = 1; num >0 ; num --)
sum *= base;
return sum;
}

int char_to_num(int c)
{
if (c >= ''0'' && c <= ''9'')
{
return c - 48;



Where does the magic number 48 come from? ITYM return c - ''0'';

}
else
{
return 10 + (tolower2(c) - ''a'');



Again, this only works if you are sure that ''a''..''f'' is a consecutive set.

}
}

int htoi(char *c)
{
int i, k, prefix = 0;
size_t sum = 0;

if (c[0] == ''0'' && tolower2(c[1]) == ''x'')
prefix = 1;



Are you sure that you have 2 valid characters in c? What happens when you
call htoi("7"), for example?



Any non-empty string will have valid values in c[0] and c[1]. Also, the
standard guarantees that ''\0'' != ''0'' :-)
Try:

if (c[0] && c[0] == ''0'' && c[1] && (c[1] == ''x'' || c[1] == ''X''))
prefix = 1;

It''s admittably a bit less elegant but safer. By the way, you could work
on an algorithm without the variable prefix. It''s really simple, think
about it a little. All you need is to skip the first 2 characters of c...

for (i = (prefix == 1)? 2:0 ; c[i] ;i++ )
{
if (!isxdigit2(c[i]) )
{
printf("Wrong hexa number\n");



"Hexa" as in "jinxed"? ;-)

return 0;
}
c[i] = char_to_num(c[i]);
}

for (k = (prefix == 1)? 2 : 0 ; k <= i-1 ; ++k )
{
sum += c[k] * power2(16, i-1-k);
}

return sum;
}

int main()
{
char c[] = "0xAB";
printf("%u", htoi(c));



Err, no sir. %u in printf() expects unsigned int, but you provide it with
the result of htoi(), which returns int. This is strictly speaking an
undefined behaviour, although admittably I have yet to see a platform
where it does not work. In any case, use %d instead or change your htoi()
to return unsigned int.

return 0;
}



It looks OK, though overly complicated. You could use already available
macros isxdigit and tolower (both defined in ctype.h), but frankly you
should not even need them. And you certainly should not need your
power2().

Think about it. What''s 1986 in decimal?
In your algorithm, it''s 1*10^3 + 9*10^2 + 8*10^1 + 1*10^0.
How about (((1)*10 + 9)*10 + 8)*10 + 6?

Now try converting it to a C program, for any (hexa)decimal number with
any number of digits.

//************************************************** ****************

when i change char c[] to char *c in main(),
it shows error, why ??



Undefined behaviour. Your htoi() tries to alter the string it is given in
situ. With char c[] in main, the string literal "0xAB" get copied to a
local array c, which is OK. But when you declare c as char *, you pass a
pointer to the string literal to htoi()... oops!



Waah... I missed that one, didn''t I? Tricksy little hobbitses...

-nrk.

Thanks..



HTH,

Peter



--
Remove devnull for email


这篇关于K&amp; R 2运动2-3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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