문과 코린이의, [C#] 기록/C# 이론

[문과 코린이의 IT 기록장] C# - BCL(Base Class Library) (System.String, System.IO Directory, File, System.Collections ArrayList, System.Collections.Generics.List<T>)

벼리네 2022. 8. 11. 17:18
반응형

[문과 코린이의 IT 기록장] C# - BCL(Base Class Library) (System.String, System.IO Directory, File, System.Collections ArrayList, System.Collections.Generics.List<T>)


 

 

C# 프로그래밍 기초 - 인프런 | 강의

본 강좌는 C# 문법 위주로 구성되어있지 않습니다. 클래스를 이해하고 만드는 요령 위주로 구성되어 있습니다. 기초 문법도 다루지만 많은 예제를 가지고 진행하기 때문에 프로그램 실전 작성

www.inflearn.com


1. System.String

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "Hello World Nice to Meet You";

            //1. Contains (대소문자 구분됨)
            // ex. Nice라는 서브 문자열을 포함하고 있는지를 확인하기 위함.
            Console.WriteLine(str.Contains("Nice")); // True, False로 결과가 나옴. 

            // 2. Index Of (대소문자 구분됨)
            Console.WriteLine(str.IndexOf("Nice")); // n번째에 가면, Nice라는 String이 존재한다. 위치 출력.

            // 3. EndWith
            Console.WriteLine(str.EndsWith("You")); // ~로 끝나는가?
            Console.WriteLine(str.StartsWith("You"));

            // 4. Replace
            Console.WriteLine(str.Replace("You","You again")); // 바뀜

            // 5. ToLower
            Console.WriteLine(str.ToLower());
            Console.WriteLine(str.ToUpper());

            // 6. Split
            string[] strs = str.Split(' '); // ' ' 를 기준으로 자르기
            for (int i=0; i<strs.Length; i++) // 7. Length : 문자열의 길이
            {
                Console.WriteLine(strs[i]);
            }
            // 위와 결과가 같음. (for -> foreach)
            // 배열 및 컬랙션은 foreach문을 많이 씀
            foreach(string s in strs) // ienumable을 구현한 객체 (movenext, current 메소드를 구현하도록 표준화된 것)
            {
                Console.WriteLine(s);
            }

            // 7. SubString
            Console.WriteLine(str.Substring(1,4)); // 1부터 4개 가져와라.

            // 8. Trim
            string str1 = "######Hello World Nice to Meet You######";
            Console.WriteLine(str1.Trim('#')); // 맨 앞, 맨 뒤의 지정한 문자를 모두 제거한 후, 반환해줌.

            // 9. equals
            Console.WriteLine(str.Equals(str));
            
            // 10. DateTime
            // 1) 현재 날짜 + 시간
            Console.WriteLine(DateTime.Today);
            // 2) 현재 날짜
            Console.WriteLine(DateTime.Today.ToShortDateString());
            // 3) 날짜에서 - 제공
            Console.WriteLine(DateTime.Today.ToShortDateString().Replace("-",""));
            // 4) DateTime.Now + Format 위와 같은 결과 추출
            Console.WriteLine(DateTime.Now.ToString("yyyyMMdd"));
        }
    }
}

[ 문제 ]

문자열 6글자를 받아들여서, 삼합이 성립하는지 검사하는, 프로그램을 작성하시오

a. 문자열은, "자축인묘진사오미신유술해"에서 여섯 글자를 선택해 입력한다.

