Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

c - Can someone please explain this line

K_count = (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0]) ? ++K_count : 1);

It is a part of this simple code, and i cant understand how precisely does it work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

this basically increments through the available options on a standard US telephone keypad for the "3" key, looping back to the first option after the last is reached. it does so by referencing a 3-dimensional array containing the options for each key layed out as row/column/options. it is written in such a way that it can be reused for other keys with minor modifications.

the "...?...:..." construct is basically a shortcut for if/else. so you can rewrite the statement like this:

if (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0])) {
    K_count = ++K_count;
} else {
    K_count = 1;
}

the "++" operator simply adds 1 to the variable, so you can rewrite as:

if (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0])) {
    K_count = K_count + 1;
} else {
    K_count = 1;
}

CharacterMask is a 3-dimensional array that describes a typical telephone keypad. the first 2 dimensionsindicate the row and column of the keypad. the third dimension contains the options available on that key. so, for example, the 3 key on a telephone has 4 options (3,d,e, and f). for some reason, the author also includes the option count as the first item in the array (index 0). so CharacterMask[0][2] would give you an array containing the number 4 followed by the characters '3','d','e', and 'f'. as such, CharacterMask[0][2][0] will return the number 4. similarly CharacterMask[0][2][1] would return the char '3'. since this line of code is only really concerned with the number of options, not their values, the final array index is hard-coded to 0. given that, you can rewrite the code like this to clarify:

rowIndex = 0;
columnIndex = (customKey - '0') - 1;
optionCountIndex = 0;
if (K_count < (byte)(CharacterMask[rowIndex][columnIndex][optionCountIndex])) {
    K_count = K_count + 1;
} else {
    K_count = 1;
}

since customKey is a char and not a number, we can use the "-" operator to subtract the '0' char. this implicitly casts both values to a byte and returns the difference between those bytes. since the numbers are ordered 0-9 in most character sets, this effectively gets us the numerical value of the character stored in the customKey variable (e.g. char 3 becomes byte 3). so the code can be rewritten as follows:

rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
if (K_count < (byte)(CharacterMask[rowIndex][columnIndex][optionCountIndex])) {
    K_count = K_count + 1;
} else {
    K_count = 1;
}

since they keys 1,2,3 are found in columns 0,1,2 in a zero-based indexed column count, we need to subtract 1 from the keyNumber to get the column index as shown above

because CharacterMask is a char array, we need to cast the first value to a byte to get the value initially entered back. this rewrite clarifies that:

rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
optionCountAsCharType = (CharacterMask[rowIndex][columnIndex][optionCountIndex]);
if (K_count < (byte)optionCountAsCharType) {
    K_count = K_count + 1;
} else {
    K_count = 1;
}

the comparison with K_count relies on the fact that the option array length is equal to the option count plus 1. since it is zero-based indexed, that means the last index is equal to the option count. so as long as the current K_count (aka option index) is less than the option count, you can still add 1 without exceeding the max index value. but if you are on the last index, you must roll back to 1 (the index of the first option). it could be made more clear with one more refactor:

rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
optionCountAsCharType = (CharacterMask[rowIndex][columnIndex][optionCountIndex]);
nextIndexIsInsideArrayBounds = K_count < (byte)optionCountAsCharType
if (nextIndexIsInsideArrayBounds) {
    K_count = K_count + 1;
} else {
    K_count = 1;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...