質問: こんにちは。Pythonのファイルについての質問です。学校の課題でどうしても分からずにに困っております。。。 やりたいことは、 1、使用者にファイル名を聞く 2、そのファイルがなければそこで終了 3、もしそのファイルがあれば使用者に行を聞く 4、もし行がなければそこで終了 5、もしインプットしたデータ(行)が正しければそのインプットされた行から100行を新しいファイルに入力する。その時に単語の数も一緒にカウントする。 英語ではこのように書かれております。 Ask user to type the name of the file text. If the file does not exist, print a message and finish. If the file exist, ask for the first row to be read. If there is no such row, print a message and finish. If input data is correct, write 100 rows from the user's given number to a new file. Add word count to each row. If there is less than 100 rows, write as many as there are. try, except , else を使うのはわかるのですが、どのようにコードを書いたらいいのか不明です。 プログラミング言語は必須で全くの初心者なのにこのような課題が出て頭を悩ませております。。 どなたかご教授をお願い申し上げます。 バージョンは3.7.2です。
回答: 必要知識 * 標準入出力 * ファイルの開き方、読み込み方 * 例外処理の仕方 * Listの使い方 * ファイルの書き込み方 注意点 正常な動作はテストしましたが、保証は致しかねます。 あくまでも以下に掲載するソースコードは解答例として参考にして頂き、 ご自身で、「何故こう動くのか」という事を意識した上で一行一行読んでいただけたら幸いです。 以下、ソースコード(解答例) ``` import sys # ファイル名を聞く print("Please enter a file name") file_name = input() try: # ファイルを開けてみる file = open(file_name, "r") except IOError: # 開けれないならエラーを出力し、IO閉じて、エラーコードを返し終了 print(file_name+" is not found") sys.exit(1) # 読み込んだファイルを一行ずつリストに入れる file_rows = file.readlines() # IOをクローズする file.close() # 何行目から読み込みたいか聞く # 読み込み直後にint型へ変換し、配列インデックスに合せ-1しとく print("What line does start row say that?") start_row = int(input())-1 try: # 指定された行にアクセスしてみる _ = file_rows[start_row] except IndexError: # アクセスできないならエラーを出力し、エラーコードを返し終了 print("The row is not found") sys.exit(1) # 書き込み用にファイルを開く。本来であれば例外処理すべきだが指定が無いのであえてそのまま # 尚、"a"は追記モード new_file = open("count_"+file_name,"a") # 100回繰り返す、iには0、1、2、...98、99の順で値が入る for i in range(100): try: # 指定行の内容を変数にいれとく current_row = file_rows[start_row + i] except IndexError: # もし100行満たす前に最後の行まで来てしまったら # IOクローズして正常終了 new_file.close() sys.exit(0) # 現在行の内容をスペースで区切ってリスト化しその要素数を求める(=単語数を求める) current_row_word_len = len(current_row.split()) # 単語数を追加した、新しいファイルに書き込むための行を構築する current_row = str(current_row_word_len) + " words | " + current_row # ファイルに書き込む new_file.write(current_row) #IOを閉じる new_file.close() #正常終了 sys.exit(0) ``` #### 仕様 * ファイル名を標準入力で受け付け開きます。存在しない場合は終了します。 * 何行目から読み込むか標準入力で受け付けます。存在しない行が指定された場合は終了します。 * 指定された行から100行、単語数のカウント を行先頭に追記したファイルを「count_元ファイル名」で保存します。 * 指定された行から、元ファイルの最後行が100行未満の場合は、最後行まで上述の処理を行います。 追加質問回答 ##### 追加質問1 > > 一つ目は単語の数の表示なのですが、 > > I am a Japanese. (4) > > このように表示するにはどうすればいいのでしょうか? > > > 回答欄ソースコード、コメント,空行を除く、下から4行目あたりに `current_row = str(current_row_word_len) + " words | " + current_row` というコードがあるのは分かりますか? この部分で、`current_row`には最初、元のテキストのある一行がそのまま入ってますが、これに文字列結合でただ単語数を追加してるだけです! まず、 ``` current_row = str(current_row_word_len) + " words | " + current_row ``` この行は、`current_row`へ「何か」を代入する行というのはお分かりいただけると思います。 そして、その「何か」、すなわち、 `str(current_row_word_len) + " words | " + current_row` は何をしているかというと、 次に以下3つを結合しています。 * `str(current_row_word_len)` current_row_word_lenを文字列型へ変換したもの * `words |` 単純な文字列 * `current_row` 文字列型変数(現在処理中の元ファイルの行の文字列) それら結合した物を、`current_row`へぶち込みなおす処理をしてます。 なので、`I am a Japanese. (4)`という表示にしたければ ``` current_row = current_row + " (" + str(current_row_word_len) + ")" ``` で、いけそうですが、無理です。(私はこれでいけると思った・・・) なぜならば、`current_row`の一番最後の文字に改行コードが入ってしまっています。 よって、以下のようにcurrent_row最後の改行を消して、さらに改行コードを連結すればいけます。 ``` current_row = current_row.rstrip('\n') + " (" + str(current_row_word_len) + ")\n" ``` ポイントとしては * `current_row.rstrip('\n')`で改行コードを消してる * `")\n"`で最後にカッコを閉じるだけでなく改行を入れてあげる です。 ##### 追加質問2 > > 二つ目は > > > > ``` > try: > # 指定された行にアクセスしてみる > _ = file_rows[start_row] > ``` > > > > の初めの_の部分はどういうことを表しているのでしょうか? > > > これは特にPythonでは意味は無いです。紛らわしくてごめんなさい。 一部のプログラミング言語では、ブランク識別子等と呼ばれ、要は捨てるための変数と考えて頂けると分かりやすいです。 ただ、Pythonにはその概念が無いのでこのようにして使いました。 もっとスマートなやり方あれば教えてください笑 今回の場合、別に今すぐには`file_rows[start_row]`に対して用事は無いけど、 もし存在しなかったら困るから念のため`try:`の中でいったんアクセスしてみる、ために使ってます。