0

I have made a program to automatically apply an encryption I have developed. Within one particular bit of code, I keep on getting a "String Index out of range" error.

What does this code do?

The below code creates an array, d. It appends some section of a string to the array. The purpose of the code is to make a rectangle out of the text with width 5, meaning if the original text was "abcdefghijkl", then the idea is to turn this into

a b c d e    
f g h i j     
k l X X X

The last line of the code gives the error "string index out of range" Why? Earlier in the code, as I have forgotten to mention, I add X's to the end of the string so that it devides evenly into 5.

d = []
for x in range(1,length/5+2):
    d.append(string[(x-1)*5:5*x])
d2=str(d).replace('[','').replace(']','').replace("'",'').replace(',','').replace(' ','')
lend2=len(d)
new=''
for i in range(1,lend2):
    new += str([l[i-1] for l in d]).replace('[','').replace(']','').replace("'",'').replace(',','').replace(' ','')

Full error text:

new += str([l[i-1] for l in d]).replace('[','').replace(']','').replace("'",'').replace(',','').replace(' ','') 
IndexError: string index out of range
  • If you need a block of text to be monospaced, the standard solution is to code-format it, even if it's not strictly code. – user2357112 Apr 27 '16 at 21:33
  • 2
    You really should be using `str.join()` instead of sending the `list` to `str()` and replacing all the unwanted characters. – TigerhawkT3 Apr 27 '16 at 21:35
  • It's true that my code is unclean in a few areas, but the primary concern is more about what is causing that error. – DevilApple227 Apr 27 '16 at 21:37
  • 4
    Cleaning up the code can often help you spot errors. – TigerhawkT3 Apr 27 '16 at 21:37
  • Seconding what TigerhawkT3 said. It will make your question easier to answer as well, because the code will become much more readable. It might also be useful to add your assignment to length – Albert Rothman Apr 27 '16 at 21:40
  • I suppose that is true, but the .replace statements are more or less irrelevant to the actual functionality. It's just removing a few characters I don't want in the text. I will edit my code to make it more efficient, but before that, I need to fix this error. – DevilApple227 Apr 27 '16 at 21:40
  • What is the output of putting `print "d[0]=",d[0]` after `new=''`? – AMACB Apr 27 '16 at 21:45
  • Cannot replicate, getting Undefined errors in the very first few lines. Please make this a [mcve]. – Jongware Apr 27 '16 at 21:46
  • 3
    @DevilApple227 `i - 1` is greater than the length of an element of `d` for some `i >=1`, `i < lend2`. Proper variable names would help. – James Buck Apr 27 '16 at 21:46
  • @JamesBuck I'm not quite sure what you mean. Can you explain this as an answer? – DevilApple227 Apr 27 '16 at 21:49
  • It's just the definition of the error: `l[i-1]` is the only place in that line where indexing is taking place, and the error means that `i-1` wasn't a valid index, defined as `range(-len(l), len(l))`. – TigerhawkT3 Apr 27 '16 at 21:53
  • @DevilApple227 There is only one place in the failing line that you are doing anything that would raise an IndexError, and that is `l[i-1]`. This would mean that there can exist strings in `d` that are individually shorter that the full list length. Like `['abcde', 'abcd', 'abc', 'a']` would cause this problem when it got to `a` since the `i` is based on `len(d)`. – sberry Apr 27 '16 at 21:53
  • For what it's worth, I answered a very similar question to this not too long ago: http://stackoverflow.com/questions/36636004/creating-a-dynamic-array-in-python/36636075#36636075 – sberry Apr 27 '16 at 21:53
  • What this really boils down to is you assume `N % M >= N // M` which is try for your example data `12 % 5 == 2 >= 12 // 5 == 2` – sberry Apr 27 '16 at 21:57

2 Answers2

2

I'll post this comment as an answer since I think it summarizes the issue well.

You are making an assumption that

N % M >= N // M

for all values of N and M. While this is true sometimes, it is not true all the time. When it is not true, you get an index error.

In your program, N == len(input string) and M == 5. You are slicing off characters from your input string M characters at a time. So for your sample input: abcdefghijkl you end up with

['abcde', 'fghij', 'kl'] 

When you iterate with

for i in range(1,lend2):

You are ranging, in this case, from 1 to 2. Then you reference the index of the individual list items by subtracting 1, so you reference indexes 0 and 1, and this works. Note that the equation with these values reads

11 % 5 >= 11 // 5
     2 >= 2

which is true.


If you shorten your input string by 1 character you get

['abcde', 'fghij', 'k']

You are still ranging over the same values of i, and you are still trying to access index 0 and 1, but that will fail on the 3rd string since it is only a single character.

Note that in this failing case the equation at the top reads

11 % 5 >= 11 // 5
     1 >= 2

which is not true.

sberry
  • 128,281
  • 18
  • 138
  • 165
  • Ah, actually, I have just realized that I left out a very important piece in my code that I have in my source. In my source, I add X to the string so that it decides evenly into 5. so abcdef would become A B C D E \n F X X X X – DevilApple227 Apr 28 '16 at 02:51
0

I think you're trying to do 'string'[i][j] internally. Although you're code is barely readable, that's what I gathered from a close inspection.

You can't get n-th element of a letter, only the first.

'string'[0][0] == 's'
'string'[0][1] == string index out of range

a = 'asd'
for i in range(1, len(a)):
    [l[i-1] for l in a] # During the first loop, l == 'a'
                        # You're trying to grab l[i-1] that doesn't exist
wanaryytel
  • 3,352
  • 2
  • 18
  • 26