728x90

인터페이스


1
2
3
4
interface ILogger // 첫글자 대문자로 적는건 약속
{
    
}
cs

인터페이스는 public

객체생성이 이뤄지지않는 껍데기


상속받은 자식클래스에서는 부모클래스에서 명시한 기능을 구현해야함

실제구현은 자식클래스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Interface
{
    interface ICar
    {
        void drive(string msg);
    }
 
    interface IAirplane
    {
        void fly(string msg);
    }
 
    class Machine : ICar
    {
        public void drive(string msg)
        {
            Console.WriteLine(msg);
        }
    }
    class Machine2 : IAirplane
    {
        public void fly(string msg)
        {
            Console.WriteLine(msg);
        }
    }
    class MainApp
    {
        static void Main(string[] args)
        {
            Machine m1 = new Machine();
            Machine2 m2 = new Machine2();
        }
    }
}



죽음의 다이아몬드 

: c#에서 클래스 다중상속을 허용하지 않는 이유는 죽음의 다이아몬드 때문이다.

프로그램에서 같은 구문이 두 가지 이상의 의미로 해석될 여지가 있어서는 안 된다





하지만, 인터페이스를 사용하면 다중상속이 가능하다.


인터페이스를 사용하는 이유는 다음과 같다.

  • 자식단에서 구현할 메소드를 미리 구현
  • 메소드의 이름만 물려받고 자식클래스에서 재정의


IComparable 인터페이스

인터페이스는 모두 대문자 I 로 시작한다. IComparable 인터페이스는 비교할 때 사용되는 규약이다.

using System; using System.Collections; using System.Collections.Generic; namespace Study {     class Program     {         class Product         {             public string Name { getset; }             public int Price { getset; }             public override string ToString()             {                 return Name + " : " + Price + "원";             }         }               static void Main(string[] args)         {             List<Product> list = new List<Product>()             {                 new Product() {Name= "고구마", Price=1500},                 new Product() {Name= "사과", Price=2400},             };             list.Sort();             foreach(var item in list)             {                 Console.WriteLine(item);             }         }     } }


위의 프로그램은 Sort() 메서드가 정렬의 기준을 알지 못하기 때문에 오류가 발생한다. 이러한 기준을 정해주기 위해 IComparable 인터페이스를 구현한다.

해당 클래스에서 IComparable 인터페이스를 상속받아 사용한다.


IComparable에 커서를 놓고 Ctrl + .  단축키를 누르면 다음과 같이 인터페이스를 쉽게 구현할 수 있다. 



인터페이스 구현을 누르면 다음과 같이 CompareTo 메서드도 자동 생성된다.

public int CompareTo(object obj)
           {
               throw new NotImplementedException();
           }

CompareTo 메서드를 다음과 같이 변경해보자. obj가 Product이면 가격을 비교해 반환하겠다는 뜻이다. 오름차순으로 정렬된다.

public int CompareTo(object obj)
          {
              return this.Price.CompareTo((obj as Product).Price);
          }


내림차 순으로 정렬하고 싶다면 다음과 같이 변경하면 될 것이다.

public int CompareTo(object obj)
{
    return (obj as Product).Price.CompareTo(this.Price);
}


using 키워드와 IDisposable 인터페이스


아래 예제에서는 IDisposable 인터페이스를 상속받은 클래스 Dummy의 인스턴스를 using 블록의 괄호 내에서 생성한다.

Dispose() 메서드를 따로 호출하지 않아도 using 블록을 벗어날 때 호출된다.

using System;

namespace Study
{
    class Program
    {
        class Dummy : IDisposable
        {
            public void Dispose()
            {
                Console.WriteLine("Dispose() 메서드 호출");
            }
        }


        static void Main(string[] args)
        {
            using (Dummy dummy = new Dummy())
            {
 
            }
        }
    }
}



파일 입출력

using System.IO;

파일을 쓸 때 사용하는 StreamWriter는 IDisposable 인터페이스를 구현한 대표적인 클래스이다.


아래 파일 입출력 경로를 보면 @ 기호가 쓰인 것을 볼 수 있다.

문자열 내부에서 \ 기호는 특수한 의미를 지니기 때문에 원래는 \\를 사용해야 한다.


하지만 @ 기호를 붙여 문자열을 만들면 \\기호를 여러번 쓰지않아도 된다. 다만 내부에서 이스케이프 문자를 사용할 수 없게 된다.


using System;
using System.IO;
 
namespace Study
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = @"c:\tesst\test.txt";
            string textValue = "시간 - " + DateTime.Now;
 
            try
            {
                File.WriteAllText(path, textValue);
                Console.WriteLine("읽은 문자열 : " + File.ReadAllText(path));        
            }
            catch (Exception)
            {
 
                Console.WriteLine("파일을 읽거나 쓸 수 없습니다");
            }
        }
    }
}


스트림으로 쓰기


큰 용량의 파일을 한꺼번에 읽고 쓰는 것은 시스템에 부담이 가기 때문에 파일을 한 줄씩 읽고 쓸 수 있는 다양한 방법이 있다.

StreamWrite 클래스를 이용하면 스트림으로 쓸 수 있다.


StreamWrite 클래스는 TextWriter의 상속을 받는다.

// 요약:
//     System.IO.TextWriter를 구현하여 특정 인코딩의 스트림에 문자를 씁니다.
[Serializable]
[ComVisible(true)]
public class StreamWriter : TextWriter


TextWriter는 abstract class로 MarshalByRefObject, IDisposable의 상속을 받는다.

이를 통해 IDisposable 인터페이스를 구현한 클래스라는 것을 알 수 있다.

public abstract class TextWriter : MarshalByRefObjectIDisposable


다음은 StreamWrite 클래스로 파일에 여러 문자열을 쓰는 예제이다.

static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamWriter writer = new StreamWriter(path))
            {
                writer.WriteLine("안녕");
                writer.WriteLine("여러줄을");
                writer.WriteLine("입력해봄");
            }
 
            Console.WriteLine(File.ReadAllText(path));
        }



StreamReader 클래스로 한줄씩 읽기


아래는 잘못된 예제이다. 한 줄을 읽고 따로 값이 저장되지 않았기에 2번째 줄만 출력된다.

class Program
    {
        static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamReader reader = new StreamReader(path))
            {
                while (reader.ReadLine() != null)
                {                    
                    Console.WriteLine(reader.ReadLine());
                }
            }
        }
    }

바른 예

static void Main(string[] args)
        {
            string path = @"c:\test\test.txt";
 
            using (StreamReader sr = new StreamReader(path))
            {
                while (sr.Peek() >= 0)
                {
                    Console.WriteLine(sr.ReadLine());
                }
            }
        }


using을 사용하지 않은 예

class Program
{
    static void Main(string[] args)
    {
        string path = @"c:\test\test.txt";
 
        StreamReader reader = new StreamReader(path);
        string line;
 
        while ((line = reader.ReadLine()) != null)
                Console.WriteLine(line); 
    }
}


인터페이스, 내용 정리


인터페이스는 다중 상속이 가능하다.

public class MyConnection : Component, IDbConnection, IDisposable
{
}


인스턴스 변수를 가질 수 없다.

오류 : 인터페이스 멤버에는 정의를 사용할 수 없습니다.

interface IBasic
        {
            void TestMethod()
            {
 
            }
        }

인터페이스는 인스턴스 메서드를 가질 수 있다.


인터페이스는 클래스 변수를 가질 수 없다.

인터페이스는 클래스 메서드를 가질 수 없다.


