C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]:


(過去ログ 129 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■76525 / inTopicNo.1)  配列中の値をソートした後、ファイルに書き込みたい。
  
□投稿者/ ゆーきゃん (17回)-(2015/07/17(Fri) 18:00:26)

分類:[C#] 

いつも大変お世話になっております。
ちょっとお時間宜しいでしょうか?

VisualC#を使用し、プログラムを組んでいます。

配列の値をソートすると、同じタイミングで打ち込んだ値も同じ順番にソートするようにしたいのですが、どのような考え方がありますでしょうか?

すみません。
上手く書けなかったので例を上げさせていただきます。


Combobox1、textbox1,2,3があり、
Combobox1に"GJ1"を入力後、
textbox1に"1"、textbox2に"5"、textbox3に"9"を入力し、
botton1をクリックすると、その値を配列に代入するようにしています。

この操作を3回繰り返し、

combobox1[3]={GJ1,GJ3,GJ2}
textbox1[3]={1,5,9}
textbox2[3]={7,2,3}
textbox3[3]={4,6,8}

を出力したとします。

Array.Sort(combobox1);
のコマンドを使用すると、

combobox1[3]={GJ1,GJ2,GJ3}
textbox1[3]={1,5,9}
textbox2[3]={7,2,3}
textbox3[3]={4,6,8}

となると思うのですが、
同じタイミングで打ち込んだtextboxの値もソートしたいのです。

ですので、comboboxがソートされた場合、
combobox1[3]={GJ1,GJ2,GJ3}
textbox1[3]={1,9,5}
textbox2[3]={7,3,2}
textbox3[3]={4,8,6

というかたちにしたいのですが、
どのようにソートもしくは並び替えればよろしいでしょうか?

お手数おかけして申し訳ございませんが、お力添え願えませんでしょうか。


引用返信 編集キー/
■76527 / inTopicNo.2)  Re[1]: 配列中の値をソートした後、ファイルに書き込みたい。
□投稿者/ ゆーきゃん (18回)-(2015/07/17(Fri) 18:20:36)
すみません。補足です。

combobox1,textbox1/2/3を入力後、button1をクリック。

↓ 3回同じ作業

button2をクリックし、配列の中身をファイルに落とすといった流れで行っております。

combobox1 = 文字を打ち込む
textbox1 = 数値を打ち込む
textbox2 = 数値を打ち込む
textbox3 = 数値を打ち込む
button1 = 配列に値を入れる。
button2 = ファイルに配列の値を書き込む
button3 = ファイルを読み込む。

button2を押したときに、今現在はソートをかけております。


引用返信 編集キー/
■76530 / inTopicNo.3)  Re[1]: 配列中の値をソートした後、ファイルに書き込みたい。
□投稿者/ 魔界の仮面弁士 (414回)-(2015/07/17(Fri) 18:48:25)
No76525 (ゆーきゃん さん) に返信
> 配列の値をソートすると、
配列は、データの追加や削除には向いていないので、
ジェネリック コレクション(List<> など)を使った方が楽ですよ。


> Combobox1に"GJ1"を入力後、
選択ではなく入力ですか?
ということは、DropDownList スタイルではなく DropDown スタイルなのですね。


> 打ち込んだ値も同じ順番にソートするようにしたいのですが、どのような考え方がありますでしょうか?

別々の配列で管理しようとせず、それらをまとめて管理するためのクラスを
用意しておけばいいんじゃないですかね。


public class ゆーきゃん
{
 public string 文字列 { get; set; }
 public string 数字1 { get; set; }
 public string 数字2 { get; set; }
 public string 数字3 { get; set; }

 public ゆーきゃん(string c, string t1, string t2, string t3)
 {
  this.文字列 = c;
  this.数字1 = t1;
  this.数字2 = t2;
  this.数字3 = t3;
 }
}

private List<ゆーきゃん> データ;
private void Form1_Load(object sender, EventArgs e)
{
 データ = new List<ゆーきゃん>();
 this.button1.Text = "追加";
 this.button2.Text = "ソート";
}

private void button1_Click(object sender, EventArgs e)
{
 データ.Add(new ゆーきゃん(
  this.comboBox1.Text,
  this.textBox1.Text,
  this.textBox2.Text,
  this.textBox3.Text));

 ViewData();
}

private void button2_Click(object sender, EventArgs e)
{
 // comboBox1 の文字列で並び替え
 データ = データ.OrderBy(x => x.文字列).ToList();

 ViewData();
}