b. 다음 세 글자가 모두 있으면 삼합이 성립된다.

 - "해묘미"

 - "인오술"

 - "사유축"

 - "신자진"

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class StringEx
    {
        internal void Run()
        {
            string str = GetString();

            // [ 풀이 1 ]
            // ChkString(str);

            // [ 풀이 2 ]
            if (Find해묘미(str) || Find인오술(str) || Find사유축(str)|| Find신사진(str))
            {
                Console.WriteLine("성립");
            }
            else
            {
                Console.WriteLine("삼합이 성립하지 않습니다.");
            }
        }

        private string GetString()
        {
            while (true)
            {
                string chk = "자축인묘진사오미신유술해";

                Console.WriteLine("'자축인묘진사오미신유술해' 중, 6글자를 선택해 입력하시오.");
                string input = Console.ReadLine();

                if (input.Length != 6)
                {
                    Console.WriteLine("6글자가 입력되지 않았습니다. 다시 입력해주세요.");
                    continue;
                }

                int cnt = 0;
                for (int i = 0; i < 6; i++)
                {
                    if (chk.IndexOf(input[i]) != -1) // chk 내에, input[i]의 값이 존재한다면
                    {
                        cnt++;
                    }
                }
                if (cnt != 6)
                {
                    Console.WriteLine("잘못입력하셨습니다. 다시 입력해주세요.");
                    continue;
                }
                else
                {
                    return input;
                }
            }
        }



        // [ 풀이 1 ]
        /*private void ChkString(string input)
        {
            if (input.IndexOf('해') != -1 && input.IndexOf('묘') != -1 && input.IndexOf('미') != -1)
            {
                Console.WriteLine("성립");
            }
            else if (input.IndexOf('인') != -1 && input.IndexOf('오') != -1 && input.IndexOf('술') != -1)
            {
                Console.WriteLine("성립");
            }
            else if (input.IndexOf('사') != -1 && input.IndexOf('유') != -1 && input.IndexOf('축') != -1)
            {
                Console.WriteLine("성립");
            }
            else if (input.IndexOf('신') != -1 && input.IndexOf('사') != -1 && input.IndexOf('진') != -1)
            {
                Console.WriteLine("성립");
            }
            else
            {
                Console.WriteLine("삼합이 성립하지 않습니다.");
            }
        }*/


        // [ 풀이 2 ] 
        private bool Find해묘미(string str)
        {
            string[] hmm = new string[] { "해", "묘", "미" };
            return FindChk(hmm, str);
        }

        private bool Find인오술(string str)
        {
            string[] ios = new string[] { "인", "오", "술" };
            return FindChk(ios, str);
        }
        private bool Find사유축(string str)
        {
            string[] suc = new string[] { "사", "유", "축" };
            return FindChk(suc, str);
        }
        private bool Find신사진(string str)
        {
            string[] ssj = new string[] { "신", "사", "진" };
            return FindChk(ssj, str);
        }

        private bool FindChk(string[] strarr, string str)
        {
            foreach (string s in strarr)
            {
                if (str.IndexOf(s) == -1) { return false; }
            }
            return true;
        }
    }
}

 


2. System.IO Directory, File

File, FileInfo

Directory, Directory Info

Path

File I/O(stream)

 

1) Directory / DirectoryInfo

