user5126840
user5126840

Reputation:

Changing parts of a string with '#'

Wanted to see if I'm going in the right direction. I have to change everything but the last four characters of a string into #. I've got two ideas so far.

First one:

def maskify(cc):
   cc = raw_input("Enter passcode: ")
   n = len(cc)
   cc.replace(cc[0:n-4], #)  # this one gives me the unexpected EOF while parsing error

Second one (I think this one's closer because it supposedly needs an algorithm):

def maskify(cc):
   cc = raw_input("Enter passcode: ")  
   n = len(cc)
   for i in range (0, n-4):  # i think a for loop would be good but i don't know how i'm going to use it yet
      cc.replace(                  #not entirely sure what to put here
   pass                           

Upvotes: 1

Views: 3084

Answers (9)

user3352995
user3352995

Reputation: 1

# return masked string
def maskify(cc):

    maskify = cc
    maskifyL= len(maskify) - 4

    char = ""
    a=0

    if maskifyL <= 2:
       c2 = cc
    else:
        for a in range(maskifyL):
            char += "#"
            a += 1
        c2 = maskify.replace(maskify[:maskifyL], char, maskifyL)

    return c2

Upvotes: 0

liushuaikobe
liushuaikobe

Reputation: 2190

cc = raw_input("Enter passcode: ")
cc = ''.join(('#' * (len(cc) - 4), cc[-4:]))

Upvotes: 3

BattleDrum
BattleDrum

Reputation: 818

First of all strings are immutable(they can't be changed) once created--so you can't change the value of cc with replace(). To change all parts of the string except the last four, do this:

def doso(text):
  assert len(str(text))>4, 'Length of text should be >4'
  ctext=str(text).replace(str(text)[:(len(str(text))-4)],'#'*(len(str(text))-4)) 
  print(ctext)

>>>doso(123) prints 'Length of text should be >4' because len(text)== 3 which is what we expect

Hovever,

 >>>doso(12345678) prints #####6789 which is exactly what we expect

Note: Doing '#' * (len(str(text))-4)) accounts for the number of characters we want to replace

Upvotes: 0

reynoldsnlp
reynoldsnlp

Reputation: 1210

How about the following?

def maskify() :
    cc = input("Enter passcode: ")
    mask = '#'*(len(cc)-4)
    return mask + cc[-4:]

I'm not sure how the flow of the rest of your program works, but I doubt whether you should be prompting for raw_input inside of this function. You can decide that depending on your needs. The alternative would look something like this:

def maskify(cc) :
    return '#'*(len(cc)-4) + cc[-4:]

myInput = input("Enter passcode: ")
maskedInput = maskify( myInput )
  • NB: python2 uses raw_input instead of input

Upvotes: 2

Martin Evans
Martin Evans

Reputation: 46759

The following solution makes the assumption that this would have a security type use, as such passcodes of 4 or fewer characters should just be hashed, otherwise someone would know the whole passcode.

def maskify(cc):
    if len(cc) < 9:
        split = [0,1,2,3,4,4,4,4,4][len(cc)]
    else:
        split = len(cc) - 4

    return "#" * split + cc[split:]

for length in range(1,12):
    test = string.lowercase[:length]
    print "%s > %s" % (test, maskify(test))

Giving the following results:

a > #
ab > ##
abc > ###
abcd > ####
abcde > ####e
abcdef > ####ef
abcdefg > ####efg
abcdefgh > ####efgh
abcdefghi > #####fghi
abcdefghij > ######ghij
abcdefghijk > #######hijk

If the short hash is not required, then simply change the array as follows to get the other results:

def maskify(cc):
    if len(cc) < 9:
        split = [0,0,0,0,0,1,2,3,4][len(cc)]
    else:
        split = len(cc) - 4

    return "#" * split + cc[split:]

Giving:

a > a
ab > ab
abc > abc
abcd > abcd
abcde > #bcde
abcdef > ##cdef
abcdefg > ###defg
abcdefgh > ####efgh
abcdefghi > #####fghi
abcdefghij > ######ghij
abcdefghijk > #######hijk

Upvotes: 1

PM 2Ring
PM 2Ring

Reputation: 55469

As others have mentioned # starts a comment. If you want a string containing a hash you need to do '#'.

As André Laszlo mentioned, Python strings are immutable, so it's impossible for a string operation to change a string's content. Thus the str.replace() method can't change the original string: it needs to create a new string which is a modified version of the original string.

So if you do

cc = 'cat'
cc.replace('c', 'b')

then Python would create a new string containing 'bat' which would get thrown away because you're not saving it anywhere.

Instead, you need to do something like

cc = 'cat'
cc = cc.replace('c', 'b')

This discards the original string object 'cat' that was bound to the name cc and binds the new string 'bat' to it.


The best approach (AFAIK) to solving your problem is given in bebop's answer. Here's a slightly modified version of bebop's code, showing that it handles short strings (including the empty string) correctly.

def maskify(s) :
    return '#' * (len(s) - 4) + s[-4:]

alpha = 'abcdefghij'
data = [alpha[:i] for i in range(len(alpha)+1)]

for s in data:
    print((s, maskify(s)))

output

('', '')
('a', 'a')
('ab', 'ab')
('abc', 'abc')
('abcd', 'abcd')
('abcde', '#bcde')
('abcdef', '##cdef')
('abcdefg', '###defg')
('abcdefgh', '####efgh')
('abcdefghi', '#####fghi')
('abcdefghij', '######ghij')

Upvotes: 0

Navneet
Navneet

Reputation: 4813

The string literal '#' is not the same as the character # which starts an inline comment.

def maskify(cc):
   cc = raw_input("Enter passcode: ")  
   mask = '#'*(len(cc)-4)
   return mask + cc[-4:]

Upvotes: 0

The6thSense
The6thSense

Reputation: 8335

Just a little change to your own code:

cc = raw_input("Enter passcode: ")  
n = len(cc)
c=""
for i in range(0, n-4):  # i think a for loop would be good but i don't know how i'm going to use it yet
    c+="#"               #not entirely sure what to put here
cc= c+cc [-4:]
print cc

output:

Enter passcode: kased
#ased

Upvotes: 0

Andr&#233; Laszlo
Andr&#233; Laszlo

Reputation: 15537

The problem in the first example is that the # is unquoted. You need to change it to '#' otherwise it is parsed as the start of a comment and the enclosing parenthesis is a part of that comment. Although, this will only fix the parsing error.

The problem with strings is that you can't change characters inside of them (they are immutable). A common way to get around this is to create an array of the string, change the characters you want to change and then convert the array back to a string (often using ''.join(character_array)). Try that!

Upvotes: 1

Related Questions