課題の進め方
基本的には適当なプロジェクト/ソリューションを作って課題を進めた上で,Program.cs
のみ(特に他に指示がなければ)を提出する.
他の人(受講者・非受講者両方)に解答内容(一部でも)を見せない,そして他の人の解答内容(一部でも)を見ないようお願いします.特に,公開の場所に解答を置かないようお願いします.githubやbitbucket等は使える人は使えばよいと思いますが,privateレポジトリにするようにお願いします.
プロジェクト/ソリューションの作成
Note
再掲:プロジェクトは一つの実行形式やライブラリを作成するためのコード等を全てまとめたものであり,ソリューションは関連するプロジェクトをまとめたもの(参考:What are solutions and projects in Visual Studio).
適当な名前(たとえば課題3の解答なのでQ3
にするなど)のフォルダを適当な場所に作成し,
VSCodeで作成したフォルダを開く.そして,VSCode内のターミナルで以下を実行する.
dotnet new console -o .
課題の実施
Program.cs
を問題文の指示の通りに編集する(提出・採点手続きの簡略化のため提出する.csファイルは一つのみ).作成した.csファイルには先頭部分に学籍番号と名前をコメントとして含めること.なので,たとえば学籍番号Z0TB9999の東北 大学さんの提出ファイルは
// Z0TB9999
// 東北 大学
という行から始まる.
提出
できあがった Program.cs
をClassroom内の当該回の「課題」より提出する.最初のステップで作成したフォルダにあるはず.また問題文に指示がある場合はそのファイル(例:課題4のitems.txt)も提出する.提出前には以下を確認しよう.
- 提出プログラムコードのファイル名は
Program.cs
になっているか - 提出するファイルに学籍番号と名前がコメントとして含まれているか
- 文献やWebサイトを参考にした場合は文献の情報やURLおよびアクセス日に加えて元文献のどの部分を参考にしたのかがコードの当該箇所付近のコメントとして記述されているか
- 友人と相談した・された場合はその友人の名前および大雑把な相談の内容がコメントとして書かれているか
- ただし,友人の解答を見ない,そして友人に解答を見せないようお願いします
- TA・教員と相談した場合は,その旨と大雑把な相談の内容がコメントとして書かれているか
基本課題
その1
Dictionary<string, int>
型のオブジェクトにキーとバリューの組をファイルから読みとることで追加したい.具体的には,中身が
Chocolate,2
Chips,4
Candy,5
であるファイルを読んで,今着目しているディクショナリdict
に
["Chocolate"] = 2;
dict["Chips"] = 4;
dict["Candy"] = 5; dict
としたのと同等の要素を追加したい.
上記を達成するため,以下のプログラムの空欄を埋めて完成させよ.
// あなたの学籍番号
// あなたの名前
using System;
using System.IO;
using System.Collections.Generic;
// インベントリ(いわゆる「アイテム欄」)
class Inventory
{
public Dictionary<string, int> Items { get; private set; } = new Dictionary<string, int>();
public void AddItemsFromFile(string filepath)
{
// 実装する.
//
// 与えられたパス filepath にファイルが存在し,そのファイルの中身が,各行が
//
// アイテム名,個数
//
// という形式であるようなテキストファイルになっているときに,
// 各行に含まれているアイテム名と個数の対応をディクショナリ Items に追加する.
// より詳細な形式については後述
}
// 必要に応じて 上の AddItemsFromFile(string) から呼ぶためのメソッドを追加してもよい.
// 変更しない
public void PrintAll()
{
foreach (var k in Items.Keys)
{
.WriteLine(k + " × " + Items[k]);
Console}
}
}
// 変更しない
class Program
{
static void Main()
{
= new Inventory();
Inventory i .AddItemsFromFile("./items.txt");
i.PrintAll();
i}
}
items.txt
の中身の例
Chocolate,2
Chips,0
Candy,5
そのときの期待される出力
Chocolate × 2
Chips × 0
Candy × 5
入力ファイルの形式
各行が
アイテム名,個数
という形になっている.基本課題においては,アイテム名,「,」,および個数の前後に余計な空白は含まれない(発展課題で変更あり)
個数は
int
で表現可能な数に比べて十分に小さいとする(オーバフローを考える必要はない).簡便のため負数や0は許すことにする.アイテム名自体は「,」および前後の空白は含まない.たとえば「 」(空白文字からなる文字列)や「 X 」(空白文字,'X',空白文字からなる文字列)などはここで言うアイテム名ではない.途中の空白は含んでもよい(例:「Ruby Chocolate」).
基本課題1では各行のアイテム名に重複を許さない(基本課題2で変更あり).
基本課題では上記の形式でないファイルが与えられたときの挙動は考えなくてよい.
items.txt
も提出物に含めること(発展課題も同じ).含めるitems.txt
は自身がプログラムの挙動を確認するのに使用したものでよい.
Note
items.txt
を相対パス./items.txt
でアクセスするためには,items.txt
は作業フォルダ直下に置く必要がある.環境設定1で紹介した方法でプロジェクトを作成しプログラムを実行しているのならば,VS Codeで開いたフォルダ(プロジェクトルート)直下に置いたので問題がないはずだ.
そうでない場合(Visual Studioを使用している場合など)は以下のいずれかを行う.
.csprojの
<PropertyGroup>...</PropertyGroup>
内に以下の行を追加する.StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory> <
Windows版のVisual Studioを使用している場合は,プロジェクト名を右クリックして出てくるコンテキストメニューから「プロパティ」を選択し,「デバッグ」の「作業ディレクトリ」を当該 .csproj ファイルの直上のディレクトリに設定する.
Mac版のVisual Studioを使用している場合は,プロジェクト名をダブルクリックして出てくるウィンドウの「実行」>「構成」> 「Default」の 「作業ディレクトリ」を当該 .csproj ファイルの直上のディレクトリに設定する.
Tip
個数の部分を処理するには,Int32.Parse(string)
を使うとよい.
この関数の使い方は以下のプログラムを参考にせよ.
using System;
// 参考:https://docs.microsoft.com/en-us/dotnet/api/system.int32.parse?view=net-6.0#system-int32-parse(system-string)
class Int32Example
{
static void TryParseInt(string s)
{
try
{
int n = Int32.Parse(s);
.WriteLine(s + " ==> " + n);
Console}
catch(FormatException e)
{
.WriteLine(s + ": ill-formed");
Console}
catch(OverflowException e)
{
.WriteLine(s + ": overflow");
Console}
catch(ArgumentNullException e)
{
.WriteLine("the input is null");
Console}
}
static void Main()
{
TryParseInt("1234");
TryParseInt("-1234");
TryParseInt("0xbeef");
TryParseInt("+34");
TryParseInt("3e10");
TryParseInt("011");
TryParseInt("1,000");
TryParseInt(string.Join("", new string[] { "1", "000", "000", "000", "000" }));
}
}
上のコードの出力
1234 ==> 1234
-1234 ==> -1234
0xbeef: ill-formed
+34 ==> 34
3e10: ill-formed
011 ==> 11
1,000: ill-formed
1000000000000: overflow
その2
基本課題その1で作成したAddItemsFromFile(string)
を拡張し,入力テキストファイルに同じアイテム名が複数含まれていた場合にそれらの個数を合計するようにせよ.
items.txt
の中身の例
Chocolate,2
Chips,14
Candy,5
Chocolate,40
Chips,-14
そのときの期待される出力
Chocolate × 42
Chips × 0
Candy × 5
Tip
ディクショナリにキーが含まれているかどうかを確認するにはContainsKey(TKey)
メソッドを用いることができる.たとえば式
.ContainsKey( k ) dict
の評価結果はk
がdict
に含まれていればtrue
,そうでなければfalse
である.
発展課題
Important
本課題を完了できたのならば本課題の解答のみを提出すればよく,基本課題の解答は提出する必要はない.
基本課題で作成したAddItemsFromFile(string)
を拡張し,入力テキストファイルにコメントや余計な空白,空行が入っていても正常に読みこめるようにせよ.ここで,"#"で始まる行をコメントとする("#"が行頭でない場合はコメントでないのに注意).また,空行は空白を含んでいてもよい.また,ある行において指定されたフォーマットで解釈することに失敗した場合には,Items
はその行以前までの行を読み取った結果で更新されるようにせよ.ここで,指定されたフォーマットで解釈できない行とは,たとえば以下のようなものである.
コメント行ではない行で「,」を含まない,あるいは2個以上含む行.たとえば:
#コメントでなくコンマを含まない行
AAA , 12, BBB , 34
コメント行ではない行で「,」を厳密に1つ含んでいるが,「,」の右側に整数以外が来ている.たとえば:
AAA, B
ここで整数以外とは
Int32.Parse()
が失敗するものとする.
items.txt
の中身の例1
#コメント行
Chocolate, 2
Chips ,14
Candy,5
Chocolate,40
例1に対し期待される出力
Chocolate × 42
Chips × 14
Candy × 5
items.txt
の中身の例2
# コメント行
Chocolate, 2
Chips ,14
# 空行は空白を含んでいてもよい
Candy,5
Chocolate,40
#コメントでない行
Candy,25
例2に対し期待される出力
Chocolate × 42
Chips × 14
Candy × 5
items.txt
の中身の例3
# アイテム名が数字なのは許される
100 , 5
# アイテム名に#は許される
#### , 9
# 個数の部分にはInt32.Parse()が失敗するようなものは許さない
something,ten
例3に対し期待される出力
100 × 5
#### × 9