当满足某些条件时,如何让这个 for 循环正常工作以替换文件中的一行?

How can I get this for loop to work correctly to replace a line in a file when certain conditions are met?

我正在寻找一个图书馆类型的程序,允许您从一个小的 "database" 文本文件中取出一本书,然后修改文件中的行以包含之前输入的用户 ID表明它已被拍摄。

输入的用户 ID 必须是一个整数和 4 位数字,我已经让程序用 try/except 来解决这个问题,除了现在要继续实际编写文件,它似乎不再 运行 过去要求 book_id 尽管在我放入所有检查 ID 的正确长度之前它是可用的。

此外,这一切都意味着在一个 "def checkout()" 函数中(这样我以后可以正确地创建一个主程序,包括我编写的搜索功能和一个允许你 'return' 书籍的程序)但是如果我试图把它放在里面,我得到的都是缩进错误,每当我试图使用 break 来阻止程序为每本书或每本书重复 "Sorry, either the book ID was not found or the book is unavailable" 时,整个事情都会死掉。在这一点上,我只是在寻找基本的功能,即使它不能完美地工作,所以主要的优先事项是实际获得它 运行ning.

while True:
    txt = open("book_list.txt", "r+")
    try:
         user_id = int((raw_input("Please enter your ID: ")))
         if len(str(user_id)) != 4:
            print "Sorry, that was an invalid ID. Please try again."
            continue
         break
    except:
       print "Sorry, that was an invalid ID. Please try again."

book_id = (raw_input("Please enter the book ID no. you would like to take out: "))

for line in txt:
         if book_id == line[0] and line[-1] == " ":
                txt.write(line.replace(line,user_id))
                print "You have successfully taken out the book."

         else:
                print "Sorry, either the book ID was not found or the book is unavailable."



txt.close()

有问题的文本文件只是:

1 Book_1 Author_1 1234
2 Book_1 Author_1 
3 Book_2 Author_2 
4 Book_3 Author_3 2000
5 Book_4 Author_3 

图书 ID 是左边的数字,用户 ID(或 space“ ”,表示该书可用)是右边的数字。

这可能是我遗漏的一些非常简单的事情,并且已经做了使其无法工作,因为我是初学者,但我感谢任何输入,干杯。

您的代码中有几个问题:

  1. 不要在 while 循环之前打开文件(并适当添加错误检查)

    while True:
        txt = open("book_list.txt", "r+")
    
  2. 如果您写入 r+ 文件,您会将 txt.write 写入的所有行追加到文件末尾。 不要覆盖它们!这意味着在签出一本书后,您将有一个新行 在文件的末尾,这本书被签出。在文件中覆盖更复杂! 基本上有两种解决方案,要么读入整个文件并将其保存在字典中,要么……。然后用 w 重写整个文件。 或者,这有点难看,你在每本书后面放了四个空格,然后使用 txt.seek.

  3. 用用户数覆盖这些空格
  4. 比较book_id == line[0]基本上就是检查line的第一个字符是否等于书的编号,这与检查是否相同该行的第一个数字与您的图书 ID 相同 book_id == int(line[0:line.index(" ")])

  5. 你得到的缩进错误很难检查,但基本上你必须检查你是 IDE 还是 texteditor 是否正确处理空格和制表符 或者如果您不关心缩进是否足够。

首先从 while 循环中删除 open 语句,它会不必要地打开文件。

while True:
    try:
         user_id = int((raw_input("Please enter your ID: ")))
         if len(str(user_id)) != 4:
            print "Sorry, that was an invalid ID. Please try again."
            continue
         break
    except:
       print "Sorry, that was an invalid ID. Please try again."

book_id = (raw_input("Please enter the book ID no. you would like to take out: "))

其次使用 with 语句 while 处理文件,因此您不必跟踪关闭它。 另外,在 "r+" 模式下打开文件会使问题复杂化,因为最后会附加数据,您可以使用 seektell 但它不会做任何事情你也可以更容易地覆盖你的数据,所以我建议你使用一个临时文件

out_txt = open("temp.txt","w")
found = False
with open("book_list.txt", "r") as txt:
    for line in txt:
        if book_id == line[0] and line[-1] == " ":          # are you sure that every line that does not have an user_id associated to it is going to have a " "(space) at the end of it, if not think of some other condition to do this

            line =  line.strip() + " " + str(user_id) + "\n"
            print "You have successfully taken out the book."
            found = True
        out_txt.write(line)

out_txt.close()
if found:
    import os
    os.remove("book_list.txt")
    os.rename(out_txt.name, "book_list.txt")
else:
        print "Sorry, either the book ID was not found or the book is unavailable."

首先,您可以在不使用异常的情况下轻松验证 ID:

def id_valid(id):
    return len(id) == 4 and id.isdigit()

如果字符串中的所有字符都是数字,isdigit() 方法return为真。

然后可以这样读取正确的 ID:

PROMPT = "Please enter your ID: "
user_id = raw_input(PROMPT)
while not id_valid(user_id):
    print "Sorry, that was an invalid ID. Please try again."
    user_id = raw_input(PROMPT)

"Sorry, either the book ID was not found or the book is unavailable." 消息显示了很多次,因为您在每次迭代中打印它,其中 id 不匹配或图书不可用。您可以使用布尔标志来记住是否找到了这本书,并在最后打印一次该消息:

book_found = False
with open("book_list.txt", "r") as txt:
    for line in txt:
        data = line.split();
        if book_id == data[0] and len(data) == 3:
            # modify the file here
            print "You have successfully taken out the book."
            book_found = True

if not book_found:
     print "Sorry, either the book ID was not found or the book is unavailable."

假设每行中的数据条目由空格分隔,您可以使用 split 来分隔 ID。它将 return 一个列表,其中 [0] 元素是图书 ID,[3] 是用户 ID(如果存在)。如果没有用户 ID,列表将只有 3 个元素。

至于更新文件,最简单的策略是在处理原始文件时保存修改后的副本,如果要在最后保存修改,则覆盖它。