将 duff 的设备从 C 移植到 JavaScript
Posted
技术标签:
【中文标题】将 duff 的设备从 C 移植到 JavaScript【英文标题】:Porting duff's device from C to JavaScript 【发布时间】:2016-08-29 04:14:55 【问题描述】:我有这种 C 语言的 Duff 设备,它工作正常(将文本格式化为钱):
#include <stdio.h>
#include <string.h>
char *money(const char *src, char *dst)
const char *p = src;
char *q = dst;
size_t len;
len = strlen(src);
switch (len % 3)
do
*q++ = ',';
case 0: *q++ = *p++;
case 2: *q++ = *p++;
case 1: *q++ = *p++;
while (*p);
*q++ = 0;
return dst;
int main(void)
char str[] = "1234567890123";
char res[32];
printf("%s\n", money(str, res));
return 0;
输出:
1,234,567,890,123
但我在尝试在 javascript 中实现相同的功能时遇到了问题:
function money(src, dst)
var len = src.length;
var i = 0;
switch (len % 3)
do
dst += ',';
case 0: dst += src[i++];
case 2: dst += src[i++];
case 1: dst += src[i++];
while (src[i]);
return dst;
var str = "1234567890123";
var res = "";
console.log(money(str, res));
nodejs 返回此错误:
do
^^
SyntaxError: Unexpected token do
我的问题是:javascript 是否支持计算的 GOTO 语句?
P.D:我不想要替代品,我只想知道为什么不起作用。
相关问题:Does Duff's Device work in other languages?
【问题讨论】:
【参考方案1】:我的问题是:javascript 是否支持计算的 GOTO 语句?
不是真的。
P.D:我不想要替代品,我只想知道为什么不起作用。
它不起作用,因为在 JavaScript 中,switch
statements must only contain case
blocks。
虽然您可能不会寻找解决方法,但其他人可能会在寻找解决方法时发现这个问题,所以无论如何我都会提供一个。 这要归功于mnieper,他在asm.js 上提出了建议。
基本思想是在顶层有一个while(true)
循环,在里面有一个switch
语句。
goto:
while(true)
switch(where)
// no breaks
case 0:
// some code...
case 1:
// some other code...
// ...
为了模拟 goto,可以使用
where = 1;
continue goto;
不过,为了模拟 duff 的设备,只需将循环设为外部结构,并在 switch 语句中使用一个变量,该变量在第一次迭代后设置为将触发 switch 语句开始的值这是第一个案例。
所以在您的情况下,这意味着交换 switch
和 do...while()
并添加 default
情况和控制变量:
var where = len % 3;
do
switch (where)
default: dst += ',';
case 0: dst += src[i++];
case 2: dst += src[i++];
case 1: dst += src[i++];
where = -1;
while (src[i]);
一般来说,这种方法的一个巨大缺点当然是它不能跨回调工作,回调在 JavaScript 中几乎无处不在。 不过,只要在单个顺序上下文中使用它,它就可以工作。
有关详细信息,请参阅the ticket posted on the asm.js repo。
【讨论】:
对不起,我不明白:it will not work across callbacks
,这是什么意思?
@AlterMann 基本上它不会跨函数工作。在 JavaScript 中,传递函数对象作为对未来值或事件做出反应的一种方式是很常见的,例如等待 100 毫秒:window.setTimeout(function() /* */ , 100);
。如果这样的函数在循环内declared,它可能会给人留下循环内run的印象(因此能够使用break
、continue
等),但如果异步执行则不是这样。只需谷歌“javascript return not working”,你就会发现很多新手问题都在问这个问题,只是用返回值代替。【参考方案2】:
JavaScript switch
语句不能这样工作。
switch (expr)
case expr:
statements;
break;
case expr:
statements;
break;
default:
statements;
break;
但 JavaScript 确实提供 labels 来控制你的循环
来自 MDN 的示例
var itemsPassed = 0;
var i, j;
top:
for (i = 0; i < items.length; i++)
for (j = 0; j < tests.length; j++)
if (!tests[j].pass(items[i]))
continue top;
itemsPassed++;
另一个来自 MDN 的例子
var allPass = true;
var i, j;
top:
for (i = 0; items.length; i++)
for (j = 0; j < tests.length; i++)
if (!tests[j].pass(items[i]))
allPass = false;
break top;
【讨论】:
以上是关于将 duff 的设备从 C 移植到 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章