[System.Diagnostics.Conditional("DEBUG")]
private void ViewData()
{
 // this.dataGridView1.DataSource = null;
 // this.dataGridView1.DataSource = データ;
}
引用返信 編集キー/
■76531 / inTopicNo.4)  Re[2]: 配列中の値をソートした後、ファイルに書き込みたい。
□投稿者/ 魔界の仮面弁士 (415回)-(2015/07/17(Fri) 18:54:20)
No76530 (魔界の仮面弁士) に追記
>  // comboBox1 の文字列で並び替え
>  データ = データ.OrderBy(x => x.文字列).ToList();

これだと別のインスタンスが生成されてしまうので、

 データ.Sort((x, y) => x.文字列.CompareTo(y.文字列));

の方が良いかな。
引用返信 編集キー/
■76532 / inTopicNo.5)  Re[3]: 配列中の値をソートした後、ファイルに書き込みたい。
□投稿者/ ゆーきゃん (19回)-(2015/07/18(Sat) 15:14:16)
No76531 (魔界の仮面弁士 さん) に返信

いつもいつもお答えありがとうございます。
大変助かっております。

現在、手元に開発環境がないためプログラムを組むことができませんが、
連休明けすぐに、魔界の仮面弁士さんのアドバイスを元に、作業に取りかかろうと思います。

お力添え感謝いたします。
引用返信 編集キー/
■76542 / inTopicNo.6)  Re[4]: 配列中の値をソートした後、ファイルに書き込みたい。
□投稿者/ ゆーきゃん (20回)-(2015/07/21(Tue) 18:34:28)
No76532 (ゆーきゃん さん) に返信

始めに長文失礼いたします。

ファイル書き込み時にエラーが起こり、回避方法が分かりません。
どなたかご教授願えませんでしょうか。

こちらがプログラムになります

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;


namespace ex
{

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        public class data
        {

            public string cb;
            public int tb_1;
            public int tb_2;
            public int tb_3;

            public data(string c, int t1, int t2, int t3)
            {
                this.cb = c;
                this.tb_1 = t1;
                this.tb_2 = t2;
                this.tb_3 = t3;
            }
        }

        private List<data> lst;

        private void Form1_Load(object sender, EventArgs e)
        {
            lst = new List<data>();
        }


        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            // データの読み出し&表示
        }

        private void comboBox1_Leave(object sender, EventArgs e)
        {
            comboBox1.Items.Add(comboBox1.Text);
        }


        public void button1_Click(object sender, EventArgs e)
        {
            lst.Add(new data(
                comboBox1.Text,
                int.Parse(textBox1.Text),
                int.Parse(textBox2.Text),
                int.Parse(textBox3.Text)));

            // ボタン1が押された際、comboBox/textBoxを空白にする
            comboBox1.Text = "";
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();

        }


        private void button2_Click(object sender, EventArgs e)
        {
            // comboBox1 の文字列で並び替え
            lst.Sort((x, y) => x.cb.CompareTo(y.cb));

            using (BinaryWriter w = new BinaryWriter(File.OpenWrite(@"c:\data\test.dat")))
            {
                w.Write(lst);   // ← ここでエラー           
            }

        }

        private void button3_Click(object sender, EventArgs e)
        {

            // 保存したファイルの呼び出し

        }

        // アプリケーション終了
        private void button4_Click(object sender, EventArgs e)
        {
            Close();
        }

        // エンターを押すと次のフォーカスに移動。
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (!e.Control)
                {
                    this.SelectNextControl(this.ActiveControl, !e.Shift, true, true, true);
                }
            }
        }
    }
}


「 w.Write(lst); 」でファイルに書き込もうとする際にエラーが起こります。

error CS1502: 'System.IO.BinaryWriter.Write(bool)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。

error CS1503: 引数 1: 'System.Collections.Generic.List<ex.Form1.data>' から 'bool' に変換できません

という内容です。

また、「lst.Sort((x, y) => x.cb.CompareTo(y.cb));」のx,yには何の値が入っているのでしょうか?デバックするごとに違う値が入ってきています。
ソートはできているのですが、どのような動きでソートされているかが分かりませんでした。

質問ばかりで申し訳ないのですが、エラー回避方法のヒントを頂けないでしょうか。
   

