Reputation: 231
I am trying to create a program that asks a user for input "name" and checks to make sure that the name is alphabetic, not too long, and not in a file called Unacceptable_Names (that contains inappropriate names)
To make sure that each user of the program doesn't use the same name, when a player enters a name I append it to Unacceptable_Names, then when the next player plays it should give them an error if they enter a name in this file.
The code below works for the words already created in the file, but when I replay and enter the same name I do not get an error. Can someone help troubleshoot why the name is not being checked?
def Char_Name(self,name):
string1=str(name).lower()
unacceptable_names=open("C://Users//Documents//Unacceptable_Names.txt", "r")
unacceptable_names2=open("C://Users//Documents//Unacceptable_Names.txt", "a")
names_list= []
for line in unacceptable_names.readlines():
for i in line.split(","):
names_list.append(i.strip())
if name.isalpha()==False:
print("You entered a name containing non-alphabetic characters, pease reenter a new name:")
main()
elif len(name)>=10:
print("You entered a name containing 10 or more characters, pease reenter a new name:")
main()
elif string1 in names_list:
print("You entered a name containing bad words or a name already in use! Try again.")
main()
else:
unacceptable_names2.write("\n"+str(name)+",")
unacceptable_names2.close()
self.character_name=name
This is what unacceptable_names looks like after entering a name "Emily": [along with some other bad words in the file before it- all of which if entered give me an error]
wrinkled starfish, xx, xxx, yaoi, yellow showers, yiffy, zoophilia, Emily,
However, if I manually go into the text file and write "Emily" exactly how it is above, it will give me the error message that I need.
Upvotes: 1
Views: 192
Reputation: 180391
You should write each name on separate lines and you won't need to aplit at all, make a set of the names when you open the file and use a+ to open once for reading and appending:
def Char_Name(self,name):
string1 = name.lower()
with open("C://Users//Documents//Unacceptable_Names.txt", "a+") as f:
unacceptable_names = set(line.rstrip() for line in f)
if not name.isalpha():
print("You entered a name containing non-alphabetic characters, please re-enter a new name:")
main()
elif len(name) >= 10:
print("You entered a name containing 10 or more characters, please re-enter a new name:")
main()
elif string1 in unacceptable_names:
print("You entered a name containing bad words or a name already in use! Try again.")
main()
f.write("{}\n".format(name))
self.character_name = name
It might be a better idea to use pickle to store a set of names.
I would also use a while loop asking the user for their name in the loop instead of repeatedly calling main.
def Char_Name(self):
with open("C://Users//Documents//Unacceptable_Names.txt", "a+") as f:
unacceptable_names = set(line.rstrip() for line in f)
while True:
name = input("Please enter your username")
_name = name.lower()
if _name in unacceptable_names:
print("You entered a name containing bad words or a name already in use! Try again.")
elif _name.isalpha():
print("You entered a name containing non-alphabetic characters, please re-enter a new name:")
elif len(name) >= 10:
print("You entered a name containing 10 or more characters, please re-enter a new name:")
else:
break
f.write("{}\n".format(name))
self.character_name = name
There is no need to ever use readlines unless you actually want a list, if you are going to build a container of names then a set is the most efficient way to check for membership.
Upvotes: 0
Reputation: 43
You should also make sure to exact match names. If you simply match in python, it can confuse one name to be other. Example,there are two users with similar user names example: 1) Megan 2) Megan2015. In a simple match case: if you search for Megan, python may find Megan2015 and say it has found it, since "Megan" in "Megan2015"
def exact_match(phrase, word):
import re
b = r'(\s|^|$)'
res = re.match(b + word + b, phrase, flags=re.IGNORECASE)
return bool(res) # returns true or false
def Char_Name(self,name):
string1=str(name).lower()
unacceptable_names=open("C://Users//Documents//Unacceptable_Names.txt", "r")
unacceptable_names2=open("C://Users//Documents//Unacceptable_Names.txt","a")
names_list= []
for line in unacceptable_names.readlines():
for i in line.split(","):
names_list.append(i)
if name.isalpha()==False:
print("You entered a name containing non-alphabetic characters, please reenter a new name:")
main()
elif len(name)>=10:
print("You entered a name containing 10 or more characters, pease reenter a new name:")
main()
elif:
for n in range(0,len(names_list)):
if exact_match(string1, names_list[n]) == True:
print("You entered a name containing bad words or a name already in use! Try again.")
main()
else:
unacceptable_names2.write(str(name + " , ") )
unacceptable_names2.close()
self.character_name=name
Upvotes: 0
Reputation: 16134
This line unacceptable_names2.write(name)
appends names to the same line.
You should each name with a ,
after each name. Only then will
for line in unacceptable_names.readlines():
for i in line.split(","):
names_list.append(i.strip())`
work.
Current file content after unacceptable_names2.write(name)
:
helloonetwothree
What you want it to be:
hello,one,two,three
Updated code:
def Char_Name(self,name):
string1=str(name).lower()
unacceptable_names=open("C://Users//Documents//Unacceptable_Names.txt", "r")
unacceptable_names2=open("C://Users//Documents//Unacceptable_Names.txt", "a")
names_list= []
for line in unacceptable_names.readlines():
for i in line.split(","):
names_list.append(i.strip())
if name.isalpha()==False:
print("You entered a name containing non-alphabetic characters, pease reenter a new name:")
main()
elif len(name)>=10:
print("You entered a name containing 10 or more characters, pease reenter a new name:")
main()
elif string1 in names_list:
print("You entered a name containing bad words or a name already in use! Try again.")
main()
else:
unacceptable_names2.write(name+',')
unacceptable_names2.close()
self.character_name=name
Update:
Add i.strip()
to the code above.
You are somehow adding a whitespace to the beginning of each name.
So when you search for yiffy
it is not able to find the match. Because it is stored as yiffy
instead.
In [54]: 'wrinkled starfish, xx, xxx, yaoi, yellow showers, yiffy, zoophilia, Emily,'.split(','
....: )
Out[54]:
['wrinkled starfish',
' xx',
' xxx',
' yaoi',
' yellow showers',
' yiffy',
' zoophilia',
' Emily',
'']
Upvotes: 1
Reputation: 1125
def Char_Name(self,name):
string1=str(name).lower()
unacceptable_names=open("C://Users//Documents//Unacceptable_Names.txt", "r")
unacceptable_names2=open("C://Users//Documents//Unacceptable_Names.txt", "a")
names_list= []
for line in unacceptable_names.readlines():
for i in line.split(","):
names_list.append(i)
if name.isalpha()==False:
print("You entered a name containing non-alphabetic characters, pease reenter a new name:")
main()
elif len(name)>=10:
print("You entered a name containing 10 or more characters, pease reenter a new name:")
main()
elif string1 in names_list:
print("You entered a name containing bad words or a name already in use! Try again.")
main()
else:
unacceptable_names2.write(',' + str(name) ) # <-------
unacceptable_names2.close()
self.character_name=name
or you can change last else
into:
else:
unacceptable_names2.write('\n' + str(name) + '\n')
unacceptable_names2.close()
self.character_name=name
Upvotes: 0