인터페이스는 속성(Property)을 가질 수 있다.

'Study > C#' 카테고리의 다른 글

C# 네트워크 기본  (1) 2017.04.12
C# 예외처리, delegate  (0) 2017.04.10
C# 클래스, 메소드  (0) 2017.04.04
c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19
728x90
사용자 설정

// 설정을 이 파일에 넣어서 기본 설정을 덮어씁니다.
{
    "workbench.colorTheme""Atom One Light",
    "window.zoomLevel"0,
    "editor.renderWhitespace""none",
    "editor.renderControlCharacters"true,

  "editor.formatOnType"false,
  "editor.formatOnPaste"false,

"terminal.external.windowsExec""%COMSPEC%",
"terminal.integrated.cursorBlinking"false,
    "terminal.integrated.fontFamily""나눔고딕"
}



작업영역 설정

// 설정을 이 파일에 넣어서 기본 설정과 사용자 설정을 덮어씁니다.
{
     "editor.codeLens"false
}


728x90

윈폼에서 코드로 디자인

namespace CS_Windows_Forms
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            myButton.Text = "코드에서 변경!";
            myButton.Width = 200;
 
            for (int i = 0; i < 5; i++)
            {
                Button btn = new Button();
                Controls.Add(btn);
                btn.Location = new Point(2080 + i * 30);
                btn.Text = i + " 동적 생성";
            }
        }
    }
}

결과 화면



폼 디자인 코드에서 생성자 정의하기

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            Button btn = new Button();
            Controls.Add(btn);
            btn.Location = new Point(2080);
            Box box = new Box(btn);
            
        }
    }
    class Box
    {
        public Box(Button btn)
        {
            btn.Text = "버튼 전달";
        }
    }






생성자 정의하고 버튼으로 값 변경하기

namespace CS_Windows_Forms
{
    public partial class Form1 : Form
    {
        Box box;
 
        public Form1()
        {
            InitializeComponent();
 
            Button btn = new Button();
            Controls.Add(btn);
            box = new Box(btn);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            box.Area();
        }
    }
    class Box
    {
        Button btn;
 
        public Box(Button btn)
        {
            this.btn = btn;
            btn.Text = "버튼 전달";
        }
 
        public void Area()
        {
            if (btn.Width > 250)
                MessageBox.Show("더 이상 늘릴 수 없습니다");
 
            else
            {
                btn.Width += 10;
                btn.Height += 10;
            }
        }
    }
}




static 키워드

static이라는 키워드를 붙인 변수 또는 메서드는 프로그램을 실행하는 순간에 메모리가 올라가게 된다.

이때는 객체의 생성없이 메서드


Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Collections;
  7. using System.Threading;
  8.  
  9. namespace SScore
  10. {
  11.     class Test
  12.     {
  13.         public static int Abs(int n)
  14.         {
  15.             if (n < 0)
  16.                 return -n;
  17.  
  18.             else
  19.                 return n;
  20.         }
  21.     }
  22.  
  23.     class Program
  24.     {
  25.         static void Main(string[] args)
  26.         {
  27.             //Test test = new Test();
  28.             int num = Test.Abs(-10);
  29.             Console.WriteLine(num);
  30.         }
  31.     }
  32. }




C#의 구조체


c#에서도 구조체를 쓸 수 있다. c#에서는 구조체 멤버 변수도 기본적으로 private로 보호된다.


namespace SScore
{
    public struct MyPoint
    {
        public int x;
        int y;
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            MyPoint point;
            Console.WriteLine(point.x);
            Console.WriteLine(point.y); // 오류 : 보호 수준 때문에 'SScore.MyPoint.y'에 액세스할 수 없습니다.	
 
        }
    }
}


private 생성자

기본적으로 생성자는 public 접근 제한자를 쓰지만, 

생성자로 클래스의 인스턴스를 만들 수 없게 할 때는 private 생성자를 사용한다.

namespace SScore
{
    class Hidden
    {
        private Hidden();
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Hidden hidden = new Hidden();   // 오류
        }
    }
}

위와 같이 메인 메소드에서 인스턴스를 생성하려고 하면 다음과 같은 오류를 출력한다.

오류	: 'SScore.Hidden.Hidden()'은(는) abstract, extern 또는 partial로 
            표시되어 있지 않으므로 본문을 선언해야 합니다.

private 생성자를 이용하는 이유는 다음과 같다.


  • 정적 멤버(static member)만 가지고 있을때
  • 팩토리 메서드 패턴에서 팩토리 메서드로만 인스턴트를 생성하게 하고 싶을 때 (디자인 패턴중의 하나로, 부모 클래스에서 숨겨진 자식 클래스의 인스턴스를 만드는 형태)



정적 생성자 (static constructor)

정적 생성자는 정적(static)요소를 초기화 할때에 사용된다.

정적 생성자를 만들 때는 접근 제한자와 매개변수를 사용하지 못한다.

class Sample
{
    public static int value;
 
    static Sample()
    {
        value = 10;
        Console.WriteLine("정적 생성자 호출");            
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        Sample sample = new Sample();   // 이 때 한번만 호출
        Console.WriteLine();
        Console.WriteLine(Sample.value);
    }
}

출력 : 

정적 생성자 호출


10



readonly 키워드 (read only)

읽기 전용 키워드인 readonly로 변수를 선언하면 값을 변경할 수 없게 된다. 

class Sample
   {        
       public readonly int id=0;
 
       public Sample()
       {
           this.id++;
           Console.WriteLine("생성자 호출");            
       }
   }
 
   class Program
   {
       static void Main(string[] args)
       {
           Sample sample = new Sample();   
           Console.WriteLine(sample.id);
       }
   }

읽기 전용 필드의 값을 변경하려 할 때 다음과 같은 오류 메시지를 출력한다. 다만, 생성자에서는 readonly 키워드 변수도 값을 변경할 수 있다.



Getter와 Setter

값을 은닉화하면서 의도치 않은 값으로 초기화하는 걸 방지할 때에는 게터와 세터를 사용한다.

get 접근자는 값을 반환하고, set 접근자는 값을 할당한다.

class Unsigned
{
    private int num;
    public int Num
    {
        get { return num; }
        set
        {
            if (value > 0) { num = value; }
            else { Console.WriteLine("num변수는 양수여야 합니다."); }
        }
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        Unsigned unsigned = new Unsigned();
        unsigned.Num = -10;            
    }
}

Output : 

num변수는 양수여야 합니다.




게터와 세터를 더 쉽게 쓰려면 prop라고 입력하고  tap키를 두번 누르면 코드 조각이 자동으로 생성된다.

public int MyProperty { getset; }


propfull을 입력한 상태에서 tap키를 두 번 누르면 다음 형태의 코드 조각이 자동으로 생성된다.

private int myVar;
 
        public int MyProperty
        {
            get { return myVar; }
            set { myVar = value; }
        }




상속

using System;
using System.Collections;
using System.Collections.Generic;
 
namespace Study
{
    class Animal
    {
        public string name;
        public void Eat()
        {
            Console.WriteLine("냠냠");
        }
        public void Sleep()
        {
            Console.WriteLine("쿨쿨");
        }
    }
 
    class Dog : Animal
    {
        public void Bark()
        {
            Console.WriteLine("왈왈");
        }
    }
    class Cat : Animal
    {
        public void Meow()
        {
            Console.WriteLine("냐옹");
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
 
            List<Animal> Animals = new List<Animal>()
            {
                new Dog(){name="멍멍이"}, new Cat(){name="냐옹이"}
            };
 
            foreach(var item in Animals)
            {
                Console.WriteLine(item.name);
                item.Eat();
                item.Sleep();
 
                ((Dog)item).Bark();
            }
        }
    }
}

