Shifting letters by two positions. What's wrong with the code?

조회 수: 5 (최근 30일)
GEORGIOS BEKAS
GEORGIOS BEKAS 2018년 2월 11일
댓글: Walter Roberson 2018년 2월 11일
I am trying to shift each letter of a given word by two positions.
alphab='abcdefghijklmnopqrstwxyz'
inStr = 'doug';
rot=2
b=''
for i=1:length(inStr)
a = find(inStr(i)==alphab)
a = (inStr(i)+rot)
if abs(a)>26
a = rem(a,26);
end
A = alphab(a)
b = strcat(b,A);
end
  댓글 수: 1
Stephen23
Stephen23 2018년 2월 11일
편집: Stephen23 2018년 2월 11일
Simpler, and less liable to mistakes:
alphab = 'a':'z'
This line does nothing because its output is ignored:
a = find(inStr(i)==alphab)

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2018년 2월 11일
편집: Stephen23 2018년 2월 11일
Your basic mistake is that you assumed that the character code for 'a' is 1, and so on, which it is not. In fact 'a' has character code 97, 'b' has 98, etc. Lets have a look:
a = inStr(i)+rot
For example, given the letter 'c' the above line will produce a value of 99+2=101, whereas you assumed that it would produce the value 3, as this is clearly your assumption on the next few lines:
if abs(a)>26
a = rem(a,26);
end
Actually all alphabetic characters have character code >26 (indeed all printable characters do), so this IF statement will always be true for alphabetic characters (upper or lowercase). If we take our example character 'c' + 2 = 101 then rem(101,26) gives 23, which is essentially a random number because there is no mathematical significance in the values of the character codes (i.e. absolute locations of characters in the tables), and certainly not in the remainder 26 of them. The only relevant information contained in the code table is the relative position of a character, but not its absolute position.
You then use this meaningless value as an index into alphab, which is a good idea, but you will need to take into account that MATLAB uses one-based indexing!
The output B is also not preallocated, which it could be quite simply.
So to fix these you first need to take into account the relative position of the character's character code, which you can do very simply by subtracting 'a' from it. Then apply mod (not rem as you can thus avoid the if statement), add one, and use that as the index:
inp = 'abcdwxyz';
rot = 2;
vec = 'a':'z';
out = inp; % preallocate!
for k = 1:numel(inp) % use NUMEL not LENGTH
tmp = inp(k)-'a'+rot; % -'a' to get relative position
out(k) = vec(1+rem(tmp,26)); % +1 for indexing
end
giving
>> out
out =
cdefyzab
However this is MATLAB, so actually no loop is required:
>> inp = 'abcdwxyz';
>> rot = 2;
>> char(mod(inp-'a'+rot,'z'-'a'+1)+'a')
ans =
cdefyzab
  댓글 수: 2
GEORGIOS BEKAS
GEORGIOS BEKAS 2018년 2월 11일
can you explain that?
Walter Roberson
Walter Roberson 2018년 2월 11일
The codes for the digits start from 0x30 (decimal 48). The hexadecimal alignment was deliberate. Space and special characters were put before the digits and letters for sorting reasons.
https://en.m.wikipedia.org/wiki/ASCII

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Walter Roberson
Walter Roberson 2018년 2월 11일
Hint: you can use the second output of ismember to give the index of the individual characters in the alphab .
Hint: a useful way to calculate wraparound is 1 + mod(value-1,base) . 26-1, mod 26 is 25, 25 + 1 is 26. 27-1, mod 26, is 0, 0 + 1 is 1.

태그

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by