1

So I have the following chunk of code in python which basically opens a text file, makes an array out of the file's text contents (splitting it line by line) and then proceeds to take input from a user and compare that input to each of the terms in the array. Despite the fact that a usersubmitted string is in the array, exactly as it was typed, the program is unable to tell that the two strings are equal. How do I compare the strings? And if this notation is correct, what could possibly be the cause of inequality? I tried substituting "is" for "==" but that didn't work either.

both the input for userinput is frogeyedpeas and UserArray[0] is frogeyedpeas

The file Usernames.txt

frogeyedpeas
vsauce

(there is an additional line that is entirely blank after vsauce)

Code posted below:

Usernames = open('Usernames.txt', 'r+')
UserArray = Usernames.read().split("\n")

userinput = raw_input("Enter Username: ")
passinput = raw_input("Enter Password: ")
i = 0
q = len(UserArray)
while(i < q):
    founduser = 0
    print userinput, UserArray[i], UserArray #out

    if(UserArray[i] == userinput):
        founduser = 1
        if(PassArray[i] == passinput):
            userstatus = i
            founduser = 2
    i = i + 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sidharth Ghoshal
  • 658
  • 9
  • 31
  • Edit the post and add the contents of 'Usernames.txt' – Sam Tubb Oct 15 '13 at 18:01
  • 1
    What does `print repr(userinput), repr(UserArray[i])` print? – Martijn Pieters Oct 15 '13 at 18:02
  • 2
    `UserArray[i] is userinput`, [Learn about `is` operator first](http://stackoverflow.com/questions/2438667/what-is-the-semantics-of-is-operator-in-python). – Ashwini Chaudhary Oct 15 '13 at 18:02
  • why don't you print out both variables and see what's up? – Marco Scannadinari Oct 15 '13 at 18:02
  • This would be much more readable, and robust, with a `for` loop instead of a `while` loop. Ideally over either `enumerate(UserArray)`, or `zip(UserArray, PassArray)`. – abarnert Oct 15 '13 at 18:03
  • There may be some trailing things in your user arrray, which make comparison fail. Try calling .strip() on each UserArray[i]. You can compare strings by using == – kren470 Oct 15 '13 at 18:03
  • Also, using names like `q` for the length of some array doesn't exactly help readability. While we're at it, get rid of the extra parens around your conditions. And if you want to read a file line by line, just do `for line in Usernames:` or `UserArray = list(Usernames)`; don't use `.read.split("\n")`, especially if you want this to work the same way on Windows and POSIX. – abarnert Oct 15 '13 at 18:04
  • @MartijnPieters the print resulted in: 'frogeyedpeas' 'frogeyedpeas' 'frogeyedpeas' 'vsauce' 'frogeyedpeas' '' – Sidharth Ghoshal Oct 15 '13 at 18:07
  • @frogeyedpeas: you may want to [edit] your question to show us what the output is; comments are not suitable to show the exact output. – Martijn Pieters Oct 15 '13 at 18:11

5 Answers5

4

You are testing for object identity:

UserArray[i] is userinput:

you really want to use equality instead:

UserArray[i] == userinput:

is tests if two object references are pointing to the same object. == tests if the values of two objects is equivalent.

Two strings that have the same contents (are equal), are not necessarily one and the same object:

>>> spam = 'foo bar baz'
>>> ham = 'foo bar baz'
>>> spam is ham
False
>>> spam == ham
True
>>> eggs = ham
>>> eggs is ham
True

CPython does use some tricks to save memory and improve performance, where small integers and some strings are interned; every time you try to create a new string or integer that is interned, instead of a new object, you get an already cached value. In those cases is tests return True only because you indeed have the same object, reused for you by the interpreter.

Note that the equality test can still be incorrect. There could be extra whitespace around the values, or other characters that are not immediately obvious when printed to the screen:

>>> val1 = 'frogeyedpeas'
>>> val2 = 'frogeyedpeas\t'
>>> val1 == val2
False
>>> print val1, val2
frogeyedpeas frogeyedpeas
>>> print repr(val1), repr(val2)
'frogeyedpeas' 'frogeyedpeas\t'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

Try:

UserArray[i].strip(' \n') == userinput.strip(' \n')

As your input methods are different and you may have trailing spaces and or newlines in one and not the other.

Steve Barnes
  • 27,618
  • 6
  • 63
  • 73
2

Well, are you trying to break out of the loop if founduser is equal to 1 in order to test that it works? That chunk of code has founduser resetting each time it runs the code inside the while loop. Maybe say while(i < q and founduser != 1) as the loop header?

1

This should suffice:

#What to look for.
x=raw_input("Test for: ")

#Read and split list.
f=open('usernames.txt','r')
y=f.read()
y=y.split(',')
f.close()

#Test if the input is in list.
#If it is, tell what the match is.
for user in y:
    if str(x)==str(user):
        print x+'='+user

And the format for 'username.txt' goes as so:

vsauce,frogeyedpeas

Let me know how it goes.

Sam Tubb
  • 945
  • 3
  • 19
  • 40
1

After copying the code, creating a new text file with the word "frogeyedpeas", and using == instead of is, the code does seem to work. To clean it up, you might want to use a for loop and zip the two arrays together, like this:

for name, password in zip(UserArray, PassArray):
    print userinput, name, UserArray        

    if name == userinput:
        founduser = 1

    if password == passinput:
        userstatus = UserArray.index(name)
        founduser = 2
Impossibility
  • 954
  • 7
  • 20