위의 프로그램을 실행시키면 다음과 같은 예외가 발생한다.


출력결과 :

멍멍이

냠냠

쿨쿨

왈왈

냐옹이

냠냠

쿨쿨


처리되지 않은 예외: System.InvalidCastException: 'Study.Cat' 형식 개체를 'Study.

Dog' 형식으로 캐스팅할 수 없습니다.


((Dog)item).Bark();

List에 Dog와 Cat 클래스의 인스턴스가 같이 존재하기 때문에 Cat 형식 개체를 Dog 형식 개체로 형변환 할 때 오류가 발생하는 것이다.

이를 해결하기 위해서는 조건문을 통해 item이 Dog객체인지 Cat 객체인지를 판별하게 해야 한다. 


is 키워드를 사용하면 특정 클래스의 객체일 때 true를 반환하게 된다.

다음과 같이 foreach 구문의 내용을 변경하고 실행해보자.


foreach(var item in Animals)
            {
                Console.WriteLine(item.name);
                item.Eat();
                item.Sleep();
 
                if (item is Dog)
                    ((Dog)item).Bark();
 
                else
                    ((Cat)item).Meow();
            }

실행 결과 :

멍멍이

냠냠

쿨쿨

왈왈

냐옹이

냠냠

쿨쿨

냐옹



섀도잉 (Shadowing)


변수의 이름이 겹칠 때 자신과 가장 가까운 변수를 사용한다. 아래 프로그램에서는 메인 메소드 내부가 된다.

class Program
   {
       public static int num = 20;
 
       static void Main(string[] args)
       {
           int num = 40;
           Console.WriteLine(num);
       }
   }

출력 결과 :

40



하이딩(Hiding)과 오버라이딩(Overriding)


부모 클래스와 자식 클래스 사이에는 이를 Hiding 이라고 한다. 상속하는 멤버가 아닌 자신의 클래스 내부의 변수를 사용한다.

숨겨진 변수나 메소드를 쓸 때는, 부모로 형변환을 통해 쓸 수 있다.


Code Snippet
  1. using System;
  2. namespace Study
  3. {
  4.     class Parent
  5.     {
  6.         public int q = 10;
  7.     }
  8.  
  9.     class Child : Parent
  10.     {
  11.         public new string q = "20";
  12.     }
  13.  
  14.     class Program
  15.     {
  16.         static void Main(string[] args)
  17.         {
  18.             Child child = new Child();
  19.             Console.WriteLine(child.q);
  20.             Console.WriteLine("" + ((Parent)child).q);
  21.         }
  22.     }
  23. }


출력결과 

20

10


static void Main(string[] args)
        {
            Child child = new Child();
            Parent parent = child;

            Console.WriteLine(child.q);
            Console.WriteLine(parent.q);
        }


메소드 하이딩

숨기려면 new 키워드를 사용해 하이딩 함을 명확하게 알려주는 것이 좋다. (에러는 띄우지 않지만 경고를 띄움)

메서드는 변수와 달리, 이름이 겹칠 때 하이딩할지 오버라이딩 할지 결정할 수 있기 때문이다.

using System;
namespace Study
{
    class Parent
    {
        public int variable = 273;
 
        public void Method()
        {
            Console.WriteLine("부모 메서드");
        }
    }
 
    class Child : Parent
    {
        public new void Method()
        {
            Console.WriteLine("자식 메서드");
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Child child = new Child();
            child.Method();
            ((Parent)child).Method();
        }
    }
}


메소드 오버라이딩

부모의 메서드를 virtual 키워드로 정의하면, 자식 클래스에서 override 될 수 있다.

이 때 자식의 메소드가 부모 메서드를 덮어 씌우고 새로 정의된다.

using System;
namespace Study
{
    class Parent
    {
        public virtual void Method()
        {
            Console.WriteLine("부모 메서드");
        }
    }
 
    class Child : Parent
    {
        public override void Method()
        {
            Console.WriteLine("자식 메서드");
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Child child = new Child();
            child.Method();
            ((Parent)child).Method();
        }
    }
}

Output :

자식 메서드

자식 메서드




sealed 키워드


클래스에 적용하면 : 절대 상속하지 못하게 함

메서드에 적용하면 : 더 이상 오버라이드하지 못하게 함



abstract(추상) 키워드


클래스에 적용하면 : 무조건 상속해서 쓰게 함. 해당 클래스 자체에서 인스턴스를 만들수 없게 됨


메서드에 적용하면 

: 반드시 오버라이드해서 쓰게 함, 이 때 메서드는 본문을 선언할 수 없으므로, 중괄호 {}를 쓰지 않고 곧바로 세미콜론 ; 으로 문장을 마침.

  abstract 메서드 선언을 위해 클래스도 abstract 클래스가 되어야 함. 따로 virtual 키워드를 쓰지 않아도 됨




Generic

using System;
namespace Study
{
    class Wanted <T>
    {
        public T value;
        public Wanted(T value)
        {
            this.value = value;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Wanted<string> wantedString = new Wanted<string>("String");
            Wanted<int> wantedint = new Wanted<int>(12);
 
            Console.WriteLine(wantedString.value);
            Console.WriteLine(wantedint.value);
        }
    }
}

T는 형식매개변수(Type Parametor)를 뜻하며, 하나의 약속이다. 이와 같이 변수 value 자료형을 원하는 자료형으로 지정 가능하다.




Out 키워드

using System;

namespace Study
{
    class Program
    {
        static void Main(string[] args)
        {
            string s="0404";
            int output;

            bool result = int.TryParse(s, out output);

            if (result)
            {
                Console.WriteLine(output);
            }
            else
                Console.WriteLine("숫자로 변환불가");
        }
    }
}


'Study > C#' 카테고리의 다른 글

C# 예외처리, delegate  (0) 2017.04.10
C# 인터페이스  (0) 2017.04.07
c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19
5/27 업무일지 c#학생성적관리(콘솔)  (0) 2016.05.27
728x90

Object 형식

어떤 형식의 데이터라도 object에 담아 처리할 수 있다. (int, long, char, bool, string...)


ex) object a=123;    object b=3.14f;    object c = true;    object d = "hello";




나머지 연산자 %

실수에 나머지 연산자 % 를 쓰는 건 추천하지 않는다.

static void Main(string[] args)
        {
            Console.WriteLine(5.0 % 2.2);
        }

정수라면 실행 결과로 2를 출력하겠지만 여기서는 0.6을 출력한다.

5.0 - (2.2 * 2) = 0.6 



문자열

문자열은 다음과 같이 더할 수 있다.

하지만 문자 (한 글자)는 더할 수 없고, 문자를 숫자로 생각해 더하게 된다.


문자를 연결하고 싶다면 ' '로 감싸지말고 문자열을 뜻하는 " " 로 감싸야한다. 

static void Main(string[] args)
      {
          Console.WriteLine("가나다" + "라마" + '바');
          Console.WriteLine("안녕하세요" [0]);
          Console.WriteLine("안녕하세요" [2]);
      }

출력 결과 :

가나다라마바



숫자와 문자열을 더하면 자동으로 문자열로 형변환된다.

하지만 숫자와 '문자'를 더하면 아스키 코드값으로 출력된다.

