0

So i have a text file named words.txt and it contains 3 words:

apple
ship
door

And what I want to do is to ask the user to input a word and then search the file to see whether there is such word and if not add it:

def search(word):
    file = open("words.txt", "r+")

    for line in file:
        if line == word:
            return False

    file.write(word + "\n")
    return True

And then I use the function to check and print the result, but the problem is that when I input the word ship or any other word that's in the list it supposedly says that it's not there which it is.

Aliann
  • 15
  • 4
  • As one of the answers says, you've failed to define what the expected return values are. As written, you return False in case of a match, True in case of a non-match (but the file has been updated). This doesn't seem to be what you are expecting. Start by writing a docstring which describes the outcomes, then you can check if the code implements those (preferably by writing a testcase :) ) – Mats Wichmann Nov 25 '19 at 18:02
  • There are two ways this could be wrong: 1) it fails to return `False` because you are comparing `"ship"` and `"ship\n"`, rather than `"ship"` and `"ship"`, or 2) it fails to return `True` when `"ship"` is compared to `"ship"`. To be clear, it is *definitely* a problem that you aren't acknowledging that `line` will end with a newline, but you may also have your return values swapped. – chepner Nov 25 '19 at 18:15

2 Answers2

2

When iterating over a text file, the line terminator \n is retained in the loop index. You need to remove that before your comparison:

def search(word):
    file = open("words.txt", "r+")

    for line in file:
        if line.rstrip('\n') == word:
            return False

    file.write(word + "\n")
    return True

If any leading and trailing whitespace in your file is not significant, you can simplify line.rstrip('\n') to line.strip().

>>> " foo \n".rstrip('\n')
" foo "
>>> " foo \n".strip()
"foo"
chepner
  • 497,756
  • 71
  • 530
  • 681
  • `line.rstrip('\n')` is obviously the only generally correct answer to this, [as we have discussed](https://stackoverflow.com/a/59037427/1170207). Including the `strip()` solution seems pointless. – Jan Christoph Terasa Nov 25 '19 at 17:59
-2

You may have to do line=line[0:-1] The line variable that you have also has the trailing new line character '\n'.

  • The way to solve that is to use `line.strip()`, not just throw away the last character. – Jan Christoph Terasa Nov 25 '19 at 17:45
  • @JanChristophTerasa `line.strip()` would throw away *all* trailing *and* leading whitespace. `line.rstrip('\n')` would be the more idiomatic way to remove *just* the single newline. Since the last character will be, by definition, a newline, the slice would still work. – chepner Nov 25 '19 at 17:47
  • That is true indeed, but in the example code given it should be equivalent. – Jan Christoph Terasa Nov 25 '19 at 17:48
  • 1
    Your suggestion is, at best, equivalent to this answer. In general, it is objectively *worse*. – chepner Nov 25 '19 at 17:49
  • I see your point. But I still consider it bad practice to remove whitespace using indexing, and _in general_ it is a worse idea than using `strip` or `rstrip`, since you'd have to add a conditional in your code. For this question it does not matter (as it does not matter whether `strip` or `rstrip('\n')` is used). – Jan Christoph Terasa Nov 25 '19 at 17:49
  • How is it worse? `" foo \n"[0:-1]` is equivalent to `" foo \n".rstrip('\n')`; `" foo ".strip()` is not. You're arguing over stylistic preferences while suggesting something that is semantically different. – chepner Nov 25 '19 at 17:53
  • of course it's equivalent in the example you give, but in a more generic situation where you might have a line that doesn't have \n at the end its becomes obvious why stripping the last character is not that nice. – Chrisvdberge Nov 25 '19 at 17:55
  • @Chrisvdberge That's beyond the scope of this question: the string in question was read from a file, so *will* end with a newline. Leading/trailing whitespace may or may not be significant, but the slice presented here will preserve it, while `strip()` will not. – chepner Nov 25 '19 at 17:59
  • @JanChristophTerasa The solution I provided works, there is only a terminating new line character here at the end of every line which we need to get rid of, your method will eat up any leading and trailing whitespaces. It is just plain wrong. – Avinash Kumar Pandey Nov 26 '19 at 03:12