using System;
using System.Collections.Generic;
using System.IO; // Directory
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class BCLex
    {
        internal void Run()
        {
            // Directory, DirecotryInfo
            // Directory : 정적 클래스. 전부 정적 메소드, 프로퍼티 지원
            // DirectoryInfo : 인스턴스 클래스. 인스턴스를 만들어 사용하는 클래스.
            TestDirectory();
        }

        private void TestDirectory()
        {
            Console.WriteLine("Directory 입력");
            string root = Console.ReadLine(); // 특정 Directory Path Full Name을 받아들이기

            // CRUD => Create, Read, Update, Delete 모두 제공 되도록 구성해보기
            CreateDirectory(root);
            ReadDirectory(root);
            DeleteDirectory(root);
            RenameDirectory(root);

            string fileSystem = "c:";
            string directory1 = "Windows";
            string root1 = fileSystem + "\\" + directory1; // \는 하나가 안먹음
            ReadDirectory(root1);
        }

        private void CreateDirectory(string root)
        {
            if (!Directory.Exists(root)) // 우리가 입력한 Directory가 존재하면 True, 존재 X라면 False
            {
                // 3. CreateDirectory : 디렉터리 생성
                Directory.CreateDirectory(root);
                return;
            }
        }

        private void ReadDirectory(string root)
        {
            if (Directory.Exists(root)) // 우리가 입력한 Directory가 존재하면 True, 존재 X라면 False
            {
                Console.WriteLine($"{root} 디렉터리가 존재합니다.");
                DirectoryInfo di = new DirectoryInfo(root); // DirectoryInfo를 통해, root를 가지고 들어가서 di인스턴스가 생긴다. 이후, di.GetFiles(root)와 같이 사용 가능

                // 1. GetFiles(root) : root 밑의 파일을 모두 보여준다.
                string[] files = Directory.GetFiles(root); // Directory.GetFiles()는 string[]으로 Return
                FileInfo[] files2 = di.GetFiles();

                foreach (FileInfo file in files2)
                {
                    // Console.WriteLine($"파일 {file}을 찾았습니다.");
                    Console.WriteLine($"파일 {file.FullName} {file.Extension}을 찾았습니다.");
                }

                // 2. GetDirectories(root) : root 밑의 directory, 즉 subdirectory를 모두 보여준다.
                string[] subdirs = Directory.GetDirectories(root);
                foreach (string dir in subdirs)
                {
                    Console.WriteLine($"디렉터리 {dir}을 찾았습니다.");
                }
            }
        }

        private void DeleteDirectory(string root)
        {
            // 예외처리 방법
            try // 이 구문을 실행했을 때, Exception 발생하지 않으면 마무리.
            {
                // [예외발생] 디렉터리 내부에 파일 및 서브 디렉터리를 가지고 있다면, 해당 디렉터리는 지워지지 않는다.
                if (Directory.Exists(root))
                {
                    Directory.Delete(root);
                }
            }
            catch (Exception ex) // Exception클래스의 ex 인스턴스
            // Exception이 발생하면, 이 부분으로 이동. (어떤 예외들이 발생할지 모두 예상 및 예방할 수 없기 때문에)
            {
                Console.WriteLine($"오류발생 : {ex.Message}"); // 어떤 사유로 인해 exception이 발생했는지 출력
                return;
            }
        }

        private void RenameDirectory(string root)
        {
            try
            {
                Directory.Move(root, "d:\\kjee1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

2) File I/O (Stream)

- FileStream

- StreamReader / StreamWriter

Student.txt

[ Program.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class Program
    {
        static void Main(string[] args)
        {
            BCLex be = new BCLex();
            be.Run();
        }
    }
}

[ BCLex.cs ]

using System;
using System.Collections.Generic;
using System.IO; // Directory
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using myLibrary;

namespace BCL_0809
{
    class BCLex
    {
        Student[] students = new Student[3];

        internal void Run()
        {
            Student st = new Student();

            // class에 object.ToString()을 적용하면, [namespace.클래스명]을 반환한다.
            // 메소드 오버라이딩을 진행했으면, 정의한 포맷대로 ToString()이 호출된다. 즉, 여기서는 Student.ToString()이 호출된다.
            Console.WriteLine(st.ToString());
            Console.WriteLine(st);
            // 위와 같은 결과 출력. 인스턴스를 입력하면 WriteLine 속에서, ToString()을 먼저 호출.

            ReadStudent();
            PrintStudent();
            WriteStudent();
        }

        private void WriteStudent()
        {
            FileStream stream = new FileStream(@"D:\Student.bak", FileMode.Create);
            StreamWriter write = new StreamWriter(stream, Encoding.Default);
            foreach (Student st in students)
            {
                write.WriteLine($"{st.stName}#{st.stSex}#{st.stScore}");
            }
            write.Close();
        }

        private void PrintStudent()
        {
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine(students[i]);
            }
        }

        private void ReadStudent()
        {
            FileStream stream = new FileStream(@"D:\Student.txt", FileMode.Open); // @ : 이후에 나오는 특수문자를 특수문자 그 자체로 인식시켜라
            StreamReader reader = new StreamReader(stream, UTF8Encoding.UTF8); // 읽어들이기 위한 것.
            string buffer = null;
            int index = 0;
            while ((buffer = reader.ReadLine()) != null) // 한 줄을 읽어와서 buffer에 저장. string return
            {
                insertStudent(buffer, index++);
            }
            reader.Close();
        }

        private void insertStudent(string buffer, int index)
        {
            Student st = new Student();
            string[] tmp = buffer.Split('#'); // tmp[0] : 이름, tmp[1] : 성별, tmp[2]: 성적

            if (tmp.Length != 3)
            {
                throw new Exception("텍스트 내용에 오류가 있습니다. : " + buffer);
            }

            st.stName = tmp[0];
            int isex = int.Parse(tmp[1]);
            st.stSex = (SexEnum)Enum.ToObject(typeof(SexEnum), isex); // string을 enum형으로 변환
            st.stScore = Convert.ToInt32(tmp[2]); // string을 int형으로 변환

            students[index] = st;
        }

    }
}

[ Student.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using myLibrary;

namespace BCL_0809
{
    class Student : Object // 기본사항. Object는 생략도 가능.
    {
        public string stName { get; set; }
        public SexEnum stSex { get; set; }
        public int stScore { get; set; }


        // 부모 클래스에서 virtual로 메소드를 선언했을 경우에는, 자손들이 override할 수 있음.
        // object.ToString()은 virtual method

        public override string ToString()
        {
            return $"{stName}[{stSex}][{stScore}]";
        }
    }
}

결과
Student.bak

 

 


3. System.Collections ArrayList

* 배열과 같은 기능을 하는 클래스들이 많이 존재

-  ArrayList // 가변적인 기능

: Boxing & Unboxing 개념

: ArrayList Test

: Student Class 정렬 방법 (ArrayList에서)

 

1) Boxing & UnBoxing

int a = 3;
object o = a; // 3이라는 int값을, object o가 받아들인다.


2) ArrayList Test

[ Program.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class Program
    {
        static void Main(string[] args)
        {
            BCLex be = new BCLex();
            be.Run();
        }
    }
}

[ BCLex.cs ]

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using myLibrary;

namespace BCL_0809
{
    class BCLex
    {
        ArrayList students = new ArrayList(); // 학생 수가 어느정도 될지 모르기 때문에, ArrayList로 하기 효율적

        public void Run()
        {
            ReadStudent();
            students.Sort(); // Sort() : Compariable이 자동으로 이루어짐. (즉, ArrayList에서 우리가 준 로직에 의해 Sort가 됨)
            PrintStudent();
            WriteStudent();
        }

        private void WriteStudent()
        {
            FileStream stream = new FileStream(@"D:\Student.bak", FileMode.Create);
            StreamWriter write = new StreamWriter(stream, Encoding.Default);
            foreach (Student st in students)
            {
                write.WriteLine($"{st.stName}#{st.stSex}#{st.stScore}");
            }
            write.Close();
        }

        private void PrintStudent()
        {
            for (int i = 0; i < students.Count; i++) // students.Count로 개수를 지정하면 됨. 
            {
                Console.WriteLine(students[i]);
            }
        }

        private void ReadStudent()
        {
            FileStream stream = new FileStream(@"D:\Student.txt", FileMode.Open); // @ : 이후에 나오는 특수문자를 특수문자 그 자체로 인식시켜라
            StreamReader reader = new StreamReader(stream, UTF8Encoding.UTF8); // 읽어들이기 위한 것.
            string buffer = null;
            int index = 0;
            while ((buffer = reader.ReadLine()) != null) // 한 줄을 읽어와서 buffer에 저장. string return
            {
                insertStudent(buffer, index++);
            }
            reader.Close();
        }

        private void insertStudent(string buffer, int index)
        {
            Student st = new Student();
            string[] tmp = buffer.Split('#'); // tmp[0] : 이름, tmp[1] : 성별, tmp[2]: 성적

            if (tmp.Length != 3)
            {
                throw new Exception("텍스트 내용에 오류가 있습니다. : " + buffer);
            }

            st.stName = tmp[0];
            int isex = int.Parse(tmp[1]);
            st.stSex = (SexEnum)Enum.ToObject(typeof(SexEnum), isex); 
            st.stScore = Convert.ToInt32(tmp[2]); 

            students.Add(st); // ArrayList이기 때문에 이렇게 작성
        }

        public void Run1()
        {
            string[] str = new string[10]; // 배열은 10개가 만들어지면, 더 추가할 수 없음. 주어진 범위에서만 써야 함.

            ArrayList list = new ArrayList(); // ArrayList는 배열이지만, 고정적으로 잡히지 않음. 이 컬랙션에 하나를 집어너면 배열이 1개, 2개, 3개... 이런식으로 증가하는 형태

            // 1. ArrayList에 값을 넣는 방법
            list.Add(3); // 배열 1번째. 파라미터를 object로 받아들임. 즉, 어떤 타입이던 다 받아들임.
            list.Add(4); // 배열 2번째
            list.Add("string");
            list.Add('A');
            list.Add(false);
            list.Add(3.14);
            AA a = new AA();
            list.Add(a); // 클래스도 들어감.
            Console.WriteLine(list[0]); // 3출력 (배열처럼 index 또한 가능)
            // [단점] 이 모든 과정에서 Boxing이 한번씩 발생함. Boxing이 너무 많이 일어나게 되면, 시스템 부하가 발생할 가능성 있음
            // [ 개선방안 ] List 등장
            // ArrayList : object를 받아들임
            // List<데이터 타입> : ArrayList와 동일하게 동작하지만, 특정 데이터 타입에 대해서만 사용할 수 있음.

            // 2. ArrayList에 값을 빼는 방법
            list.Remove(3);
            foreach (object o in list)
            {
                Console.WriteLine(o); // 4만 출력됨.
            }
            Console.WriteLine(list[0]); // 4가 앞으로 땡겨져서, 4출력됨.
        }

        class AA
        {
            
        }
    }
}

[ Student.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using myLibrary;

namespace BCL_0809
{
    class Student:IComparable
    {
        public string stName { get; set; }
        public SexEnum stSex { get; set; }
        public int stScore { get; set; }

        public int CompareTo(object obj) // CompareTo 인터페이스 구현
        // ArrayList.Sort()를 부르면, CompareTo라는 메서드를 호출해서, 이 로직에 따라 클래스들을 모두 정렬한다.
        {
            Student st1 = obj as Student;
            // return stName.CompareTo(st1.stName); // 이름 비교 (오름차순) : 작으면 -1, 같으면 0, 크면 1 (반환값 int)
            return stScore - st1.stScore; // 성적순 (오름차순)
        }

        public override string ToString()
        {
            return $"{stName}[{stSex}][{stScore}]";
        }
    }
}

 


4. System.Collections.Generics.List<T>

- List<T>

: Generic을 사용한 ArrayList

: List<T>의 배경 - ArrayList의 Boxing / UnBoxing 문제를 해결하기 위해 나온, 새로운 컬랙션. 이 외에는 ArrayList와 동일

 

[ Program.cs ]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCL_0809
{
    class Program
    {
        static void Main(string[] args)
        {
            BCLex be = new BCLex();
            be.Run();
        }
    }
}

[ BCLex.cs ]

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using myLibrary;

namespace BCL_0809
{
    class BCLex
    {
        ArrayList students = new ArrayList(); // 학생 수가 어느정도 될지 모르기 때문에, ArrayList로 하기 효율적

        public void Run()
        {
            // ArrayList
            ArrayList list = new ArrayList();
            list.Add(1);
            int a = (int)list[0]; // 이와 같이 Unboxing을 할 때, 타입을 캐스팅해야하는 번거로움 발생

            // List<T>
            // ArrayList의 유연성, 장점들을 가져옴과 동시에, Boxing / Unboxing을 발생시키지 않기 때문에, 현재는 List<T>를 많이 사용함.
            List<int> list1 = new List<int>();
            list1.Add(1); list1.Add(2);
            a = list1[0]; // Unboxing의 문제 발생 X
            Console.WriteLine(list1.Count);
            Console.WriteLine(list1[0]);
            list1.Remove(1); // 값 : 1 하나 삭제
            Console.WriteLine(list1[0]);
            list.RemoveAt(0); // list[0] 삭제
            Console.WriteLine(list1.Count);

            // [ List<T>의 확장개념 1 ] Dictionary
            // List<T>와 비슷하지만, Dictionary는 <key, value>로 구성되는 클래스이다.
            Dictionary<int, string> dic = new Dictionary<int, string>();
            dic.Add(1, "홍길동"); // <key, value> 구성
            dic.Add(2, "황진이");
            // dic.Add(2, "가나다"); // key값이 중복되기 때문에, 오류 발생 


            // [ List<T>의 확장개념 2 ] SortedDictionary
            // <key, value>값을 넣어주면, key를 기준으로 자동 정렬해줌.
            SortedDictionary<int, string> sdic = new SortedDictionary<int, string>();
        }
    }
}

 


* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)
반응형