Застрял в цикле, можете ли вы помочь? - PullRequest
0 голосов
/ 24 октября 2010

Я сейчас пишу программу, которая читает записи из текстового файла и печатает данные на экране следующим образом:

                       GRADE REPORT

NAME                COURSE                            GRADE
-----------------------------------------------------------
JOE FRITZ           AMERICAN GOVERNMENT                 B
                    CALCULUS I                          A
                    COMPUTER PROGRAMMING                B
                    ENGLISH COMPOSITION                 A
                    Total courses taken = 4

LANE SMITH          FUND. OF DATA PROCESSING            B
                    INTERMEDIATE SWIMMING               A
                    INTRO. TO BUSINESS                  C
                    Total courses taken = 3

JOHN SPITZ          CHOIR                               C
                    COLLEGE STATISTICS                  B
                    ENGLISH LITERATURE                  D
                    INTRO. TO BUSINESS                  B
                    Total courses taken = 4

Total courses taken by all students = 11

Run complete.  Press the Enter key to exit.

Это текстовый файл, из которого он читает:

JOE FRITZ           AMERICAN GOVERNMENT           B
JOE FRITZ           CALCULUS I                    A
JOE FRITZ           COMPUTER PROGRAMMING          B
JOE FRITZ           ENGLISH COMPOSITION           A
LANE SMITH          FUND. OF DATA PROCESSING      B
LANE SMITH          INTERMEDIATE SWIMMING         A
LANE SMITH          INTRO. TO BUSINESS            C
JOHN SPITZ          CHOIR                         C
JOHN SPITZ          COLLEGE STATISTICS            B
JOHN SPITZ          ENGLISH LITERATURE            D
JOHN SPITZ          INTRO. TO BUSINESS            B

Вот мой код:

# VARIABLE DEFINITIONS

name = ""
course = ""
grade = ""
recordCount = 0
eof = False
gradeFile = ""

#-----------------------------------------------------------------------
# CONSTANT DEFINITIONS

#-----------------------------------------------------------------------
# FUNCTION DEFINITIONS

def startUp():
    global gradeFile
    gradeFile = open("grades.txt","r")
    print ("grade report\n").center(60).upper()
    print "name".upper(),"course".rjust(22).upper(),"grade".rjust(32).upper()
    print "-" * 60
    readRecord()

def readRecord():
    global name, course, grade

    studentRecord = gradeFile.readline()
    if studentRecord == "":
        eof = True
    else:
        name = studentRecord[0:20]
        course = studentRecord[20:50]
        grade = studentRecord[50:51]
        eof = False

def processRecords():
    numOfRecs = 0
    while not eof:
        numOfRecs += 1
        printLine()
        readRecord()
    return numOfRecs

def printLine():
    print name, course.rjust(3), grade.rjust(3)

def closeUp():
    gradeFile.close()
    print "\nTotal courses taken by all students = ",recordCount

#-----------------------------------------------------------------------
# PROGRAM'S MAIN LOGIC

startUp()
recordCount = processRecords()
closeUp()

raw_input("\nRun complete. Press the Enter key to exit.")

Результаты просто печатают самую последнюю строку в текстовом файле и зацикливаются. Будем очень благодарны любой помощи. Спасибо за ваше время.

Ответы [ 7 ]

5 голосов
/ 24 октября 2010

Почему бы вам не сделать все это в одной функции -

def processRecords():
    print ("grade report\n").center(60).upper()
    print "name".upper(),"course".rjust(22).upper(),"grade".rjust(32).upper()
    print "-" * 60

    rec_count = 0
    for line in open("grades.txt","r"):
        name   = line[0:20]
        course = line[20:50]
        grade  = line[50:51]
        print name, course.rjust(3), grade.rjust(3)
        rec_count += 1
    return rec_count

Все эти функции сжаты в одной функцииВы, кажется, программируете очень похоже на C-код.Это Питон!

Также старайтесь избегать использования globals, если не требуется.Просто принцип, которому я следую.Очевидно, что в этой ситуации вам не нужно.

4 голосов
/ 24 октября 2010

Вы должны объявить eof как global в readRecord():

def readRecord():
    global eof, name, course, grade

В противном случае изменения, которые вы вносите в eof, когда studentRecord пусто, не сохранятся снаружи *Сфера 1009 *.

