这个str_rev()好吗? [英] Is this str_rev() ok?

查看:78
本文介绍了这个str_rev()好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在弄乱我发现的一个练习。

这似乎有效,除了在调试中,发生了一些非常奇怪的事情,

所以我想我'' d在这里查看代码以查看它是如何站起来的。


为了释放它,我必须使char * y全局化。恶心。


#include< stdio.h>

#include< stdlib.h>

#include< string.h>


char * rev_str(char *);

char * y;

int main(void)

{

char * stToRev =" Dontchajustwishthisstringwouldgetreversed" ;;

printf("%s \ n",rev_str(stToRev));

免费(y);

返回0;

}


char * rev_str(char * x)

{

size_t arrLength = strlen(x)+1;

y = malloc(arrLength);

memcpy(y,x,arrLength);

y =& y [arrLength-1];

while(* - y = * x ++);

* y ++;

返回y;

}

I was messing around with an exercise I found.
This seems to work, except in debugging, some VERY odd stuff happens,
so I thought I''d chuck the code on here to see how it stands up.

I had to make char *y global in order to free it. Disgusting.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *rev_str(char *);
char *y;
int main(void)
{
char *stToRev = "Dontchajustwishthisstringwouldgetreversed";
printf("%s\n", rev_str(stToRev));
free(y);
return 0;
}

char *rev_str(char *x)
{
size_t arrLength = strlen(x)+1;
y = malloc(arrLength);
memcpy(y,x,arrLength);
y = &y[arrLength-1];
while (*--y = *x++);
*y++;
return y;
}

推荐答案

ballpointpenthief说:
ballpointpenthief said:
我正在搞乱我发现的一个练习。
这似乎有用,除了在调试中,一些非常奇怪的事情发生,
我必须让char * y全球化以便释放它。恶心。


不,你可以这样做:


char * ptr = rev_str(stToRev);

if (ptr!= NULL)

{

printf("%s \ n",ptr);

free(ptr);

}


无需文件范围。


< snip>
char * rev_str (char * x)


既然你不打算改变x,为什么不把它变成const char *?

