有人用 goto 语句么?我是用它代替递归

2017-10-24 16:35:17 +08:00
 me15000

//递归
void repeat(c) {

	
		//需要重复的代码
	

		if (xx) {
			 repeat(xx);
		}

}

//goto 代替递归
void repeat(c) {

	loop:
		//需要重复的代码
	

		if (xx) {
			goto loop;
		}

}


        //一个采集程序
        public void Run(string listurl)
        {
            using (var wc = new WebClient())
            {
                loop:

                string html = Encoding.GetEncoding("utf-8").GetString(wc.DownloadData(listurl));
                var doc = new HtmlDocument();
                doc.LoadHtml(html);
                var nodes = doc.DocumentNode.SelectNodes("//ul[@id=\"data_list\"]/li/div/a");
                for (int i = 0; i < nodes.Count; i++)
                {
                    var node = nodes[i];
                    string link = "http://www..cn" + node.Attributes["href"].Value;
                    string title = node.SelectSingleNode("span[@class=\"sTit\"]").InnerText;
                    Save(title, link);
                }
                var nextnode = doc.DocumentNode.SelectSingleNode("//div[@class='page mb clearfixs']/em/following-sibling::a");
                if (nextnode != null)
                {
                    listurl = "http://www..cn" + nextnode.Attributes["href"].Value;
                    goto loop;
                }
            }
        }
10509 次点击
所在节点    分享发现
128 条回复
QAPTEAWH
2017-10-24 16:39:39 +08:00
zhujinliang
2017-10-24 16:39:44 +08:00
goto 替代不了递归吧
b821025551b
2017-10-24 16:41:45 +08:00
用 goto 的都烧死,自己爽了,别人要捋大半天。
hualuogeng
2017-10-24 16:41:59 +08:00
递归是可以带参数传入的
me15000
2017-10-24 16:42:04 +08:00
@zhujinliang

```



//一个采集程序 goto 代替递归
public void Run(string listurl)
{
using (var wc = new WebClient())
{
loop:

string html = Encoding.GetEncoding("utf-8").GetString(wc.DownloadData(listurl));
var doc = new HtmlDocument();
doc.LoadHtml(html);
var nodes = doc.DocumentNode.SelectNodes("//ul[@id=\"data_list\"]/li/div/a");
for (int i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
string link = "http://www..cn" + node.Attributes["href"].Value;
string title = node.SelectSingleNode("span[@class=\"sTit\"]").InnerText;
Save(title, link);
}
var nextnode = doc.DocumentNode.SelectSingleNode("//div[@class='page mb clearfixs']/em/following-sibling::a");
if (nextnode != null)
{
listurl = "http://www..cn" + nextnode.Attributes["href"].Value;
goto loop;
}
}
}

//如果使用递归
public void Run(string listurl)
{
using (var wc = new WebClient())
{

string html = Encoding.GetEncoding("utf-8").GetString(wc.DownloadData(listurl));
var doc = new HtmlDocument();
doc.LoadHtml(html);
var nodes = doc.DocumentNode.SelectNodes("//ul[@id=\"data_list\"]/li/div/a");
for (int i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
string link = "http://www..cn" + node.Attributes["href"].Value;
string title = node.SelectSingleNode("span[@class=\"sTit\"]").InnerText;
Save(title, link);
}
var nextnode = doc.DocumentNode.SelectSingleNode("//div[@class='page mb clearfixs']/em/following-sibling::a");
if (nextnode != null)
{
var nexturl = "http://www..cn" + nextnode.Attributes["href"].Value;

Run(nexturl);
}
}
}
```
me15000
2017-10-24 16:45:17 +08:00
@b821025551b 我一般仅用它代替递归,逻辑也很清晰,因为递归好像在 .NET 中有最大嵌套次数限制,而且递归比较消耗资源,所以用 goto 发现很好
takanasi
2017-10-24 16:48:30 +08:00
@me15000 递归不能传参数和循环有什么区别?
me15000
2017-10-24 16:51:33 +08:00
@takanasi
没懂你意思,我没说递归不能传参数
我只想说用 goto 可以代替递归 很好用,递归有限制而且消耗资源
zhujinliang
2017-10-24 16:51:53 +08:00
@me15000 为啥不用 while(true) 呢? for(;;) 也行啊
me15000
2017-10-24 16:53:25 +08:00
@zhujinliang 没 goto 清晰吧,而且 while(true){} for 有作用域范围,不好跳出去,要跳出去还要再写一些逻辑
goto 倒是很省事,定义好 label,就可以跳到那里
pcatzj
2017-10-24 17:00:04 +08:00
@me15000 #8 他的意思是说,如果递归不传递参数的话,跟循环就一样了。所以递归的优势是参数,你用 goto,传递不了参数,跟循环基本没区别
xupefei
2017-10-24 17:02:54 +08:00
高级语言都会把尾递归优化为 goto,所以 goto 我一般只在跳出多层循环的时候用。
不过 goto 有个好处就是调试比递归方便,因为后者在 debug 编译模式下不会被优化从而导致压栈。
hjc4869
2017-10-24 17:06:17 +08:00
楼主,while 这里不好用,用 do while 不行吗?
什么叫循环没 goto 清晰?省事,想跳到哪里就跳到哪里就是清晰吗?那叫面条代码。
wwqgtxx
2017-10-24 17:07:21 +08:00
@xupefei 并不是“都会”,很多解析式语言明确不支持尾递归优化
SuperMild
2017-10-24 17:08:58 +08:00
这样用 goto,真不如循环,循环一看就知道这是想循环,goto 本身不能表达这个意思,想让代码清晰还要加注释说明这个 goto 是为了循环。代码是给人类看的,在遇到瓶颈之前没必要做太细的优化。
fqwerl
2017-10-24 17:09:23 +08:00
用 goto 的基本可以打死了
me15000
2017-10-24 17:09:33 +08:00
@pcatzj 汗,不觉得我上面贴的代码 很方便么,goto 可以再一个 代码块里面,还用传参么?
goto 之前先给变量赋值,赋值之后 goto 过去,变量存储的值还是在的

伪代码:

var 参数 a=1,参数 b=2;

loop:

参数 a++;
参数 b--;

goto loop;
SuperMild
2017-10-24 17:11:13 +08:00
而且从深层循环跳出去,很多语言都支持 break to label
me15000
2017-10-24 17:12:14 +08:00
@fqwerl
@hjc4869

╮(╯▽╰)╭, 不要遵守教条,教条说是面条,意思是大量使用 goto 的情况下,然后就有人根据教条就 不敢用 goto 了
hackpro
2017-10-24 17:13:58 +08:00
递归是多个堆栈
你这个 goto 只有一个堆栈 可能会改写之前的状态参量

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/400286

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX