0

i need to convert this function in C to Python:

void myencrypt(char password[],int mkey)
{
    unsigned int i;
    for(i=0;i<strlen(password);++i)
    {
    password[i] = password[i] - mkey;
    }
}

I try this, but fails...

def myencrypt(password, mkey):

    i = 0
    newpass = []

    for i in range(len(password)):
        newpass[i] = ord(password[i]) - mkey;

    return newpass

any help ?

OpenSys
  • 11
  • you may want to look at http://stackoverflow.com/questions/1228299/change-one-character-in-a-string-in-python – Keith Nicholas Feb 14 '13 at 01:21
  • use append. but why convert from c to python in the first palce?. just keep your c code and use cython to wrap – jassinm Feb 14 '13 at 01:29
  • 1
    Is there a reason you're not using `chr` to convert the numbers back to characters? (In C, that isn't necessary, because `'a'` and `97` are the same value. But in Python, just as you need `ord` to turn one into the other, you need `chr` to go the other way.) – abarnert Feb 14 '13 at 01:36

3 Answers3

2

In Python, you can only assign to an index in a list if the list is long enough, otherwise you will get an IndexError. Try the following:

def myencrypt(password, mkey):
    i = 0
    newpass = []
    for i in range(len(password)):
        newpass.append(ord(password[i]) - mkey)
    return newpass

By using newpass.append(), you will just add each new element to the end of the list. As a side note, you can iterate directly over the elements of password which is a bit more concise:

def myencrypt(password, mkey):
    newpass = []
    for x in password:
        newpass.append(ord(x) - mkey)
    return newpass
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • While you're improving the OP's code, get rid of the unnecessary `i = 0`, and maybe explain about the missing `chr`, and it might be worth showing the list comprehension equivalent, which turns 4 lines into 1. – abarnert Feb 14 '13 at 01:35
2

The C code is modifying password in-place. So, the closest equivalent would be:

def myencrypt(password, mkey):
    for i in range(len(password)):
        password[i] = chr(ord(password[i]) - mkey)

That assumes password is a list of characters, rather than a string.

Also, notice that I'm calling chr on the result of each ord(password[i]) - mkey, because otherwise you're replacing each character with a number—for example, myencrypt(['a'], 32) would give you [65] instead of ['A']. (This isn't necessary in C, because 65 and 'A' are the same value in C.)

You're more likely going to want to call this function with a string, and get back a string. You can still use the C-style in-place functionality to do it, just by converting and converting back:

def myencrypt(password, mkey):
    newpass = list(password)
    for i in range(len(newpass)):
        newpass[i] = chr(ord(newpass[i]) - mkey)
    return ''.join(newpass)

However, this isn't a very Pythonic way to do things. A more idiomatic solution would be:

def myencrypt(password, mkey):
    return ''.join(chr(ord(ch) - mkey) for ch in password)

And that brings up a more general point: Except in very trivial cases, trying to "convert C code to Python" directly is a bad idea. Instead, figure out what the C code does, and write new Python code that accomplishes the same task in the best way for Python, rather than in the way the C code did it.

abarnert
  • 354,177
  • 51
  • 601
  • 671
1

First of all, I wouldn't use the word "encrypt" in this function. In modern Python you can use a bytearray object, that is mutable. Then convert to string.

def myobfuscate(password, mkey):
    a = bytearray(password)
    for i, c in enumerate(password):
        a[i] = ord(c) - mkey
    return str(a)


myobfuscate("secret", 10)
# OUT: 'i[Yh[j'

In Python, strings are immutable, they can't be alterend in-place. So you would use a function like this as:

pw = myobfuscate(pw, 10)

Assuming you won't need the original value any more. This replaces the original reference with a new object that the function returns.

Keith
  • 42,110
  • 11
  • 57
  • 76
  • Or `return ''.join(chr(ord(c) - mkey) for c in password)`. – Jon-Eric Feb 14 '13 at 01:32
  • The elements of a `bytearray` are integers, not characters, so that should be `a[i] -= mkey` (or, if you prefer, `a[i] = ord(c) - mkey`). (In 2.7, the `chr` is harmless, even though the documentation says otherwise; in 3.x, it will raise an exception.) – abarnert Feb 14 '13 at 01:33
  • @Jon-Eric: That's really a completely different answer from Keith's. It might be useful as a comment on F.J's answer, because it _is_ equivalent to (and shorter, and probably more Python than) his. – abarnert Feb 14 '13 at 01:34
  • @abarnert Fair enough. – Jon-Eric Feb 14 '13 at 01:36
  • @Jon-Eric Yes, but for those new to Python I try to make the example a little more straightforward. – Keith Feb 14 '13 at 01:50
  • Thank you folks for all answers, but i use a hex key like this: print myencrypt("mything",0xFABBCA09333) The solutions posted help me allot but have error when i use a hex key – OpenSys Feb 14 '13 at 08:16