static void Main(string[] args)
       {
           Console.WriteLine(2 + '3' + "4");
           Console.WriteLine(2 + '3' + '4');
       }

출력결과 :

534

105




다른 자료형을 bool로 변환

다음과 같은 경우 23번째 줄에서 에러를 출력한다.
Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             Console.WriteLine(bool.Parse("True"));
  4.             Console.WriteLine(bool.Parse("true"));
  5.             Console.WriteLine(bool.Parse("test"));
  6.         }


bool은 true, false 데이터를 다루며 1바이트 크기의 type이다. (1비트만으로 표현가능하지만 컴퓨터가 기본적으로 바이트 단위를 사용하므로)



오버플로우 확인하기

static void Main(string[] args)
        {
            int num = int.MaxValue;
            Console.WriteLine(num+1);
        }   

오버플로우를 일으키며 -2147483648 이라는 값을 출력한다.

다음과 같이 double로 형변환하면 해결 가능하다.

static void Main(string[] args)
       {
           int num = int.MaxValue;
           Console.WriteLine((double)num+1);
       }   

혹은 num을 선언할 때 unsigned 자료형으로 선언해 해결할 수도 있다.

uint num = int.MaxValue;




음수의 음수?


Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             Console.WriteLine(-(-1));
  4.             
  5.             int output = int.MinValue;
  6.             Console.WriteLine(-(output));
  7.             Console.WriteLine(-(-2147483648));
  8.         }


위 소스 25번째 줄에서 다음과 같은 오류를 일으킨다.


checked 모드에서 컴파일하면 작업이 오버플로됩니다.

25번째 줄을 주석처리하면 다음과 같은 결과가 출력된다.

출력결과 :
1
-2147483648


키 입력을 출력
static void Main(string[] args)
        {
            Console.ReadKey();
        }
위의 예제를 실행하면 사용자가 누른 키를 콘솔 화면에 표시한다.


ReadKey() 메서드는 ConsoleKeyInfo 객체를 받게 되고, 이 객체 내부의 KeyChar 속성을 통해 입력 키를 알아낸다.
public static ConsoleKeyInfo ReadKey();
public static ConsoleKeyInfo ReadKey(bool intercept);





지정된 크기의 배열 생성


값을 넣지않고 초기화하면 기본 값으로 공간이 채워진다. (숫자 자료형은 0, 문자열 자료형은 빈 문자열, 객체는 null로 초기화)