引用返信 編集キー/
■76546 / inTopicNo.7)  Re[5]:
□投稿者/ Azulean (504回)-(2015/07/21(Tue) 19:26:06)
2015/07/21(Tue) 19:27:52 編集(投稿者)
No76542 (ゆーきゃん さん) に返信
> 「 w.Write(lst); 」でファイルに書き込もうとする際にエラーが起こります。
> error CS1502: 'System.IO.BinaryWriter.Write(bool)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。
> error CS1503: 引数 1: 'System.Collections.Generic.List<ex.Form1.data>' から 'bool' に変換できません

エラーの通りで、BinaryWriter.Write にあなたが作ったクラスを処理するメソッドはありません。
クラスを自分で作り、それをファイルに書き落としたいなら、どのように書き込むかをあなたが実装しなければなりません。

一例
 1.最初に List の要素数を書く。
 2.foreach ループで要素ごとに、cb, tb_1, tb_2, tb_3 を Write する。

w.Write(lst.Count);
foreach (data item in lst)
{
  w.Write(item.cb);
  w.Write(item.tb_1);
  w.Write(item.tb_2);
  w.Write(item.tb_3);
}


> また、「lst.Sort((x, y) => x.cb.CompareTo(y.cb));」のx,yには何の値が入っているのでしょうか?
> デバックするごとに違う値が入ってきています。
> ソートはできているのですが、どのような動きでソートされているかが分かりませんでした。

x と y にはソートアルゴリズムの途中で、どのように並べ替えるべきか決めるために、リストの中のある値と別の値を取り出したものです。
ソートのアルゴリズムについては Sort メソッド自体に説明があります。
https://msdn.microsoft.com/ja-jp/library/w56d4y5z

引用返信 編集キー/
■76558 / inTopicNo.8)  Re[6]:
□投稿者/ ゆーきゃん (21回)-(2015/07/22(Wed) 10:32:42)
No76546 (Azulean さん) に返信

> エラーの通りで、BinaryWriter.Write にあなたが作ったクラスを処理するメソッドはありません。
> クラスを自分で作り、それをファイルに書き落としたいなら、どのように書き込むかをあなたが実装しなければなりません。
> 
> 一例
>  1.最初に List の要素数を書く。
>  2.foreach ループで要素ごとに、cb, tb_1, tb_2, tb_3 を Write する。
> 
> w.Write(lst.Count);
> foreach (data item in lst)
> {
>   w.Write(item.cb);
>   w.Write(item.tb_1);
>   w.Write(item.tb_2);
>   w.Write(item.tb_3);
> }

お答えありがとうございます。
要素ごとにwriteする必要があったのですね。
勉強になりました。 
「w.Write(lst);」だけで、Azuleanさんが書いて下さったプログラムの働きがあると思っておりました。

 
> x と y にはソートアルゴリズムの途中で、どのように並べ替えるべきか決めるために、リストの中のある値と別の値を取り出したものです。
> ソートのアルゴリズムについては Sort メソッド自体に説明があります。
> https://msdn.microsoft.com/ja-jp/library/w56d4y5z

ソートに関するサイトのURLを載せて頂きありがとうございます。
参考にさせて頂きたいと思います。 

引用返信 編集キー/
■76561 / inTopicNo.9)  Re[7]:
□投稿者/ ゆーきゃん (22回)-(2015/07/22(Wed) 11:57:28)
皆様のおかげで無事に思い通りの結果を出力することができました。
大変感謝しております。ありがとうございます。

最後にもう一つだけ宜しいでしょうか。

button3を押し、前回書き込んだファイルを読み込み、コンボボックスの要素選択時に、要素に合った文字と数値を表示させるプログラムを作成しているのですが、これもListを使用した書き方など考えられるのでしょうか?

ここからは配列でやるしか思いつかないのですが、どうなのでしょうか?

他の人の役に立つかわかりませんが、完成したプログラムを提示させて頂きました。
また、ここをこうするとよりよくなるなどありましたら、ご教授願えませんでしょうか?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;


namespace ex
{

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        public class data
        {

            public string cb;
            public int tb_1;
            public int tb_2;
            public int tb_3;

            public data(string c, int t1, int t2, int t3)
            {
                this.cb = c;
                this.tb_1 = t1;
                this.tb_2 = t2;
                this.tb_3 = t3;
            }
        }

        private List<data> lst;
        int yomikomi;

