C++ 使用名称中包含值的其他人的库
所以,我正在使用Arduino的库,我遇到了一个问题。有一块他们的代码,在其中他们从变量名(或对象?或其他?)中提取一个值。我读过关于在这里有变量名的值(堆栈溢出),我知道你不应该这样做,但我被卡住了 我不是一个能够修改代码的优秀程序员,但我仍然想使用它(金星盾非常酷)。下面是一个使用他们的C++ 使用名称中包含值的其他人的库,c++,c,arduino,C++,C,Arduino,所以,我正在使用Arduino的库,我遇到了一个问题。有一块他们的代码,在其中他们从变量名(或对象?或其他?)中提取一个值。我读过关于在这里有变量名的值(堆栈溢出),我知道你不应该这样做,但我被卡住了 我不是一个能够修改代码的优秀程序员,但我仍然想使用它(金星盾非常酷)。下面是一个使用他们的s->setEnvelope的示例: s->setEnvelope (OSC_1, AT_100MS, 1.0f, DR_100MS, 1.0f, DR_100MS, 0.0f); 我想随机更改这些值
s->setEnvelope
的示例:
s->setEnvelope (OSC_1, AT_100MS, 1.0f, DR_100MS, 1.0f, DR_100MS, 0.0f);
我想随机更改这些值,所以我做了以下操作:
String adsrMake(String type, int attack){
return type + attack + "MS";
}
然后我做这个:
s->setEnvelope (OSC_1, adsrMake("AT_",time/2), etc..
但它不喜欢这样。它不需要字符串,它需要一个名称(?)或其他东西。我得到的错误表明它想要:
void GinSingSynth::setEnvelope(GSSynthOsc, GSAttackDur, float, GSDecRelDur, float, GSDecRelDur, float)
我打开了.cpp
文件,它说它在另一端执行此操作:
void GinSingSynth::setEnvelope (GSSynthOsc oscIdx ,
GSAttackDur attackDur , float attackAmp,
GSDecRelDur decayDur , float decayAmp ,
GSDecRelDur releaseDur, float releaseAmp )
{
ubyte voiceIdx = OscIdxToVoiceIdx(oscIdx);
// Construct ADR bytes ( high four bits amplitude, low four bits duration )
ubyte atkByte = ( (ubyte) ( 0x0f * attackAmp ) << 4 ) + attackDur;
ubyte dcyByte = ( (ubyte) ( 0x0f * decayAmp ) << 4 ) + decayDur;
ubyte rlsByte = ( (ubyte) ( 0x0f * releaseAmp ) << 4 ) + releaseDur;
void GinSingSynth::setEnvelope(GSSynthOsc oscIdx,
GSAttackDur attackDur,float attackAmp,
GSDecRelDur decayDur,浮子decayAmp,
GSDecRelDur releaseDur,float releaseAmp)
{
ubyte voiceIdx=OscIdxToVoiceIdx(oscIdx);
//构造ADR字节(高四位振幅,低四位持续时间)
ubyte-atkByte=((ubyte)(0x0f*attackAmp)很可能GSAttackDur
代表某种整数类型。它可能是一个枚举,因此您必须查找定义并查看可接受的值。例如AT_100MS
可能代表整数值
这意味着您可以通过如下方式传递整数来更改值:
s->setEnvelope (OSC_1, GsAttackDur(42), 1.0f, DR_100MS, 1.0f, DR_100MS, 0.0f);
^ random
但是,必须检查有效值的范围是否为。非常重要的是,不要传递不在可接受范围内的枚举值。很遗憾,GsAttackDur(n)
将接受任何n
,而不考虑其是否有效。这意味着您必须知道有效范围,并在此范围内生成一个数字n
。最近出现了一个您应该检查的问题。请记住,随机枚举生成将始终与枚举定义相耦合。如果后者发生更改,您可以将不得不修改前者
将它们的头文件添加到/source
使函数返回其结构类型或#def
GSAttackDur adsrMake(字符串类型,int攻击){
....
}
虽然您知道GSAttackDur
枚举成员是连续的数值,但依靠第三方库(甚至您自己的库)的内部信息来推断向枚举强制转换整数是有效的或安全的并不是最佳做法
在一般情况下,或在代码维护下,值是连续的,甚至是算术级数,这可能并不总是正确的。更好的一般解决方案是使用查找表将随机整数转换为有效的枚举类型值,因此不需要知道实际枚举文字值的大小或顺序:
GSAttackDur getRandomDuration()
{
static const GSAttackDur lookup[]
{
AT_2MS, AT_8MS, AT_16MS, AT_24MS, AT_38MS,
AT_56MS, AT_68MS, AT_80MS, AT_100MS // add more as necessary
} ;
// Get random index into lookup - 0 to N-1 where N is the number
// of elements in lookup.
int r = rand() / (RAND_MAX / (sizeof(lookup) / sizeof(*lookup)) ) ;
// Return a random GSAttackDur value
return lookup[r] ;
}
好的,太棒了。我发现了://GSAttackDur-ADSR攻击持续时间(持续时间被量化为这些值,以毫秒为单位)enum GSAttackDur{AT_2MS=0x00,AT_8MS=0x01,AT_16MS=0x02,AT_24MS=0x03,AT_38MS=0x04,AT_56MS=0x05,AT_68MS=0x06,AT_80MS=0x07,…等等
但我仍然不确定如何处理它。当我在代码中使用s->setEnvelope时,如何交换数字?我必须将字符串转换为其他内容吗?或者…对不起,我仍然不知道我理解。谢谢你这么快回答thought@gregdebicki您根本不应该使用字符串。只需传递与枚举值之一对应的整数。使用此选项时,我会得到“从'int'到'GSAttackDur'的无效转换”(OSC_1,42,1.0f,DR_100MS,1.0f,99,0.0f)^random^random
如果我选择(像这样^),它会告诉我在_100MS“未在此范围内声明”@juanchopanza:建议传递整数值似乎不是个好主意。您无法知道某些意外整数值将如何解释。在这种情况下,整数值与语义之间的映射完全是任意的。此函数接受enum
参数;您应该只传递一个defnedenum
constants.@jamesdlin完全正确。我在回答中添加了一些说明,以及一个相关问题的链接。