3 голосов
/ 24 октября 2010

Вам нужно добавить eof к глобальным переменным в readRecord ():

...
def readRecord():
    global name, course, grade, eof
...

Но ваше решение немного непитонно.Как насчет чего-то более короткого и гибкого:

import re
print ("grade report\n").center(60).upper()
print "name".upper(),"course".rjust(22).upper(),"grade".rjust(32).upper()
print "-" * 60
for line in open("grades.txt"):
    name, course, grade = re.split("   *", line.strip())
    print "%-21s%-34s%-21s" % (name, course, grade)

raw_input("\nRun complete. Press the Enter key to exit.")

Регулярное выражение очень простое и разбивается на несколько пробелов.Если вы используете разделитель как-то еще, то замените регулярное выражение " *" на ваш разделитель.

А вот версия, в которой используются python-диктанты для отслеживания курсов и оценок по студентам (т.е. ваш целевой результат):

import re

print ("grade report\n").center(60).upper()
print "name".upper(),"course".rjust(22).upper(),"grade".rjust(32).upper()
print "-" * 60
grades = {}
total_courses = 0
for line in open("grades.txt"):
    name, course, grade = re.split("   *", line.strip())
    if not grades.get(name): grades[name] = []
    grades[name].append([course, grade])

for name, data in grades.items():
    for course, grade in data:
        print "%-21s%-34s%s" % (name, course, grade)
        name = ""
    print "%-21sTotal courses taken = %d\n" % (" ", len(data))
    total_courses += len(data)

print "Total courses taken by all students = %d" % total_courses

raw_input("\nRun complete. Press the Enter key to exit.")

Кстати, похоже, вам нужно узнать больше о python (и способе программирования на python).Я рекомендую Dive Into Python .IMO - это самый быстрый (и самый интересный) способ достичь скорости в python, если у вас есть некоторый опыт программирования.

3 голосов
/ 24 октября 2010

В этом варианте «eof» необходимо добавить в список глобальных переменных в readRecord ()

В противном случае при его назначении создается новая локальная переменная, которую processRecords () никогда не видит.

2 голосов
/ 25 октября 2010

Вы должны добавить eof в список глобалов в readRecord.

Однако вы сказали любая помощь , так что вот другая версия:

import itertools as it, operator as op
import collections

Record= collections.namedtuple("Record", "name course grade")
grouper= op.itemgetter(0) # or op.attrgetter('name')

def file_reader(fobj_in):
    for line in fobj_in:
        name= line[:20].rstrip()
        course= line[20:50].rstrip()
        grade= line[50:].rstrip()
        yield Record(name, course, grade)

def process(fn_in, fobj_out):
    for name, records in it.groupby(file_reader(fobj_in), grouper):
        out_name= name
        for index, record in enumerate(records, 1):
            fobj_out.write(
                "%-20.19s%-36.35s%s\n" % (out_name, record.course, record.grade)
            )
            out_name= ''
        fobj_out.write("%20sTotal courses taken = %d\n" % ('', index))

if __name__ == "__main__":
    import sys

    with open('so4009899.txt', 'r') as fobj_in:
        process(fobj_in, sys.stdout)
2 голосов
/ 24 октября 2010

Здесь вам не хватает global, в то время как ваш цикл while проверяет глобальную переменную eof, ваша функция readRecord фактически устанавливает переменную local eof.

1 голос
/ 25 октября 2010

Если у вас есть для использования многих функций в целях «структуры», рассмотрите возможность передачи параметров в функции вместо использования глобальных переменных. Вот небольшое изменение, которое иллюстрирует мой смысл.

def startUp():
    print ("grade report\n").center(60).upper()
    print "name".upper(),"course".rjust(22).upper(),"grade".rjust(32).upper()
    print "-" * 60
    processRecords()

def processRecords():
    numOfRecs = 0
    for line in open("grades.txt","r"):
        numOfRecs += 1
        printLine(line)
    return numOfRecs

def printLine(studentRecord):
    name = studentRecord[0:20]
    course = studentRecord[20:50]
    grade = studentRecord[50:51]
    print name, course.rjust(3), grade.rjust(3)

def closeUp(recordCount):
    print "\nTotal courses taken by all students = ",recordCount


startUp()
...