        public string[] cb_hai = new string[3]; // 長さが3の整数型配列を用意。
        public int[] tb_1_hai = new int[3]; // 長さが3の整数型配列を用意。
        public int[] tb_2_hai = new int[3]; // 長さが3の整数型配列を用意。
        public int[] tb_3_hai = new int[3]; // 長さが3の整数型配列を用意。


        private void Form1_Load(object sender, EventArgs e)
        {
            lst = new List<data>();
        }


        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            // データの読み出し&表示
            if (yomikomi == 1)
            {

                FileStream fs = new FileStream(
                     @"c:\data\test.dat",
                         FileMode.Open,
                           FileAccess.Read);


                int fileSize = (int)fs.Length; // ファイルのサイズ

                byte[] buf = new byte[fileSize]; // データ格納用配列

                int readSize; // Readメソッドで読み込んだバイト数
                int remain = fileSize; // 読み込むべき残りのバイト数
                int bufPos = 0; // データ格納用配列内の追加位置


                while (remain > 0)
                {
                    // 14 Bytesずつ読み込む 
                    readSize = fs.Read(buf, bufPos, Math.Min(14, remain));

                    bufPos += readSize;
                    remain -= readSize;

                    for (int i = 0; i < 3; i++)
                    {
                        if (cb_hai[i] == comboBox1.SelectedItem.ToString())
                        {
                            comboBox1.Text = cb_hai[i].ToString();
                            textBox1.Text = tb_1_hai[i].ToString();
                            textBox2.Text = tb_2_hai[i].ToString();
                            textBox3.Text = tb_3_hai[i].ToString();
                        }
                    }
                }
            }
        }

        private void comboBox1_Leave(object sender, EventArgs e)
        {
            comboBox1.Items.Add(comboBox1.Text);
        }


        public void button1_Click(object sender, EventArgs e)
        {
            lst.Add(new data(
                comboBox1.Text,
                int.Parse(textBox1.Text),
                int.Parse(textBox2.Text),
                int.Parse(textBox3.Text)));

            // ボタン1が押された際、comboBox/textBoxを空白にする
            comboBox1.Text = "";
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();

        }


        private void button2_Click(object sender, EventArgs e)
        {
            // comboBox1 の文字列で並び替え
            lst.Sort((x, y) => x.cb.CompareTo(y.cb));

            using (BinaryWriter w = new BinaryWriter(File.OpenWrite(@"c:\data\test.dat")))
            {
                //w.Write(lst.Count);   // ← ここでエラー 
                foreach(data Item in lst)
                {
                    w.Write(Item.cb);
                    w.Write(Item.tb_1);
                    w.Write(Item.tb_2);
                    w.Write(Item.tb_3);

                }
            }

        }

        // 保存したファイルの呼び出し
        private void button3_Click(object sender, EventArgs e)
        {

            yomikomi = 1;

            comboBox1.Items.Clear();

            // 簡単読込             
            FileStream fs = new FileStream(@"c:\data\test.dat",
                                             FileMode.Open,
                                             FileAccess.Read);

            BinaryReader br = new BinaryReader(fs);

            for (int i=0; i<3; i++)
            {
                cb_hai[i] = br.ReadString();
                tb_1_hai[i] = br.ReadInt32();
                tb_2_hai[i] = br.ReadInt32();
                tb_3_hai[i] = br.ReadInt32();

                comboBox1.Items.Add(cb_hai[i]);
            }
        }

        // アプリケーション終了
        private void button4_Click(object sender, EventArgs e)
        {
            Close();
        }

        // エンターを押すと次のフォーカスに移動。
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (!e.Control)
                {
                    this.SelectNextControl(this.ActiveControl, !e.Shift, true, true, true);
                }
            }
        }
    }
}

引用返信 編集キー/
■76562 / inTopicNo.10)  Re[8]:
□投稿者/ 魔界の仮面弁士 (420回)-(2015/07/22(Wed) 12:17:57)
No76561 (ゆーきゃん さん) に返信
> 皆様のおかげで無事に思い通りの結果を出力することができました。

数値入力特化なら、TextBox.Text よりも NumericUpDown.Value の方が良いかもしれません。
数値以外のデータが入力されることを防げますので。


> button3を押し、前回書き込んだファイルを読み込み、コンボボックスの要素選択時に、要素に合った文字と数値を表示させるプログラムを作成しているのですが、これもListを使用した書き方など考えられるのでしょうか?

たとえばこんな感じ。

string コンボボックスの値 = comboBox1.Text;

