質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

1256閲覧

スコープ外での変数や配列の利用について

fujimu

総合スコア4

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1グッド

0クリップ

投稿2023/04/22 15:34

実現したいこと

・スコープ外で行数がわからないものを配列に格納する方法はどうしたらいいのかわかりません。
・こういう場合はリストを使った方がいいのでしょうか?
・最終的には日付と会社名が一致すれば、内容が表示できるようにしたいです。
・まだまだ不慣れなので、色々プログラムの効率のいい考え方等も教えていただけると助かります。

発生している問題・エラーメッセージ

whie内で作成した配列がwhile外では使えない

前提

・C#を勉強がてら、手探りで個人的に会社の打ち合わせメモアプリを作成しています。
・data.csvの中には「日付,会社名,内容」をカンマ区切り出力できるように保存しています。
・まだ慣れていないのでコードを考えてから、それぞれクラスに考えていこうと思っています。

・プログラムの順番は
①streamを使ってcsvをカンマ区切りで配列に格納
配列fields [0]日付 [1]会社名 [2]内容
②fields配列をさらに配列に格納?
③「日付」と「会社名」を入力し一致したら「内容」が表示される
という順番で考えています。

該当のソースコード

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6using System.IO; 7using System.Runtime.Remoting.Messaging; 8 9namespace login 10{ 11 internal class Program 12 { 13 static void Main(string[] args) 14 { 15 try 16 { 17 StreamReader s = new StreamReader("C:\\Users\\gonta\\Desktop\\data.csv", Encoding.GetEncoding("Shift-JIS")); 18 int count = 0; 19 while (!s.EndOfStream) 20 { 21 string line = s.ReadLine(); 22 string[] fields = line.Split(','); 23 for (int i = 0; i > fields.Length; i++) 24 { 25 csv[count] = fields[i]; 26 } 27 count++; 28 } 29 s.Dispose(); 30 31 string date = Console.ReadLine(); 32 string name = Console.ReadLine(); 33 34 string msg = ""; 35 foreach (string lines in csv) 36 { 37 if (lines[0] == date && lines[1] == name) 38 { 39 msg = lines[2]; 40 } 41 else if(lines[0] == date) 42 { 43 msg = "指定した日にちに指定の会社のメモが存在しません。"; 44 } 45 } 46 if( msg != "") 47 { 48 Console.WriteLine(msg); 49 } 50 else 51 { 52 Console.WriteLine("指定した日にちにメモはありません。"); 53 } 54 } 55 catch(System.Exception e) 56 { 57 // ファイルを開くのに失敗したとき 58 System.Console.WriteLine(e.Message); 59 } 60 } 61 } 62}

補足情報(FW/ツールのバージョンなど)

visual studio2022

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2023/04/22 15:46

スコープが何を指すのかわからないけど、とりあえず参考にしているものが古すぎます。
episteme

2023/04/22 16:19

> ・こういう場合はリストを使った方がいいのでしょうか? やってみてはいかが? # きっとうまくいく
otn

2023/04/22 17:37

実現したいことに書いてあることの意味ががよくわかりませんが、 > whie内で作成した配列がwhile外では使えない の1行だけを見て言うと、while外で使いたい変数はwhile外で宣言すれば良いだけでは?
guest

回答2

0

ベストアンサー

・スコープ外で行数がわからないものを配列に格納する方法はどうしたらいいのかわかりません。

string[][] csv = new string[/* ここをどうすればいいかわからない */][];ということですね?

・こういう場合はリストを使った方がいいのでしょうか?

StreamReaderを使う縛りなら、リストを使った方がいいでしょう。

cs

1using System; 2using System.Collections.Generic; 3using System.IO; 4using System.Text; 5 6namespace Qbk5ysjl4t6nvtm 7{ 8 internal class Program 9 { 10 static void Main() 11 { 12 List<string[]> csv = new List<string[]>(); 13 14 try 15 { 16 //string filePath = @"C:\Users\gonta\Desktop\data.csv"; 17 string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 18 string filePath = Path.Combine(desktopPath, "data.csv"); 19 20 //Dummy(filePath); 21 22 using (StreamReader s = new StreamReader(filePath, Encoding.GetEncoding("Shift-JIS"))) 23 { 24 while (!s.EndOfStream) 25 { 26 string line = s.ReadLine(); 27 string[] fields = line.Split(','); 28 csv.Add(fields); 29 } 30 } 31 } 32 catch (Exception e) 33 { 34 Console.WriteLine(e.Message); 35 Console.ReadKey(); 36 return; 37 } 38 39 40 while (true) 41 { 42 Console.Write("日付を入力(yyyyMMdd) >"); 43 string date = Console.ReadLine(); 44 45 Console.Write("会社名を入力 >"); 46 string name = Console.ReadLine(); 47 48 bool found = false; 49 foreach (string[] fields in csv) 50 { 51 if (fields[0] == date && fields[1] == name) 52 { 53 Console.WriteLine(fields[2]); 54 found = true; 55 } 56 } 57 58 if (!found) 59 { 60 Console.WriteLine("指定した日にちに指定の会社のメモが存在しません。"); 61 } 62 63 Console.WriteLine(); 64 } 65 } 66 67 private static void Dummy(string filePath) 68 { 69 string csv = @" 7020230423,ほげ株式会社,ほげほげ 7120230423,株式会社ふが,ふがふが 72".Trim(); 73 File.WriteAllText(filePath, csv, Encoding.GetEncoding("Shift-JIS")); 74 } 75 } 76}

List<T> クラス (System.Collections.Generic) | Microsoft Learn

Environment.GetFolderPath メソッド (System) | Microsoft Learn

Environment.SpecialFolder 列挙型 (System) | Microsoft Learn

Path.Combine メソッド (System.IO) | Microsoft Learn

using ステートメント - 破棄可能なオブジェクトが正しく使用されるようにする | Microsoft Learn


StreamReaderにこだらないのであれば、配列にすることも可能です。

cs

1using System; 2using System.IO; 3using System.Linq; 4using System.Text; 5 6namespace Qbk5ysjl4t6nvtm 7{ 8 internal class Program 9 { 10 static void Main() 11 { 12 string[][] csv; 13 14 try 15 { 16 //string filePath = @"C:\Users\gonta\Desktop\data.csv"; 17 string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 18 string filePath = Path.Combine(desktopPath, "data.csv"); 19 20 //Dummy(filePath); 21 22 csv = File.ReadLines(filePath, Encoding.GetEncoding("Shift-JIS")) 23 .Select(line => line.Split(',')) 24 .ToArray(); 25 } 26 catch (Exception e) 27 { 28 Console.WriteLine(e.Message); 29 Console.ReadKey(); 30 return; 31 } 32 33 34 while (true) 35 { 36 Console.Write("日付を入力(yyyyMMdd) >"); 37 string date = Console.ReadLine(); 38 39 Console.Write("会社名を入力 >"); 40 string name = Console.ReadLine(); 41 42 bool found = false; 43 foreach (string[] fields in csv) 44 { 45 if (fields[0] == date && fields[1] == name) 46 { 47 Console.WriteLine(fields[2]); 48 found = true; 49 } 50 } 51 52 if (!found) 53 { 54 Console.WriteLine("指定した日にちに指定の会社のメモが存在しません。"); 55 } 56 57 Console.WriteLine(); 58 } 59 } 60 61 private static void Dummy(string filePath) 62 { 63 string csv = @" 6420230423,ほげ株式会社,ほげほげ 6520230423,株式会社ふが,ふがふが 66".Trim(); 67 File.WriteAllText(filePath, csv, Encoding.GetEncoding("Shift-JIS")); 68 } 69 } 70}

File.ReadLines メソッド (System.IO) | Microsoft Learn

Enumerable.Select メソッド (System.Linq) | Microsoft Learn

Enumerable.ToArray<TSource>(IEnumerable<TSource>) メソッド (System.Linq) | Microsoft Learn

投稿2023/04/22 22:14

編集2023/04/22 22:17
TN8001

総合スコア9326

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fujimu

2023/04/23 06:54

ベストアンサーにさせていただきました。 私のわかりにくい意図を理解していただき、2種類のわかりやすいコードを書いていただきありがとうございます。 3日間悩んでいた事が無事に実装できました。 リストの中に配列を格納できること、またstram readerを使用しない方法で配列にする方法もあるなんて、色々調べても出てこなかったので、とても勉強になりました。 本当にありがとうございました。
guest

0

こういう場合はリストを使った方がいいのでしょうか?

そうです。問題は、スコープは関係なくて、今のコードでは while ループが終わるまで行数が分からないので配列の初期化ができないことです。なので、List<string[]> を使いましょう。

以下の一行、

var csv = new List<string[]>();

を Main メソッド内の最初の行に追加して、while ループの中の、

for (int i = 0; i > fields.Length; i++) { csv[count] = fields[i]; }

を、

csv.Add(fields);

に代えてはいかがですか?

foreach (string lines in csv) 以下の処理も、上記に合わせて変更する必要がありますので忘れずに。

どうしても配列を使いたいということであれば、File.ReadAllLines メソッドを使って全行読んでしまうという手もあります。

投稿2023/04/22 21:27

編集2023/04/23 01:31
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fujimu

2023/04/23 06:59

回答ありがとうございます。 私のわかりにくい質問の意図を理解していただきありがとうございます。 配列は要素数を明確にしないと使えない事が今回のことで私自身に叩き込まれました。 Listに変更することで無事に実装することができました。 Listの使い方を、わかりやすく解説していただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問