{
size_t arrLength = strlen(x)+1;
y = malloc(arrLength);
memcpy(y,x,arrLength);


这很好(除了你可能想使用本地的y,而不是文件范围对象的
),前提是malloc成功。但是如果它失败了,你真的真的不想记住结果。


所以先检查一下NULL。

y =& y [arrLength-1];


不要修改那个指针。使用临时。请注意,如果arrLength为1(如果x为"则为
),则表示您位于数组的开头...

while( * - y = * x ++);
I was messing around with an exercise I found.
This seems to work, except in debugging, some VERY odd stuff happens,
so I thought I''d chuck the code on here to see how it stands up.

I had to make char *y global in order to free it. Disgusting.
No, you could have done this:

char *ptr = rev_str(stToRev);
if(ptr != NULL)
{
printf("%s\n", ptr);
free(ptr);
}

No need for file scope.

<snip>
char *rev_str(char *x)
Since you don''t plan to change x, why not make it const char *?
{
size_t arrLength = strlen(x)+1;
y = malloc(arrLength);
memcpy(y,x,arrLength);
That''s fine (except that you probably want to use a local for y, rather than
a file scope object), provided malloc succeeds. But if it fails, you really
really really don''t want to be memcpying to the result.

So check for NULL first.
y = &y[arrLength-1];
Don''t mod that pointer. Use a temp. Note that, if arrLength is 1 (which it
will be if x is ""), you are at the beginning of the array...
while (*--y = *x++);




....这意味着这一位将会中断。


-

Richard Heathfield

Usenet是一个奇怪的地方 - dmr 29/7/1999
http://www.cpax.org.uk

电子邮件:rjh在上面的域名(但显然放弃了www)



....which means this bit will break.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)




Richard希思菲尔德写道:

Richard Heathfield wrote:
不,你可以这样做:




这是什么?


#include< stdio.h>

#include< stdlib.h>

#include< string.h>


char * rev_str(char *);

int main(无效)

{

char * stToRev ="一个男人,一个计划,运河;巴拿马。" ;;

char * ptr = rev_str(stToRev);

if(ptr)

{

printf("%s \ n",ptr);

免费(ptr);

}

返回0;

}


char * rev_str(char * x)

{

char * tmp,* y ;

size_t arrLength = strlen(x)+1;


y = malloc(arrLength);

if(y == NULL)

返回NULL;

if(!memcpy(y,x,arrLength))

返回NULL;

tmp =& y [arrLength-1];

while(* - tmp = * x ++);

返回y;

}


我正在使用调试器吗?它正在做一些ODD的东西。

还有关于while的抱怨(* - tmp = * x ++);当显示

时所有警告:


Wedit输出窗口构建:2006年6月27日星期二19:40:31

警告c: \lcc\projects\str_rev.c:29条件中的分配

表达式

编译+链接时间:0.1秒,返回代码:0



What this?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *rev_str(char *);
int main(void)
{
char *stToRev = "A man, a plan, a canal; Panama.";
char *ptr = rev_str(stToRev);
if (ptr)
{
printf("%s\n", ptr);
free(ptr);
}
return 0;
}

char *rev_str(char *x)
{
char *tmp, *y;
size_t arrLength = strlen(x)+1;

y = malloc(arrLength);
if (y == NULL)
return NULL;
if (!memcpy(y,x,arrLength))
return NULL;
tmp = &y[arrLength-1];
while (*--tmp = *x++);
return y;
}

Is the debugger I''m using broken then? It''s doing some ODD stuff.
There is also a complaint about the while (*--tmp = *x++); when showing
all warnings:

Wedit output window build: Tue Jun 27 19:40:31 2006
Warning c:\lcc\projects\str_rev.c: 29 Assignment within conditional
expression
Compilation + link time:0.1 sec, Return code: 0


2006年6月27日11:00:34 -0700,ballpointpenthief

< Ma ********* ****@gmail.com>在comp.lang.c中写道:
On 27 Jun 2006 11:00:34 -0700, "ballpointpenthief"
<Ma*************@gmail.com> wrote in comp.lang.c:
我正在搞乱我发现的练习。
这似乎有用,除了在调试中,发生了一些非常奇怪的事情,
所以我想我会把代码放在这里查看它是如何站起来的。


确实非常奇怪。

为了解冻它,我必须使char * y全局化。恶心。


不,你没有。看看我添加到你主要的行()。


我打算假装你使用一个小得多的原始字符串来表示

说明用途,即" 123"。

#include< stdio.h>
#include< stdlib.h>
#include< string.h>

char * rev_str(char *);


制作原型:


char * rev_str(const char *);


。 ...因为你没有修改输入字符串而且函数是安全的

用于字符串文字和常量字符串。

char * y;
int main(void)
{* * char * stToRev =" Dontchajustwishthisstringwouldgetreversed" ;;


char * rev = rev_str(stTdRev);

printf("%s \ n",rev_str(stToRev));
自由(Y);


现在将以上两行替换为:


printf("%s \ n",rev);

免费(转);

返回0;
}

char * rev_str(char * x)


再次:


char * rev_str(const char * x)

{
size_t arrLength = strlen(x)+1;


好​​,加+1。对于字符串123,arrLength是4.

y = malloc(arrLength);


错误,没有检查来自malloc()的NULL返回。

memcpy(y,x,arrLength);
y =& Y [arrLength-1];


如果malloc()为
不成功并且返回空指针,则上述两行都会调用未定义的行为。另外它是完全不必要的,如果你只是用相反的顺序写它们,你可以通过复制原始的

顺序中的内容获得什么? />
如果您想要做的只是''\ 0''终止新字符串,那么肯定会更有效率,更清晰,更好:
$ b $ + = arrLength - 1;

* y =''\ 0'';

while(* - y = * X ++);


目前,让我们假设你的memcpy()代码仍然存在,所以

因为这个循环开始了,这里是两个每次通过循环时,内存区域和两个

指针看起来像:

在传递之前1:orig = 1 2 3 \0 rev = 1 2 3 \ 0

xy


在通过之前2:orig = 1 2 3 \ 0 rev = 1 2 1 \ 0

xy


在通过3之前:orig = 1 2 3 \ 0 rev = 1 2 1 \ 0

xy

在传球3之前:orig = 1 2 3 \ 0 rev = 3 2 1 \ 0

xy


传球前4:orig = 1 2 3 \ 0 rev = 3 2 1 \ 0

xy


在传球4中,你首先减少''y'指向

分配内存之前的一个字节,这本身就是未定义的行为。你可以

总是在有效内存结束后形成指向对象的指针,

是否动态分配,但不保证

,你可以在块的开头之前形成一个指针。


但更糟糕的是,你写或试图写''\ 0''null字符

从初始字符串到分配的

内存之前的一个字节。这是一个严重的错误,很可能是你的原因造成的。

奇数行为。

* y ++;
返回y;


现在已经太晚了,因为你的程序已经关闭了

永远不会降落,但是你不需要取消引用指针只是

来增加它,你不需要在

返回语句之前计算该值。


你没有用它,因为当你正确地重写算法

时,你永远不会指向分配的

块的开头之前并且需要递增指针。但如果你确实需要在返回其值之前增加一个指针,你可以将这两行合并为

,或者:


返回++ y;


....或:


返回y + 1;

}
I was messing around with an exercise I found.
This seems to work, except in debugging, some VERY odd stuff happens,
so I thought I''d chuck the code on here to see how it stands up.
Very odd stuff indeed.
I had to make char *y global in order to free it. Disgusting.
No, you didn''t. See the lines I added to your main().

I''m going to pretend you used a much smaller original string for
illustrative purposes, namely "123".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *rev_str(char *);
Make the prototype:

char *rev_str(const char *);

....since you don''t modify the input string and the function is safe
for string literals and constant strings.
char *y;
int main(void)
{
char *stToRev = "Dontchajustwishthisstringwouldgetreversed";
char *rev = rev_str(stTdRev);
printf("%s\n", rev_str(stToRev));
free(y);
Now replace the two lines above with:

printf("%s\n", rev);
free(rev);
return 0;
}

char *rev_str(char *x)
Again:

char *rev_str(const char *x)
{
size_t arrLength = strlen(x)+1;
Good, adding the +1. For the string "123", arrLength is 4.
y = malloc(arrLength);
Bad, not checking for a NULL return from malloc().
memcpy(y,x,arrLength);
y = &y[arrLength-1];
Both lines above invokes undefined behavior if malloc() was
unsuccessful and returned a null pointer. Also it is completely
unnecessary, what do you gain by copying the contents in the original
order if you are only going to write over them with the reverse order?
If all you wanted to do was ''\0'' terminate the new string, it would
surely be more efficient, and much clearer, to do:

y += arrLength - 1;
*y = ''\0'';
while (*--y = *x++);
For the moment, let''s assume your memcpy() code is still in place, so
as this loop starts, here is what the two memory areas and the two
pointers look like on each pass through the loop:

Before pass 1: orig = 1 2 3 \0 rev = 1 2 3 \0
x y

Before pass 2: orig = 1 2 3 \0 rev = 1 2 1 \0
x y

Before pass 3: orig = 1 2 3 \0 rev = 1 2 1 \0
x y

Before pass 3: orig = 1 2 3 \0 rev = 3 2 1 \0
x y

Before pass 4: orig = 1 2 3 \0 rev = 3 2 1 \0
x y

During pass 4, you first decrement ''y'' to point to one byte before the
allocated memory, which is in itself undefined behavior. You can
always form a pointer to the object one past the end of valid memory,
whether it is dynamically allocated or not, but there is no guarantee
that you can form a pointer before the beginning of the block.

But even worse, you write, or attempt to write, a ''\0'' null character
from the initial string into this byte one before the allocated
memory. That''s a serious error, and most likely the cause of your
"odd" behavior.
*y++;
return y;
It''s too late now, because your program is already off into
never-never land, but you don''t need to dereference the pointer just
to increment it, and you don''t need to compute the value before the
return statement.

You have no use for this, because when you rewrite the algorithm
properly you will never point to before the beginning of the allocated
block and need to increment the pointer. But if you did need to
increment a pointer before returning its value, you could combine
these two lines into one, either:

return ++y;

....or:

return y + 1;
}




-

Jack Klein

主页: http://JK-Technology.Com



comp.lang的常见问题解答.c http://c-faq.com/

comp.lang.c ++ http://www.parashift.com/c++ -faq-lite /

alt.comp.lang.learn.c-c ++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html



--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html


这篇关于这个str_rev()好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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