static void Main(string[] args)
       {
           int[] intArray = new int[100];
 
           Console.WriteLine(intArray[0+ "\n" + intArray[99]);
       }


배열 요소를 마지막 요소에서부터 출력

static void Main(string[] args)
        {
            int[] intArray = { 123456 };
 
            for (int i = intArray.Length - 1; i >= 0; i--)
                Console.Write(intArray[i] + " ");
        }

출력결과 : 6 5 4 3 2 1



List 클래스를 이용한 가변적인 크기의 배열 생성

List<> 에서 <>안에는 Generic으로 어떤 자료형인지를 미리 알려준다.

static void Main(string[] args)
       {
           Random random = new Random();
 
 
           List<int> list = new List<int>();
 
           for (int i = 0; i < 6; i++ )
               list.Add(random.Next(1100));
 
           for (int i = 0; i < list.Count; i++)
               Console.Write(list.ElementAt(i) + " ");
       }   


List활용예제

이름, 학점, 영어 입력받고 학점 4.0 이상이고 영어점수가 900점 이상인 리스트를 출력


C#에서 클래스는 앞글자 대문자, 변수명은 소문자를 쓴다. (절대 규칙은 아니지만 권장)


이외의 네이밍 규칙 http://zepeh.tistory.com/115


Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Collections;
  7.  
  8.  
  9. namespace SScore
  10. {
  11.     class Student
  12.     {
  13.         public string name;
  14.         public double grade;
  15.         public int eng;
  16.     }
  17.     class Program
  18.     {
  19.         static void Main(string[] args)
  20.         {
  21.             List<Student> list = new List<Student>();
  22.  
  23.             for (int i = 0; i < 3; i++)
  24.             {
  25.                 Student s = new Student();
  26.  
  27.                 Console.Write("이름:");
  28.                 s.name = Console.ReadLine();
  29.                 Console.Write("학점:");
  30.                 s.grade = double.Parse(Console.ReadLine());
  31.                 Console.Write("영어:");
  32.                 s.eng = int.Parse(Console.ReadLine());
  33.  
  34.                 list.Add(s);
  35.             }
  36.             for (int i = 0; i < list.Count; i++)
  37.             {
  38.                 if (list.ElementAt(i).grade < 4.0 || list.ElementAt(i).eng < 900)
  39.                     break;
  40.                    
  41.  
  42.                 Console.WriteLine(list.ElementAt(i).name + "," +
  43.                     list.ElementAt(i).grade + "," +
  44.                     list.ElementAt(i).eng);                
  45.             }
  46.         }
  47.     }
  48. }



Generic

제네릭은 클래스 자료형을 지정하는 기능이다.  형식 매개 변수 T를 사용 하고 선언할 때 Name<T>의 형태를 가진다. 
두 개 이상을 지정하려면 T, U와 같이 쓴다.

namespace Generic
{
    class Wanted<T, U>
    {
        public T value;
        public U value2;
 
        public Wanted(T value, U value2) 
        {
            this.value=value;
            this.value2 = value2;
        }
    }    
    class Program
    {
        static void Main(string[] args)
        {
            Wanted<stringint> StringAndInt = new Wanted<stringint>("String"32);
 
            Console.WriteLine(StringAndInt.value + "\n" + StringAndInt.value2);
        }
    }
제네릭의 가장 일반적인 사용은 컬레션 클래스를 만드는 것이지만, 클래스나 인터페이스, 메서드, 대리자에도 사용된다.


Indexer
인덱서를 이용하면 클래스나 구조체의 인스턴스를 배열처럼 인덱싱할 수 있다.
인덱서는 프로퍼티와 유사하지만 반드시 인스턴스 멤버로만 존재하여야 한다. (static 선언 불가)
class Sign
{
    public int this[int i]
    {
        get { return (-i); }
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        Sign sign = new Sign();
        Console.WriteLine(sign[15]);
    }
}

'Study > C#' 카테고리의 다른 글

C# 인터페이스  (0) 2017.04.07
C# 클래스, 메소드  (0) 2017.04.04
headfirst c#-wpf  (0) 2016.11.19
5/27 업무일지 c#학생성적관리(콘솔)  (0) 2016.05.27
c# 클래스 복습2  (0) 2016.05.23
728x90

DOM(Document Object Model)


DOM은 HTML에서 정의하는 것이나, 자바스크립트의 일부로 구현된 것이 아닌, 주요 브라우저 벤더들이 구현하는 것이다.

DOM은 HTML 페이지에 대한 모델을 구성하거나 페이지에 접근하고 수정하는 영역을 담당한다.




DOM은 브라우저가 DOM tree를 이용하여 이 모델을 구성하는 방법을 명시한다.




DOM 쿼리 캐싱하기

스크립트가 같은 요소를 한 번 이상 사용할 필요가 있다면 요소의 위치를 변수에 저장하는 것이 좋다.

같은 요소를 탐색하기 위해 DOM 트리를 여러번 조회하는 것을 방지할 수 있기 때문이다.


이런 방법을 Caching 이라고 한다. DOM 트리내의 객체에 대한 Reference(노드의 위치)를 저장한다고도 한다.



var itemOne = getElementById('one');



사용한 메서드가 하나 이상의 노드를 리턴할 수 있다면 탐색 조건에 일치하는 노드가 하나 뿐이더라도,

항상 노드의 collection인 NodeList 객체를 리턴한다. 



Nodelist 객체에서 요소 선택하기


var elements = getElementById('hot');

if (elements.length >=1) {
    var firstItem = elements[0];    // elements.item(0);
}


배열 문법이 item() 메서드보다 빠르게 동작한다.



CSS 선택자를 이용해 요소 선택하기

querySelector는 첫번째 요소만 리턴하고, querySelectorAll은 NodeList 객체를 리턴한다.



// querySelector 메서드는 조건에 일치하는 첫 번째 요소만 리턴한다.
var el = document.querySelector('li.hot');
el.className = 'cool';

// querySelectorAlll 메서드는 NodeList 객체를 리턴한다.
// 조건에 일치하는 두 번째 (목록에서는 세 번째) li 요소를 선택하여 특성을 변경한다.
var els = document.querySelectorAll('li.hot');
els[1].className = 'cool';



공백 노드


일부 브라우저는 요소 사이사이의 공백을 텍스트 노드로 추가하기 떄문에 DOM을 탐색하는데 방해가 된다. 

(ie는 공백문자를 무시해 텍스트 노드를 추가 생성하지 않음)



페이지 내의 공백 문자를 모두 제거한다면 페이지 크기가 작아져 더욱 빠르게 클라이언트에 전송되거나 로드할 수 있지만,

코드를 읽기 어려워진다.


jQuery라는 자바스크립트 라이브러리는 이 문제를 알아서 해결해준다. 



텍스트 노드에 접근해서 변경하기


var itemTwo = document.getElementById('two');  // 목록의 두 번째 아이템을 가져온다.

var elText  = itemTwo.firstChild.nodeValue;    // 텍스트 내용을 가져온다.
//elText = elText.replace('잣', '양배추');
itemTwo.firstChild.nodeValue = elText.replace('잣''양배추');  // 잣을 양배추로 변경한다.




HTML 콘텐츠 추가 / 제거하기


DOM 조작방식은 innerHTML 속성을 이용하는 방법보다 보안상 안전하다. 하지만 더 많은 코드를 작성해야하며, 더 느리게 동작할 수도 있다.

innerHTML 속성은 전체 콘텐츠에 접근 및 수정할 때 적합하다.



요소로부터 HTML을 가져올 때 innerHTML 속성을 이용해 요소의 모든 콘텐츠를 하나의 문자열로 가져올 수 있다.

이 때 마크업도 포함된다.


'<em>신선한</em>무화과'



아래는 마크업을 포함한 문자열을 수정하는 예제이다.


// 목록의 첫 번째 아이템을 변수에 저장한다.
var firstItem = document.getElementById('one');

// 아이템의 콘텐츠를 가져온다.
//var itemContent = firstItem.innerHTML;

// 첫 번째 아이템의 콘텐츠를 링크로 수정한다.
firstItem.innerHTML = '<a href=\"http://example.org\">' + firstItem.innerHTML + '</a>';




728x90

해커스쿨에서 컴퓨터와 프로그래밍의 역사 공부

http://www.hackerschool.org/Sub_Html/HS_Community/?Type=Middle&More_Size=-90



텔넷에서 리눅스 공부

http://www.hackerschool.org/Sub_Html/HS_FTZ/html/ftz_menual.html





한글PuTTY



접속형식 Telnet / Host Name : ftz.hackerschool.org





728x90


타입 강제와 약한 형식화


자바스크립트는 내부적으로 데이터 타입을 변환하여 작업을 완료할 수 있다.

이를 type coercion (타입 강제) 이라고 한다.


'1' > 0 이라는 구문에서 문자열 1이 숫자 1로 강제 변환되고 true를 return할 수 있다.


강력한 형식화를 사용하는 일부 다른 프로그래밍 언어와 달리, 자바스크립트는 약한 형식화를 사용한다.


따라서 의도하지 않은 값을 만들어내는 것이 싫다면 동등 비교 연산자 ==, != 를 쓰는 것보다 

일치 비교 연산자 ===, !== 를 쓰는 것이 권장된다.



===, !== 는 같은 값인지 여부 뿐만 아니라 데이터 타입도 비교한다.




단축 평가 값


OR 연산자를 사용할 때는 true를 리턴할 가능성이 높은 코드를 첫번째 조건으로 작성하고,

AND 연산자를 사용할 때는 false를 리턴할 가능성이 높은 코드를 첫번째 조건으로 작성한다.


단축 평가 기버은 페이지 내에 요소가 존재하는지를 검사하는 용도로 활용이 가능하다.



자바스크립트에서 true와 false

자바스크립트에서 숫자 0이나 빈 값, 값을 대입하지 않은 변수는 false로 취급된다.


반면에 내용을 가진 문자열이나 0이 아닌 다른 숫자는 true이다.



단항 연산자에서 

if( document.getElementById('header') ) 라는 구문이 있다면


ifdocument.getElementById('header'== true ) 로 생각하기 쉽다.

하지만 boolean값인 true와 document.getElementById('header') 가 
리턴되는 객체(true로 취급될 순 있어도)는 엄연히 다른 값이다!

논리 연산자는 항상 true나 false를 리턴하지 않는다. 

처리를 중지하게 된 계기가 된 값을 리턴하거나, 
그 값이 실제로 boolean type이 아니더라도 true나 false로 취급될 수 있다.


예약된 데이터 타입

단순혹은 기본 데이터 타입인 String, Number, Boolean, Undefined, Null

복합데이터 타입인 Object



true, false는 boolean 값이므로 (false === 0)은 

type이 일치하지 않으므로 false를 return한다.


(undefined == null)이 true지만, (undefined === null)은 false이다. 

boolean과 마찬가지로 undefined도 하나의 형식이기 때문이다.





'Study > JavaScript' 카테고리의 다른 글

[JavaScript] Proxy  (0) 2024.04.03
[JavaScript] 기본  (0) 2021.10.18
html + javascript 기초  (0) 2021.01.07
자바 스크립트 기초 - 함수, 메서드, 객체  (0) 2017.03.27
728x90

함수의 매개변수와 인수의 비교


function getArea(width, height) {

return width * height;

}


위 함수내에서 변수 이름과 동일하게 동작하는 (width, height) 가 매개 변수이다.


wallWidth = 3;

wallHeight = 5;

getArea(wallWidth, wallHeight);


위에서 함수가 호출될 때 전달되는 값이 바로 인수이다.



함수로부터 여러 값 전달받기


1
2
3
4
5
6
7
8
9
function getSize(width, height, depth) {
  var area = width * height;
  var volume = width * height * depth;
  var sizes = [area, volume];
  return sizes;    
}
 
var areaOne = getSize(323) [0];
var volumeOne = getSize(323) [1];
cs


8행의 areaOne 변수는 3 * 2 의 연산결과인 사각형 면적을 저장하며, size 배열의 첫번째 값[0] 이다.




익명 함수와 함수 표현식


자바 스크립트 해석기가 표현식을 필요로 하는 곳에 함수를 전달하면, 이 함수는 표현식으로 처리된다. 

(var area = 3*5와 같은 선언이 아닌 함수를 대입하였다)


이런 함수를 함수 표현식이라고 하며, 함수 표현식을 사용할 때는 대부분 함수 이름을 생략한다.


1
2
3
4
5
var area = function (width, height) {
return width * height;
};
 
var size = area(34);
cs


위와 같이 함수의 선언과 함께, 변수에 저장할 때 함수 이름을 생략 가능하다. 

이처럼 이름이 없는 함수를 익명 함수(anonymous function)이라고 한다.


5행에서 이 익명 함수를 변수의 이름으로 호출하는 것을 볼 수 있다.



즉시 호출 함수 표현식 

IIFE(Immediately Invoked Function Expressions: “이피( Iffy )”라고 발음)


이름이 부여되지 않은 함수를 의미한다. 자바 스크립트 해석기가 함수 정의를 만났을 때 단 한번 실행된다.


1
2
3
4
5
var area = (function () { 
    var width = 3;
    var height = 2;
    return width * height;
() );
cs

위의 변수 area는 나중에 호출할 목적으로 함수를 저장하는 것이 아닌, 함수가 리턴한 값만 저장하게 된다.


초록색 괄호는 자바스크립트 해석기에게 함수가 즉시 호출되어야 함을 알린다.


빨간색 괄호그룹화 연산자 이며, 해석기가 전체 코드를 표현식처럼 취급하도록 하기 위해 둘러싼 괄호이다.



이러한 익명 함수와 즉시 호출 함수는 어떤 작업 내에서 단 한번만 실행될 필요가 있을 때 사용된다.

예를 들면 다음과 같다.


  • 함수를 호출할 때 인수로 전달하기 위해(호출할 함수에 전달할 값을 계산하기 위해)
  • 객체의 속성에 값을 대입하기 위해
  • 동일한 변수 이름을 사용하는 두 스크립트 간의 이름 충돌을 방지하기 위해
  • 이벤트 핸들러와 리스너 내부에서 이벤트가 발생했을 때 작업을 처리하기 위해

즉시 호출 함수는 주로 일련의 코드를 감싸기 위해 사용한다.
scope라는 개념 하에 익명 함수 내부에 선언된 모든 변수들은 스크립트의 다른 부분에 선언된 같은 이름의 변수로부터 보호된다.



변수의 범위 scope


함수내부에서 var 키워드를 이용해 함수 내부에 선언하면 해당 함수 내부에서만 사용할 수 있다. 

이를 지역 변수, 함수 수준 변수라고 하며, 지역 범위, 함수 수준 범위를 가지고 있다고 표현한다.


함수 바깥 부분에서 선언한 변수는 전역 변수이며, 전역 범위(global scope)를 가진다.


var 키워드를 사용하지 않아도 전역변수로 취급된다.




객체란?

현실 세계에서 인지한 물체에 대한 모델을 만들기 위해 변수와 함수를 그룹화 한 것.


객체의 일부로 선언된 변수는 속성(property)이라고 부른다.

객체의 일부로 선언된 함수는 메서드(method)라고 부른다.


다음은, 축약형 표기법을 이용해 객체 생성 

(app간에 데이터를 저장하거나 전송할 때 또는 페이지를 위한 정보를 설정하는 설정 객체나 전역 객체를 생성할 때 권장됨)


var hotel = {
  name : 'Quay',
  rooms : 40,
  booked : 25,
  checkAvailability : function() {
    return this.rooms - this.booked
  }
};


객체 내에서의 속성 이름을 key라고 부른다. 이 키를 통해 해당 값에 접근하기 때문에 중복은 불가하다.

: 왼쪽이 속성 이름이며, 오른쪽이 값이다. 여러 개의 속성을 선언할 때 쉼표로 구분한다.


객체에 접근할 때는 멤버 접근 연산자 . 을 통해 접근한다.


1
var hotelName = hotel.name;
cs


또는 아래와 같이 대괄호 문법을 통해 접근 가능하다.

1
var hotelName = hotel['name'];
cs



빈 객체를 축약형 표기법으로 생성

1
var hotelName = {};
cs



객체 수정하기


1
hotel.name = 'Park';
cs


대입 연산자를 통해 새로운 속성값을 대입하면 된다. 객체가 가지고 있지 않은 속성에 대입하려하면, 객체에 새 속성이 추가된다.

대괄호 문법으로도 속성값 변경이 가능하다.


1
hotel['name'= 'Park';
cs


속성 제거하기

다음과 같이 delete 키워드를 이용한다.


1
delete hotel.name;
cs


속성 값만 제거하기

다음과 같이 빈 문자열을 대입한다.

1
hotel.name = '';
cs



객체 생성자


function Hotel(name, rooms, booked) {
  this.name = name;
  this.rooms = rooms;
  this.booked = booked;
  
  this.checkAvailability = function() {
    return this.rooms - this.booked;
  }
}

위 함수는 호텔을 표현하는 새 객체를 만들기 위한 템플릿처럼 사용된다.
객체 생성자 함수의 이름은 주로 대문자로 시작한다. (일반적으로 함수 이름은 소문자로 시작한다)

객체 생성자에서 각각의 구문은 새로운 속성이나 메소드를 대입하는 것이므로 semi-colon으로 끝을 맺는다.

new 키워드를 이용한 객체 생성

quayHotel과 parkHotel 객체 생성,  Hotel('Quay'4025)는 생성자 함수이다.

var quayHotel = new Hotel('Quay'4025);
var parkHotel = new Hotel('Park'12077);


아래 예제에서는 생성자 함수를 이용해 hotel 이란 이름의 빈 객체를 생성한다.
객체 생성후엔 속성과 메소드를 대입하는데, 이미 가지고 있는 속성이 있다면 값을 덮어 쓰게 된다.

// Set up the object
var hotel = new Object();

hotel.name = 'Park';
hotel.rooms = 120;
hotel.booked = 77;
hotel.checkAvailability = function() {
  return this.rooms - this.booked;  
};

var elName = document.getElementById('hotelName'); // Get element
elName.textContent = hotel.name;                   // Update HTML with property of the object

var elRooms = document.getElementById('rooms');    // Get element
elRooms.textContent = hotel.checkAvailability();   // Update HTML with result of method




객체 생성자 표기법을 이용해 객체 생성 및 사용하기


// 호텔 객체를 위한 생성자 함수 템플릿을 정의

function Hotel(name, rooms, booked) {
  this.name = name;
  this.rooms = rooms;
  this.booked = booked;
  this.checkAvailability = function() {
    return this.rooms - this.booked;
  };
}


// 두 개의 다른 호텔 객체 인스턴스 생성

var quayHotel = new Hotel('Quay'4025);
var parkHotel = new Hotel('Park'12077);


// 이미 존재하는 변수에 += 연산자를 사용해 다른 데이터를 덧붙인다.
var details1 = quayHotel.name + ' 남은 방: ';
    details1 += quayHotel.checkAvailability();
var elHotel1 = document.getElementById('hotel1');
elHotel1.textContent = details1;

var details2 = parkHotel.name + ' 남은 방: ';
    details2 += parkHotel.checkAvailability();
var elHotel2 = document.getElementById('hotel2');
elHotel2.textContent = details2;



한글 때문에 html의 글자가 깨진다면 html 소스에 다음 코드를 추가한다.

<meta charset="utf-8">


속성을  추가하거나 제거하기
이미 hotel 객체의 인스턴스를 생성한 후에도 속성을 추가하거나 제거할 수 있다.

var hotel = {
  name : 'Park',
  rooms : 120,
  booked : 77
};

// gym, pool 속성을 추가하고 boolean 값을 대입 후 booked 속성을 제거

hotel.gym = true;
hotel.pool = false;
delete hotel.booked;




this 키워드


var shape = {
  width: 600,
  height: 400,
  getArea: function() {
    return this.width * this.height;
  }
}
이 키워드는 항상 단 하나의 객체를 참조하며, 함수를 실행하고 있는 객체를 가리킨다.
바꿔 말해, 함수 내부에서 this 키워드가 사용될 때, this 키워드는 함수를 감싸는 함수가 소속된 객체를 가리킨다는 것이다.

한 함수가 다른 함수 내에 중첩되어 있는 경우에는, 첫번째 함수 내의 변수에 this 키워드의 값을 저장해두고, 

중첩된 함수내에서 이 변수를 this 키워드 대신 사용하는 것이 권장된다.



function windowSize() {
  var width = this.innerWidth;
  var height = this.innerHeight;
  return [height, width];
}

스크립트의 최상위 수준 (다른 객체나 함수 내부가 아닌 곳)에 함수를 선언하면, 이 함수는 global scope 혹은 global context에 포함된다.

이 global context에 속한 객체는 window 객체이므로 this 키워드를 사용하면 window 객체를 가리키게 된다.



아래 예제에서는 축약형 표기로 객체를 생성했다. 하지만 전역 범위에 선언된 showWidth() 함수는 객체의 멤버가 아니므로,

이 경우 전역 변수 width 를 가리킨다.


var width = 600;


var shape = {
    width: 300
};


var showWidth = function() {
  document.write(this.width);
};


showWidth();



메서드로서의 함수 표현식


아래 예제의 11행은 익명 함수가 shape 객체의 메서드로 사용될 것이며, 그 이름이 getWidth() 함수가 될 것임을 표현한 것이다.

getWidth() 함수를 호출하면, 실제로 showWidth() 함수가 호출된다. 
이 때는 그 함수가 속한 객체가 shape이므로 shape 객체의 속성 width의 값 300을 가리키게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
var width = 600;
 
var shape = {
    width: 300
};
 
var showWidth = function() {
  document.write(this.width);
};
 
shape.getWidth = showWidth;
shape.getWidth();
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
var funcThis = null
 
function Func(){
    funcThis = this;
}
var o1 = Func();
if(funcThis === window){
    document.write('window <br />');
}
 
var o2 = new Func();
if(funcThis === o2){
    document.write('o2 <br />');
}
cs


결과

1
2
window 
o2
cs



6행에서는 함수를 호출한 것이므로 함수에서의 this는 그 함수가 속한 객체, 여기서는 window 객체를 가리킨다.

11행에서는 new 키워드를 통해 생성자를 통해 만들어진 객체에서의 this 는 그 만들어진 객체 자신을 가리킨다.



배열도 객체이다


호텔 방의 가격을 객체로 표현한 경우


costs = {
  room1: 420,
  room2: 460,
  room3: 230,
};


이 경우 room1~3 속성과 각각의 값을 가진다.

호텔 방의 가격을 배열로 표현한 경우


costs = [420460230];

이 경우 index 0~2 와 각각의 값을 가진다.


객체 내에 배열을 가지거나 배열 내에 객체를 가질 수 있다.

객체 내의 배열
costs.room1.items[0];

배열 내의 객체
costs[2].phone;


배열의 2번째 index  { accom: 620, phone: 60 }




내장 객체

브라우저 객체 모델, 문서 객체 모델, 전역 자바스크립트 객체



브라우저 객체 모델

window.screen.width;


문서 객체 모델

documnet.getElementById('one');


전역 자바스크립트 객체

hotel.toUpperCase();    


: string 객체가 전역 객체로 제공되며 문자열 자체가 마치 String 객체인 것처럼 동작하기 때문에 wrapper object라고도 함



예약된 데이터 타입


단순혹은 기본 데이터 타입인 String, Number, Boolean, Undefined, Null

복합데이터 타입인 Object



배열이 객체라는 것은 .length라는 속성을 통해 확인할 수 있다.




'Study > JavaScript' 카테고리의 다른 글

[JavaScript] Proxy  (0) 2024.04.03
[JavaScript] 기본  (0) 2021.10.18
html + javascript 기초  (0) 2021.01.07
자바스크립트 - 의사 결정  (0) 2017.03.28
728x90

열거형

열거형의 멤버는 차례대로 0의 값을 갖는다. 하지만 선언할 때 초기값을 원하는 값으로 설정할 수도 있다.

#include <stdio.h>
 
enum season
{
	spring = 1, summer, fall, winter
}Season;
 
void main(void)
{	
	printf("계절을 고르세요 -> \n 1.봄  2.여름  3.가을  4.겨울 : ");
	scanf("%i" , &Season);
	
	switch (Season)
	{
	case spring:
		printf("봄은 꽃 피는 계절\n");
		break;
	case summer:
		printf("여름은 바캉스의 계절\n");
		break;
	case fall:
		printf("가을은 낙엽이 밟히는 계절\n");
		break;
	case winter:
		printf("겨울은 눈 내리는 계절\n");
		break;
	default:
		break;
	}
}


auto 키워드


원래 C에서의 의미와 C++에서의 의미

https://dojang.io/mod/page/view.php?id=803


c에서도 다음과 같이 선언하고 실행 결과를 얻을 수 있다. (http://codepad.org/kzaEWQRj)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

auto func() {
	return 10;
}

void main() {
	int a;
	a = func();
	printf("%d \n", a);
}

Output:
1
10 


구조체 변수를 함수 매개변수에 사용하기


구조체 변수는 대입 연산이 가능하므로 함수의 매개변수로 주거나 반환받을 수 있다.

예를 들어, 함수에서 여러 개의 값을 구조체로 묶어 동시에 반환할 수 있다.


두 변수의 값을 바꾸는 함수는 포인터가 필요하지만, 구조체 변수를 사용해 값을 주고 받으면 

포인터 없이도 두 변수의 값을 바꾸는 함수를 만들 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
 
typedef struct
{
    double left;
    double right;
} vision;
 
vision exchange(vision);    // 구조체를 통해 두 변수의 값을 교환
 
int main(void) {
    vision robot;
    printf("시력 입력 : ");
    scanf_s("%lf %lf"&(robot.left), &(robot.right));
    robot = exchange(robot);
    printf("바뀐 시력 : %.1lf, %.1lf \n", robot.left, robot.right);
 
    return 0;
}
 
vision exchange(vision robot)
{
    double temp;
    temp = robot.left;
    robot.left = robot.right;
    robot.right = temp;
 
    return robot;
};
cs


Output :

시력 입력 : 0.5 1.5

바뀐 시력 : 1.5, 0.5




비트 필드 구조체

1
2
3
4
5
6
struct children
{
    unsigned int son 2;
    unsigned int daughter 2;
    unsigned int pet 3;
};
cs

비트 필드 구조체를 이용하면, 멤버의 크기를 비트 단위로 설정할 수 있다. colon(:) 뒤의 숫자가 멤버가 사용하는 비트 수 이다.

저장할 수 있는 값의 범위는 비트 수에 따라 2의 n승. (2비트는 0~3, 3비트는 0~7)


signed를 이용하면 음수도 저장할 수 있으나, 부호비트 처리방식이 시스템에 따라 다를 수 있으므로 unsigned를 주로 사용



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
typedef struct
{
    unsigned int son : 4;
    unsigned int daughter : 4;
} children;
 
int main(void) {
    children child = { 12 };    // 구조체 변수 초기화
    int sum;
 
    printf("children 구조체 크기 : %d 바이트 \n"sizeof(child) );
    sum = child.son + child.daughter;
    printf("자식 수 : %d \n", sum);
}
cs

Output : 

children 구조체 크기 : 4 바이트

자식 수 : 3


자료형은 정수형만 사용하며, 멤버가 가질 수 있는 최대 비트 수를 결정

unsigned int형은 최대 32비트까지만 지정 가능. 

위에서 children 구조체 멤버의 비트 수를 모두 합해도 7비트지만, unsigned int형 크기인 32비트가 메모리에 할당된다.

(멤버가 할당되지 않은 영역은 사용하지 않는 영역이 됨)


만약 기본 할당된 영역을 넘어서면 새로운 바이트 공간을 사용하면서 멤버가 할당되게 된다.


패딩 비트 (사용하지 않는 공간)

만약, 멤버의 이름을 생략하면 사용하지 않는 패딩 비트가 된다.



                 

 

 

 b

 b

 b

 패딩

  비트

 a


 

 

 

 

 c 

 c

 c 

 c 



배열을 멤버로 선언하거나 멤버의 주소를 직접 구할 순 없다.

키보드로 입력을 받아들이려면 별도의 변수에 입력한 후에 멤버에 대입해야 한다.

6행의 주석을 제거하고 실행한다면, 에러가 난다. 비트 필드 구조체 멤버의 주소를 직접 구할 수 없기 때문이다.


1
2
3
4
5
6
7
8
int main(void) {
    children child;
    int temp;
    scanf("%d"&temp);
    child.son = temp;
    //* scanf("%d", child.son); /* 에러 */
    printf("%d \n", child.son);
}
cs



구조체 포인터와 -> 연산자


child. 과 같이 구조체 멤버에 직접 접근하는 거 외에도, 구조체를 가리키는 포인터를 통해 멤버에 접근할 수도 있다.


구조체 변수 전체의 주소를 구해, 그 값을 저장하는 것이 바로 구조체 포인터이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
typedef struct
{
    int son;
    int daughter;
} children;
 
int main(void) {
    children child = { 12 };
    children *ps = &child;
        
    printf("아들은 몇 명? : %d \n", (*ps).son);
    printf("딸은 몇 명? : %d \n", ps->daughter);
}
cs


children 구조체를 가리키는 포인터 변수 ps에, child의 주소 연산 (&)을 통해 구한 변수의 주소값을 저장하는 것이다.

그러면 ps는 구조체 변수 child를 가리키게 된다.


멤버 접근 연산자인 . 연산자가 * 연산자 보다 우선 순위가 높기 때문에, * 연산자가 먼저 수행될 수 있도록 다음과 같이 괄호로 묶는 것이다.

(*ps).son


이것을 사용하기 편하게 해주는 것이 -> 연산자이다.

(*ps).son    ==      ps->son


 

'Study > C' 카테고리의 다른 글

size_t  (0) 2017.05.29
C 복습-콘솔 입출력  (0) 2017.02.11
c 복습  (0) 2016.11.03
파일의 분할과 헤더파일의 디자인  (0) 2016.08.30
선행처리기와 매크로2  (0) 2016.08.30
728x90

미디어 쿼리

css 모듈 중 하나로 접속 기기에 따라 특정한 CSS 스타일을 사용하도록 해줌

1
[ONLY | NOT] @media 미디어 유형 [AND 조건]*[AND 조건]
cs


미디어 유형의 예 :

all : 모두

print : 인쇄장치

screen :  컴퓨터 스크린


미디어 쿼리의 조건에는 뷰 포트의 너비(width, height)나 단말기 브라우저의 너비(device-), 

단말기 방향(landscape, portrait) 등을 속성으로 사용할 수 있다.


처음부터 미디어 쿼리를 이용해 반응형 웹을 만들 때

스마트폰 스타일이 간단한 스타일을 사용하므로, 처음부터 미디어 쿼리를 이용해 반응형 웹을 만들 때는 모든 기기에서 공통되는 스타일을 정의하고 

스마트폰->태블릿 -> PC 순으로 미디어 쿼리를 적용한다.



화면 너비가 1024 이상일 때 #container 너비를 960px로 지정


style.css

1
2
3
4
5
@media screen and (min-width:1024px) {
    #container {
        width: 960px;
    }
}
cs




유동형 레이아웃

픽셀로 레이아웃을 지정하면 화면이 작은 스마트폰이나 태블릿 PC에서는 글자가 작아 보기가 어렵다.


미디어 쿼리는 기기 해상도별로 따로 CSS를 정의해야하며 까다롭다. 따라서 문서 안의 각 요소 너비를 픽셀 값과 같은 고정폭이 아닌 백분율(%)과 같은 가변폭으로 지정하면 좋다.

이렇게 사이트 레이아웃을 백분율로 지정하는 것을 '유동형 레이아웃(fluid layout)'이라고 한다. (브라우저 너비 값이 바뀔 때마다 너비 값이 바뀜)



요소의 너비를 백분율로 바꾸기


// 960px를 백분율로 변경 -> 96%

1
2
3
4
#wrapper {
width:96%
( ...)
}
cs


// wrapper너비인 960px를 기준으로 600px를 백분율로 변경, 600px / 960px = 0.625 -> 62.5%

1
2
3
4
5
article {
float : left;
width: 62.5%;
padding:20px;
}
cs



글자 크기를 em 단위로 변환하기

px는 모니터의 해상도를 기준으로 하기 떄문에 N-screen 시대에는 적합하지 않아서, em 단위를 사용하는 것이 좋다.

16px가 1em 이므로, em값을 구하려면 px 글자크기를 16px로 나누어 em 값을 계산하면 된다.


em = 글자 크기(px) / 16px




유동형 이미지 만들기

백분율로 지정한다. (100%)

1
2
3
img {
    max-width: 100%;
}
cs


유동형 비디오 만들기

마찬가지로 백분율로 지정. (100%)

1
2
3
4
video {
        max-width: 100%;
    }
 
cs



그리드 레이아웃

백분율로 지정하는 유동형 레이아웃도 N-screen 시대에 대처할 순 있지만, 사이트 전체 레이아웃을 똑같이 유지하기 때문에

스마트폰처럼 브라우저 창의 너비가 좁을 경우에는 적합하지 않을 수 있다.


그래서 나온 것이 그리드 레이아웃 기법이다.


PC나 태블릿, 스마트폰 용 각각에 맞게 레이아웃을 먼저 구상한다.

그런 후 각각의 요소에 적절한 시맨틱 태그나 id값을 지정한다.



CSS 리셋

문서 전체의 글꼴, 마진이나 패딩의 값을 지정하지 않으면 브라우저마다 각기 다른 기본 값을 적용하게 된다. 그것을 막기위해 필요한 CSS 기본 값들을 미리 설정하는 것을 'CSS reset' 이라고 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
      body { /* 문서전체의 글꼴, 마진, 패딩 리셋*/
        margin: 0;
        padding: 0;
        font-family: "돋움";
        font-size: 1em;
      }
      a:link {
        text-decoration: none;
      }
      a img {
        border: 0; /* 이미지 링크 테두리 0 */
      }
    </style>
cs




geoMap_result.html


'Web Develop > Web Programming' 카테고리의 다른 글

WebRTC 및 Node 등 스터디  (0) 2022.02.25
Spring Boot시작하기  (0) 2021.08.10
html 기초  (0) 2021.01.07
HTML 5 미지원 브라우저 고려하기  (0) 2017.03.21
윈도우 웹서버 설치 및 HTML 실습기초  (0) 2017.03.09

+ Recent posts