data item = lst.FirstOrDefault(x => x.cb == コンボボックスの値);
if (item == null)
{
  textBox1.Text = textBox2.Text = textBox3.Text = "";
}
else
{
  textBox1.Text = item.tb_1.ToString();
  textBox2.Text = item.tb_2.ToString();
  textBox3.Text = item.tb_3.ToString();
}
引用返信 編集キー/
■76563 / inTopicNo.11)  Re[8]:
□投稿者/ 魔界の仮面弁士 (421回)-(2015/07/22(Wed) 12:39:40)
No76561 (ゆーきゃん さん) に返信
> if (cb_hai[i] == comboBox1.SelectedItem.ToString())
ここでは、『comboBox1.SelectedItem.ToString()』で取得していて、

> comboBox1.Items.Add(comboBox1.Text);
ここでは、『comboBox1.Text』で取得していますね。


コードに対象性が無いようにも見えますが、両者を意図的に使い分けているのでしょうか?
(役割が異なるため、これらが同じ値を返すこともあれば、別の値を返すこともあります)


> lst.Add(new data(
>  comboBox1.Text,
>  int.Parse(textBox1.Text),
>  int.Parse(textBox2.Text),
>  int.Parse(textBox3.Text)));


TextBox の内容が「int 型に変換できない文字列」だった場合、たとえば
"" や "-" や "3" や "1.5" や "9876543210" だった場合なにおいては
.Parse が例外を発生させますが、その点は大丈夫でしょうか。

TextBox 側に、数値以外を入力できないような制限をかけているなら良いですが、
そうしたチェックを行っていないのなら、int.TryParse メソッドを試してみると良いかもしれません。
数値変換するだけでなく、それが数値として変更できるかどうかの検証も同時に行ってくれますよ。
(サンプルコードゆえに、細かい点は省略して投稿されているだけなのかもしれませんが…)
引用返信 編集キー/
■76564 / inTopicNo.12)  Re[9]:
□投稿者/ ゆーきゃん (24回)-(2015/07/22(Wed) 13:37:47)
No76563 (魔界の仮面弁士 さん) に返信
>> if (cb_hai[i] == comboBox1.SelectedItem.ToString())
> ここでは、『comboBox1.SelectedItem.ToString()』で取得していて、
> 
>> comboBox1.Items.Add(comboBox1.Text);
> ここでは、『comboBox1.Text』で取得していますね。
> 
> コードに対象性が無いようにも見えますが、両者を意図的に使い分けているのでしょうか?
> (役割が異なるため、これらが同じ値を返すこともあれば、別の値を返すこともあります)
> 

迅速なご回答ありがとうございます。
同じ値を返すつもりなので、対称性は持たせたいです。
このままですと違う値を返すことがあるのですね。
今後はしっかり対称性も考えてプログラムを組むよう心掛けたいと思います。

>>lst.Add(new data(
>> comboBox1.Text,
>> int.Parse(textBox1.Text),
>> int.Parse(textBox2.Text),
>> int.Parse(textBox3.Text)));
> 
 
> TextBox の内容が「int 型に変換できない文字列」だった場合、たとえば
> "" や "-" や "3" や "1.5" や "9876543210" だった場合なにおいては
> .Parse が例外を発生させますが、その点は大丈夫でしょうか。
> 
> TextBox 側に、数値以外を入力できないような制限をかけているなら良いですが、
> そうしたチェックを行っていないのなら、int.TryParse メソッドを試してみると良いかもしれません。
> 数値変換するだけでなく、それが数値として変更できるかどうかの検証も同時に行ってくれますよ。
> (サンプルコードゆえに、細かい点は省略して投稿されているだけなのかもしれませんが…)

今回、textboxには整数のみしか入らないので、このような形に致しました。
 "" や "-" や "3" や "1.5" や "9876543210"や "文字" だった場合、
確かにこの形だとエラーが起こりました。
全対応する書き方とかもありそうですね。
教えて頂いたint.TryParse メソッドと一緒に調べてみたいと思います。

助けて頂いてばかりで恐縮です。
自分も早く回答できる立場になれるよう、頑張っていきたいと思います。




引用返信 編集キー/
■76565 / inTopicNo.13)  Re[10]:
□投稿者/ ゆーきゃん (25回)-(2015/07/22(Wed) 14:40:09)
解決いたしましたので、解決積みを付けさせていただきます。

お答えくださった皆様ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -