오늘은 벌써 4일차입니다. 미니프로젝트를 끝내고 발표까지 하는 날입니다. 4일이지만 하루에 14시간 이상 코딩에 몰입하다보니 일주일은 넘게 지난 느낌입니다. 마지막에 트러블 슈팅하면서 배포후 구현이 안되고 에러가 생기는 경우가 있긴 했지만 그래도 무사히 프로젝틀 끝냈습니다.
Ajax POST rendering
AJAX로 포스트요청을 서버에 보낸후 서버측에서 다른 페이지로 랜더링 해도 페이지 이동이 안되는 현상 → 해결 : Success 함수 안에 해당 코드를 포함하면 해결 document.write(response); -> response로 html안의 내용이 전달되어 오기 때문에 해당 내용을 써주면 됨
Jinja2
Jinja2에서 html에서 python 서버로 변수에 값을 담아 보내는 방법.. → html에서는 {{ 변수이름 }}, app.py에서 받을 때 <변수이름>으로 받을 수 있었다!
encoding
Ec2 서버에서의 app.py 실행 시, 토큰 인코딩 값이 바이트로 타입이 지정됨.. → 해결 : .decode(‘utf-8’)을 붙여 스트링 값으로 바꿔주어 해결
1주차 미니프로젝트 회고
다른 조들을 봤는데 수준이 다양하게 분포되어 있었습니다. 다른 사람들의 작업물과 과정, 회고까지 들었는데 굉장히 도움이 되었고 공부를 더 열심히 해야겠다고 마음을 다시 한번 더 다잡게 되는 좋은 자극제가 되었습니다.
오늘은 아침에 일어나는 게 너무 힘들었는데 막상 또 일어나서 컴퓨터 앞에 앉으니까 열정이 샘솟았습니다. 제가 어제 걱정하고 씨름했던 오류가 말끔히 해결이 되었거든요. 껐다 켰다는 진리입니다..... 원격 repo에 푸시하지 않는이상 로컬은 상관없으므로 몽땅 merge를 했더니 잘 됐습니다.
merge 오류에 대해서
왜 오류가 생기나 했더니 .gitignore에 .idea와 __pycache__넣어서 환경설정을 방해하지 못하게 했었어야했습니다.
.gitignore 파일에 .idea와 __pycache__ 를 넣는다.
새로 원격 repo를 받았는데 실행이 안되는 건에 대하여...
다시 처음부터 받았는데 몇 개 페이지 실행이 안됐다. 알고보니...
DB를 끌어와서 구현하는 페이지들이었습니다. 환경설정도 처음부터 해야했었던겁니다.
.env 파일을 만들고 DB 정보를 저장하니 실행이 잘 되었습니다.
환경변수 처리 .env
JWT 토큰 실행을 위한 SECRET_KEY 정보를 .env 넣었습니다.
SECRET_KEY가 필요한 파일에 다음과 같이 코드를 넣어줍니다.
from dotenv import load_dotenv
import os
load_dotenv()
SECRET_KEY = os.getenv('SECRET_KEY')
어제 남궁성의 자바의 정석 기초편 챕터 1을 듣고 잤습니다. 앞부분이라 프로그램 설치에 대한 내용이 대부분이라 자기 전에 1시간 들었습니다. 강의가 171개가 있던데 다 들을 수 있겠죠...? 회원가입 페이지 구현하는 게 그냥 아이디, 비밀번호, 닉네임 값만 가져오면 될 줄 알았는데, 아이디 중복확인도 해야하고 페이지 디자인도 예쁘게(?) 바꿔야 합니다. 오늘은 회원가입만 완성하고 자도록 하겠습니다. 내일은 로그인 구현하면 되겠죠.....?
열심히 해서 커밋해서 푸시까지 해서 원격 repo까지 보냈는데 그 후로 부터 갑자기 제 로컬 repo가 이상해져서 파일 실행이 안됩니다....그래서 해본 게
로컬 repo 삭제하고 원격 repo 새로 다운 받기
도대체가 모르겠네
여튼 아래처럼 회원가입 페이지를 구현했습니다.
일단은 회원 가입 정보도 DB로 잘 들어가는 걸 확인했습니다. 근데 중복확인은 아직 구현을 못했습니다.
DB연결이 안되서 애를 먹었는데 그룹으로 프로젝트를 하는 것이 처음이라 더 어렵습니다. 설정을 모두와 맞춘다고 Python도 3.9 버전으로 바꾸고 Blueprint라는 방법도 처음 사용해봤습니다. url 적는 방식이 다르다는 걸 조원분들이 알려줘서 고쳤습니다. 아예 생초보인 저는 다 새롭고 어려운데 척척 하시는 다른분들을 보니 대단하게만 느껴지네요.
백엔드 테스트를 할 때는 postman이라는 것도 사용한다고 합니다. 오늘은 결국 회원가입과 로그인만 구현하고 Github으로 푸시를 했습니다. 각각 feature 별로 커밋하려고 했더니 뭔가 로컬에서 꼬여버려서 작업이 복구가 안되네요.
다행히 원격 repo는 잘 들어갔는데... 다시 작업하려고 하니까 도대체 어떻게 해야 원래 작업상태로 돌아갈지 모르겠어요...... 일단 잡니다!
드디어 오늘이 항해99 부트캠프 정식 시작일입니다. 지난주는 pre-onboarding 기간으로 주특기 언어인 Java를 공부하는 시간을 가졌습니다. 오늘부터 새로 배정된 조에서 미니 프로젝트를 진행합니다. 조원 4명이서 4일동안 진행할 프로젝트를 기획하고 제작하고 배포하고 발표까지해야 합니다.
오늘은 첫날이라고 대표님이 오셔서 OT를 해주셨는데 항해99프로그램에 대한 흥미로운 사실들과 개발자로서의 마음가짐에 대해 좋은 말씀을 나누어 주셨습니다. '나는 개발을 사랑한다'가 세뇌가 되어야 한다고 하셨는데 저는 지금은 좋아한다 정도여서 사랑으로 한번 끌어올리도록 노력해보겠습니다. 하면 할수록 더 좋아지고 있긴 합니다. 컴퓨터의 역사부터 여러가지가 흥미로워요. 다른 개발자분들이 토이프로젝트를 올려놓은 웹사이트가 있는데 보면서 이런것도 개인이 만들수가 있구나 하면서 열정이 샘솓고 있습니다. 늘 가는 웹사이트를 들어가더라도 전에는 아무 생각없이 이용만 했다면 지금은 어떤 기능을 써서 이런 웹사이트를 구현했나 하고 분석을 하게 됩니다. 아는 만큼 보이는 것 같습니다.
드디어 한 주가 끝났습니다. 일주일동안 핵심 쏙쏙 Git 강의를 들었고 혼자 공부하는 자바 챕터 5까지 진도를 나갔습니다. 이번주는 Pre-Onboarding 기간으로 주특기 언어를 학습하는 시간이었고 다음주부터 정식으로 시작합니다. 부족한 공부를 위해서 어떻게 해야하나 백준이랑 프로그래머스라는 게 있다는 데 조사를 해봐야겠습니다. 일단 어디서 시작해야할지 알아보는 중이에요. 아예 새로운 분야에 입문하려고 하니까 공부할 게 태산이네요.
int year = now.get(Calendar.YEAR); //연
int month = now.get(Calendar.MONTH) +1; //월(1~12)
int day = now.get(Calendar.DAY_OF_MONTH); //일
int week = now.get(Calendar.DAY_OF_WEEK); //요일(1~7)
int hour = now.get(Calendar.HOUR); //시간
int minute = now.get(Calendar.MINUTE); //분
int second = now.get(Calendar.SECOND); //초
열거 타입과 열거 상수
Week.java (열거 타입 선언)
public enum Week {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}
Main.java (열거 타입 사용하기)
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
Week today = null;
Calendar cal = Calendar.getInstance();
int week = cal.get(Calendar.DAY_OF_WEEK);
switch (week) {
case 1:
today = Week.SUNDAY; break;
case 2:
today = Week.MONDAY; break;
case 3:
today = Week.TUESDAY; break;
case 4:
today = Week.WEDNESDAY; break;
case 5:
today = Week.THURSDAY; break;
case 6:
today = Week.FRIDAY; break;
case 7:
today = Week.SATURDAY; break;
}
System.out.println("오늘 요일: " + today);
if(today == Week.SUNDAY) {
System.out.println("일요일에는 축구를 합니다.");
} else {
System.out.println("열심히 자바 공부합니다.");
}
}
}
❗열거 타입을 사용하려면 public enum 열거 타입 선언한 먼저 해야함
확인문제 복습 손코딩으로 하기
손코딩으로 해야 는다는 글을 어디서 본 적이 있어서 복습은 노트에 손코딩하면서 하기로 결심했습니다. 확실히 답지도 안보고 문제만 보면서 펜으로 노트에 직접 쓰니까 더 머릿속에 잘 들어오는 듯 합니다. 그래도 한 번 푼 문제라고 풀리는 문제가 안풀리는 문제보다는 많습니다.
근데 생각보다 저는 더 악필이네요🤓
while문에 break; 잊지 않기
타입 선언 잊지 않기
변수 선언한 {}를 벗어나놓고 왜 안되지 하지 않기
이유 알고 쓰기
{} 빼먹지 않기; 실행 순서 알기
문제를 꼼꼼히 읽읍시다
String 변수는 .equals() 메소드를 사용
Chapter 02-1
1. o,x 문제
변수는 하나의 값에만 저장할 수 있음
변수 선언 시에 사용한 타입의 값만 저장할 수 있음
변수는 초기 값이 저장되지 않은 상태에서 읽을 수 없음
2. 변수 이름으로 사용할 수 있는 것 o,x 문제
$value는 사용할 수 있음
첫번째 글자는 문자이거나 '$', '_' 만 가능함
Chapter 02-2
2. o,x 문제
char var = 'AB'; //char 타입이 아니라 String 타입임
long var = 50000000000; //long은 int 타입의 범위를 벗어 날 시 숫자 뒤에 L 을 붙어야 함
String var = "나의 직업은 "개발자" 입니다."; //"를 썼으면 안에는 '를 써야함
오늘은 금요일입니다. 벌써 항해를 시작한지 5일이 지났네요. 입학시험도 무사히 치르고 일주일동안 많은 것들을 학습했습니다. 아직 Java와 친해지려면 멀었지만요. 프로그래밍 언어는 인간의 언어보다 더 규칙적이라 독일어 배울 때를 생각하면 훨씬 쉬운 것 같습니다만 시간이 좀 필요합니다. 🎼오늘의 노래: 로꼬 - '시간이 들겠지'.
Chapter 05-1 참조 타입과 참조 변수
기본타입과 참조 타입
기본 타입(primitive type) 변수는 실제 값을 변수안에 저장
참조 타입(배열, 열거, 클래스, 인터페이스) 변수는 메모리의 번지를 변수 안에 저장
번지를 통해 객체를 참조한다는 뜻에서 참조 타입이라고 부름 -> heap memory
메모리 사용 영역
JVM은 Runtime Data Area(운영체제에서 할당받은 메모리 영역)을 아래와 같이 세부 영역으로 구분해서 사용
메소드 영역 Method area:JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역; 코드에서 사용되는 class들을 클래스 로더로 읽어 클래스 별로 정적 필드(static field)와 상수constant, 메소드 코드, constructor(생성자) 코드 등을 분류해서 저장
힙 영역 Heap Area: 객체와 배열이 생성되는 영역; JVM 스택 영역의 변수나 다른 객체의 필드에서 참조
참조하는 변수나 필드가 없다면 의미 없는 객체가 되기 때문에 JVM이 쓰레기로 취급하고 쓰레기 수집기(Garbage Collector)를 실행시켜 자동으로 제거
객체를 제거하기 위해 별도의 코드를 작성할 필요가 없음
자바는 코드로 객체를 직접 제거하는 방법을 제공하지 않음
JVM 스택 영역 Stack area:메소드를 호출할 때마다 Frame을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(pop)하는 동작을 수행
프레임 내부에는 로컬 변수 스택이 있음
기본 타입 변수와 참조 타입 변수가 Push 되거나 Pop
최초로 변수에 값이 저장 될 때 stack 영역에 변수가 생성됨
변수는 선언됨 블록 안에서만 스택에 존재하고 블록을 벗어나면 스택에서 제거 됨
기본 타입 변수는 스택 영역에 직접 값을 가지고 있지만, 참조 타입 변수는 스택 영역에 힙 영역의 객체 주소를 가짐
자바에서는 배열을 객체로 취급
참조 변수의 ==, != 연산
기본 타입 변수의 ==, != 연산은 true, false를 조사하지만 참조 타입 변수들은 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용
동일한 번지 값을 갖고 있다는 것 == 동일한 객체를 참조함
null과 NullPointerException
참조 타입 변수는 힙 영역의 객체를 참조하지 않는다는 뜻으로 null 값을 가질 수 있음
null값을 초기값으로 사용할 수 있기 때문에 null로 초기화 된 참조 변수는 스택 영역에 생성됨
참조 타입 변수가 null 값을 가지는지 확인하려면
변수 ==, != null 연산을 수행하면 됨
예외Exception: 프로그램 실행 도중에 발생하는 오류
사용자의 잘못된 입력
코드 잘못 작성
가장 많이 발생하는 예외: NullPointerException-> 참조 타입 변수를 잘못 사용하면 발생함
참조 변수가 null을 가지고 있을 경우에는, 참조 객체가 없으므로 변수를 통해 객체를 사용할 수 없음
null이 없는 상태에서 객체의 데이터나 메소드를 사용하는 코드 실행시 발생
String 타입
문자열이 직접 변수에 저장되는 것이 아니라, 문자열은 String 객체로 생성되고 변수는 String 객체를 참조함
문자열 리터럴이 동일하면 String 객체를 공유함
공유하지 않고 별개의 객체에 저장하려면-> new 연산자를 사용해서 직접 String 객체를 생성
new 연산자= 객체 생성 연산자
문자열 리터럴로 생성 vs. new 연산자로 생성
동일한 문자열 리터럴로 String 객체 생성했을 경우: ==연산의 결과는 true
new 연산자로 생성 했을 경우: ==연산 결과는 false
== 연산자는 변수의 저장된 객체의 번지가 동일한지를 검사하기 때문
동명이인 같은 걸 입력할 때 쓰는 방법일까....?
객체에 상관없이 내부 문자열을 비교하고 싶을 때 -> equals() 메소드를 사용
String 변수는 참조 타입으로 초기값으로 null을 대입할 수 있음
String 변수가 참조하는 String 객체가 없다는 의미
String hobby = null
참조를 잃은 String 객체는.... goes to the Garbage Collector
Chapter 05-2 배열
배열이란? array
같은 타입의 데이터를 연속된 공간에 나열하고 각 데이터에 인덱스(index)를 부여해놓은 자료 구조
인덱스는 0부터 시작함
배열의 특징
같은 타입의 데이터만 저장; 다른 타입 저장하면 타입 불일치 컴파일 에러 발생 type mismatch
한 번 생성된 배열은 길이를 늘리거나 줄일 수 없음
새로운 배열을 생성하고, 기존 배열 항목을 새 배열로 복사하는 수밖에 없음
배열 선언
배열을 사용하기 위해서는 배열 변수를 선언해야함
형식1: 타입[] 변수;
형식2: 타입 변수[];
배열 변수는 참조 변수
배열은 객체로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체를 참조함
참조할 배열 객체가 없다면 배열 변수는 null값으로 초기화 됨
배열 변수가 null 값을 가진 상태에서 변수로 값을 읽거나 저장하면 -> NullPointerException 에러 발생
배열을 생성하고 배열 변수가 참조하는 상태에서 값을 저장하거나 읽어야함
배열 생성
값 목록 이용 또는 new 연산자 이용
값 목록으로 배열 생성
타입[] 변수 = {값0, 값1, 값2, 값3, ...}
배열 변수를 이미 선언한 후에는 다른 실행문에서 중괄호를 사용한 배열 생성이 안됨 -> 컴파일 에러!
배열 변수를 미리 선언한 후 값 목록들이 나중에 결정되는 상황에는 -> new 연산자 사용해서 값 목록을 지정!
변수 = new 타입[] {값0, 값1, 값2, 값3, ...}
메소드의 매개값이 배열일 경우에도 new 연산자를 사용
int result = add( new int[] {값0, 값1, 값2} );
public class prac {
public static void main(String[] args) {
int[] scores;
scores = new int[] {83,90, 87};
int sum1 = 0;
for (int i=0; i<3; i++){
sum1 += scores[i];
}
System.out.println("총합 : " + sum1);
int sum2 = add( new int[]{83, 90,87});
System.out.println("총합 : " + sum2);
System.out.println();
}
public static int add(int[] scores){
int sum =0;
for(int i=0; i<3;i++){
sum += scores[i];
}
return sum;
}
}
new 연산자로 배열 생성
향후 값들을 저장할 배열을 미리 만들고 싶다면 new 연산자로 배열 객체 생성
타입[] 변수 = new 타입[길이];
길이 == 배열이 저장할 수 있는 값을 개수
new 연산자로 배열을 처음 생성할 경우-> 기본값 0으로 초기화; String이라면 null값
배열이 생성되고 나서 특정 인덱스 위치에 새로운 값을 저장
변수[인덱스] = 값;
배열 길이
배열에 저장할 수 있는 전체 항목의 개수
.length 사용
읽기 전용 필드기 때문에 값을 바꿀수 없음
for 문 사용할 때 유용
배열의 length 필드
public class prac {
public static void main(String[] args) {
int[] scores = {83,90,87};
int sum =0;
for(int i=0; i<scores.length; i++){
sum+=scores[i];
}
System.out.println("총합 : " + sum);
double avg = (double) sum/scores.length;
System.out.println("평균 : " + avg);
}
}
< 연산자를 사용한 이유는 배열의 마지막 인덱스는 배열 길이보다 1이 적기 때문~~
인덱스 초과해서 사용시 -> ArrayIndexOutOfBoundsException 에러 발생
명령 라인 입력
public static void main(String[] args){ .... }
(String[] args)가 필요한 이유
명령 라인(명령 프롬프트)에서 위 코드를 java 명령어로 실행하면 JVM은 길이가 0인 String 배열을 먼저 생성하고 Main() 메소드를 호출할 때 매개값으로 전달
main() 메소드는 String[] args 매개 변수를 통해서 명령 라인에서 입력된 데이터의 수(배열의 길이)와 입력된 데이터(배열의 항목 값)을 알 수 있음
JDK 8 이전 버전: java sec02.exam05.MainStringArgument 10 20
args는 {"10", "20"}을 array로 참조
문자열로 인식되니까 숫자로 바꾸려면 Integer.parseInt() 메소드를 이용해서 정수로 변환함
정수로 변환할 수없는 문자열이라면 -> NumberFormatException 에러 발생
다차원 배열
2차원 배열: 행과 열로 구성된 배열; 가로 인덱스와 세로 인덱스를 사용함
자바는 중첩 배열 방식으로 구현
int[][] scores = new int [2][3]
배열의 정확한 길이를 알고 인덱스를 사용해야 함
아니면 ArrayIndexOutOfBoundsException 에러 발생
int[][] scores = { {95, 80}, {92, 96}};
행, 열
0
1
0
95
92
1
80
96
int score = scores[0][0]; /95
int score = scores[1][1]; /96
배열 속의 배열
public class prac {
public static void main(String[] args) {
int[][] mathScores = new int[2][3];
for (int i = 0; i < mathScores.length; i++) {
for (int k = 0; k < mathScores[i].length; k++) {
System.out.println("mathScores[" + i + "][" + k + "]=" + mathScores[i][k]);
}
}
System.out.println();
int[][] englishScores = new int[2][];
englishScores[0] = new int[2];
englishScores[1] = new int[3];
for (int i = 0; i < englishScores.length; i++) {
for (int k = 0; k < englishScores[i].length; k++) {
System.out.println("englishScores[" + i + "][" + k + "]=" + englishScores[i][k]);
}
}
System.out.println();
int[][] JavaScores = {{95, 80}, {92, 96, 80}};
for (int i = 0; i < JavaScores.length; i++) {
for (int k = 0; k < JavaScores[i].length; k++) {
System.out.println("JavaScores[" + i + "][" + k + "]=" + JavaScores[i][k]);
}
}
}
}
public class prac {
public static void main(String[] args) {
int[] oldIntArray = {1,2,3};
int[] newIntArray = new int[5];
for(int i =0; i<oldIntArray.length; i++){
newIntArray[i] = oldIntArray[i];
}
for(int i=0; i<newIntArray.length; i++){
System.out.print(newIntArray[i] + ", ");
}
}
}
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
System.arraycopy()로 배열 복사
public class prac {
public static void main(String[] args) {
String[] oldStrArray = { "java", "array", "copy"};
String[] newStrArray = new String[5];
System.arraycopy( oldStrArray, 0, newStrArray, 0, oldStrArray.length);
for(int i=0; i< newStrArray.length; i++){
System.out.print(newStrArray[i] + ", ");
}
}
}
복사되지 않은 항목은 null 처리 됨
참조 타입 배열이 복사되면 복사되는 값이 객체의 번지이므로 새 배열의 항목은 이전 배열의 항목이 참조하는 객체와 동일
항상된 for문 enhanced for statements
for(타입 변수: 배열){ ... }
배열의 항목 개수 만큼 반복하고 자동적으로 for문을 종료; 반복할 때마다 변수에는 배열에서 가져온 항목이 저장됨
향상된 for문
public class prac {
public static void main(String[] args) {
int[] scores = { 95, 71, 84, 93, 87};
int sum = 0;
for (int score : scores){
sum = sum + score;}
System.out.println("점수 총합 = " +sum);
double avg = (double) sum / scores.length;
System.out.println("점수 평균 = " +avg);
}
}
public class prac {
public static void main(String[] args) {
int max = 0;
int[] array = { 1, 5, 3, 8, 2};
//작성 위치
for(int i=0; i<array.length; i++){
if (max < array[i]) {
max = array[i];
}
}
System.out.println("max: " + max);
}
}
5. 중첩for문을 이용해서 주어진 배열의 전체 항목의 합과 평균값 구하기
public class prac {
public static void main(String[] args) {
int[][] array = {
{95, 86},
{83, 92, 66},
{78, 83, 93, 87, 88}
};
int sum = 0;
double avg = 0.0;
//작성 위치
int count =0;
for(int i=0; i<array.length; i++){
for(int k=0; k<array[i].length; k++){
sum += array[i][k];
count++;
}
}
avg = (double) sum/ count;
System.out.println("sum: " +sum);
System.out.println("avg: " +avg);
}
}
7. 학생 점수 구하기
import java.util.Scanner;
public class prac {
public static void main(String[] args) {
boolean run = true;
int studentNum = 0;
int[] scores = null;
Scanner scanner = new Scanner(System.in);
while (run) {
System.out.println("--------------------------------");
System.out.println("1. 학생수 | 2. 점수입력 | 3. 점수리스트 | 4.분석 | 5. 종료");
System.out.println("--------------------------------");
System.out.println("선택> ");
int selectNo = Integer.parseInt(scanner.nextLine());
if (selectNo == 1) {
System.out.print("학생수> ");
studentNum = Integer.parseInt(scanner.nextLine());
scores = new int[studentNum];
} else if (selectNo == 2) {
for (int i = 0; i < scores.length; i++) {
System.out.println("scores[" + i + "]> ");
scores[i] = Integer.parseInt(scanner.nextLine());
}
} else if (selectNo == 3) {
for (int i = 0; i < scores.length; i++) {
System.out.println("scores[" + i + "]:" + scores[i]);
}
} else if (selectNo == 4) {
int max = 0;
int sum = 0;
double avg = 0.0;
for (int i = 0; i < scores.length; i++) {
max = (max < scores[i]) ? scores[i] : max;
sum += scores[i];
}
avg = (double) sum / studentNum;
System.out.println("최고 점수: " + max);
System.out.println("평균 점수: " + avg);
} else if (selectNo == 5) {
run = false;
}
}
System.out.println("프로그램 종료!!!");
}
}
Sololearn에서 제공하는 Java 언어 학습은 총 60개 레슨으로 이루어져 있습니다. 현재는 아직 40번째 레슨에 머물러 있는 상태에요. 뒤로 갈수록 어려워져서 그렇습니다. 부트캠프 핑계로 Sololearn을 놓고 있지만 이번주 일요일까지는 Sololearn의 Java를 끝내 보도록 하겠습니다. 어차피 저랑은 당분간 친해지려고 노력해야하는 언어입니다. 이 포스팅에서는 공부하다가 헷갈리거나 다시 복습하고 싶은 부분을 캡쳐해서 정리해보려고 합니다.
.toCharArray() : String 타입을 CharArray로 바꾼다. 문자열을 문자별로 다 따로 저장
ex) "Santa" -> "S", "a", "n", "t", "a"
arr.length에 -1을 하는 이유:
.length에 -1을 하지 않는 경우: core dump error가 발생
arr[10]에서 배열의 첫 주소는 0부터 시작하지만!!
즉, 배열의 주소는 arr+0, arr+1, ..., arr+9까지이고, 이는 arr[0], arr[1], ..., arr[9]로 표현됨
즉, arr[10]부터는 존재하지 않고 arr[10]에 관한 코드가 작성되면 에러가 발생
이중for문에서 j<length(=10)이기 때문에 j가 될 수 있는 가장 마지막 수는 9가 되니 j가 9인 경우, if문 안에 j=9인 상황을 대입하면 arr[9] < arr[10]입니다. 이 때 arr[10]은 코드 어디에도 정의되지 않았기 때문에 찾을 수 없음. 그렇기 때문에 컴퓨터는 arr[10]이 도대체 어디 정의되었는지 알 수 없다고 에러를 발생시킵니다.
그렇기 때문에 for문의 범위를 length-1까지 정해준다.
그러니까 갯수 세는건 우리가 아는 것 처럼 세지만!!! index 번호는 0부터 시작하니까 array 마지막 수를 부르고 싶으면 array.length-1 을 써야한다!
Object-Orientation
Java는 Object-Oriented Programming(OOP) 객체지향 프로그래밍 스타일을 사용하고 현실과 가깝게 프로그래머들이 생각할 수 있도록 한다
OOP에서는 각 객체가 유니크 아이덴티티를 가진 독립적인 유닛이다. (마치 현실에서 그런것처럼(?))
사과는 객체이다. 머그잔도 그러하다. 각각의 사물은 그만의 아이덴티티를 가진다. 두개의 머그잔이 똑같이 생길 수는 있지만 각각의 독립적인 유니크한 objects이다.
Objects는 그들을 묘사하는 특징이 있다.
차가 빨간색이거나 파란색, 머그잔이 가득 차 있거나 비어있는 것처럼 말이다.
이러한 특징(characteristics)들은 attributes라고 불린다.
attributes는 object의 현 상태를 묘사한다.
차가 움직이거나 전화가 울리는 것처럼 object type에도 behavior 가 적용된다.
어제는 Java의 창조자인 제임스 고슬링의 팟캐스트 인터뷰를 듣다가 잠이 들었습니다. 제임스 고슬링이 가장 좋아하는 숫자는 √2라고 합니다. 종교를 바꿔놓은 숫자라고 해서 그렇답니다. 피타고라스의 정리를 만들어 기존의 개념을 파괴한 숫자이기 때문이랍니다. 컴퓨터 과학자들은 수학자에서 시작하는 경우가 많은데 이분도 마찬가지 인 것 같습니다. 전에 우연히 유튜브 알고리즘에 의해 알게 된 Leslie Lampart라는 튜링상을 받은 마이크로소프트 출신의 컴퓨터 과학자도 마찬가지로 수학에서 시작했다고 합니다. 제 주변만 봐도 비전공자중에 수학전공했던 분들이 개발자로 전향한 케이스가 대부분이었습니다. 저는... 경제학과 경영학과를 복수전공했으니 아예 거리가 있지는 않네요. 대학교에서 통계학 공부한 게 도움이 되길 바라면서 오늘도 공부를 시작해봅니다!
오늘의 학습목표는 어제 못한 Sololearn Java 정리(임시저장을 안해서 다 날라갔습니다.. 저장을 생활화 합시다😢), 핵심 쏙쏙 Git 3주차 듣기, 혼자 공부하는 자바 챕터 4를 끝내는 것입니다. 점심시간에 운동을 하고 오겠습니다. 강도는 좀 낮게 3세트씩만.. 안그럼 졸려서..ㅎㅎ
핵심 쏙쏙 Git 3주차
PR (Pull Request)
PR(Pull Request): 작업내역을 바로 merge 하지 않고, 참여하고 있는 프로젝트에 내 작업(branch)를 merge해달라고 요청(Request) 를 먼저 보내는 것
여러 피드백을 거쳐서 repo 관리자의 승인을 거쳐 프로젝트에 반영(merge)
왜 PR 이 완료된 후에야 로컬 repo의 feature/jjim 을 삭제해야할까요?
통상적으로 PR 이 반영되기 전 추가 commit을 해야한다면, 로컬 branch에서 commit 후 원격 branch에 push해서 변경된 내용을 반영하기 때문
PR 은 리뷰하는 과정을 통상적으로 포함
PR 후에도 추가적으로 commit을 해야하는 경우
리뷰에서 추가 수정을 요청받거나
PR 을 그대로 merge한다고 했을 때 merge conflict 가 나는 것을 미리 고치기
ex) 만약 추가 수정을 제안받았다고 가정할 때, 로컬 repo 의 feature/jjim 에서 commit 후, 원격 repo의 feature/jjim (origin/feature/jjim) 에 push 하는 것이 통상적임
github repo에서 issue 만들기 해서 이미지 끌어다 놓으면 자동으로 생성됨. 이슈 등록 안해도 이미지 링크는 쓸 수 있음
왜 또 안되냐... 깃헙 푸시 오류 😱
지난번에 토큰을 url 주소에 추가하는 것으로 해결된 문제(참조)인 줄 알았는데 PR 하고 푸시하는 과정에서 다시 에러가 발생했습니다. 김치 레시피 추가하는 게 이렇게 힘들일인가요😭
git -c color.branch=false -c color.diff=false -c color.status=false -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree push -v --tags --set-upstream origin refs/heads/feature/1_stir_fired:refs/heads/feature/1_stir_fired Pushing to https://github.com/sooni2/kimchi-recipe-os.git remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/sooni2/kimchi-recipe-os.git/' Pushing to https://github.com/sooni2/kimchi-recipe-os.git remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/sooni2/kimchi-recipe-os.git/' Pushing to https://github.com/sooni2/kimchi-recipe-os.git remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/sooni2/kimchi-recipe-os.git/' Pushing to https://github.com/sooni2/kimchi-recipe-os.git remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/sooni2/kimchi-recipe-os.git/' Completed with errors, see above
5. start부터 시작하는 n개의 정수 중에서 임의의 정수 하나를 얻기 위한 연산식은 다음과 같음
int num = (int) (Math.random()*n)+1;
6. 주사위 번호 하나 뽑기 위한 연산식
int num = (int) (Math.random()*6)+1;
7. 로또 번호 하나 뽑기 위한 연산식
int num = (int) (Math.random()*45)+1;
public class prac {
public static void main(String[] args) {
int num = (int) (Math.random() * 6) + 1;
if (num == 1) {
System.out.println("1번이 나왔습니다!");
} else if (num == 2) {
System.out.println("2번이 나왔습니다!");
} else if (num == 3) {
System.out.println("3번이 나왔습니다!");
} else if (num == 4) {
System.out.println("4번이 나왔습니다!");
} else if (num == 5) {
System.out.println("5번이 나왔습니다!");
} else if (num == 6) {
System.out.println("6번이 나왔습니다!");
}
}}
switch문
if와 다르게 변수의 값에 따라 실행문이 결정됨
if문보다 코드가 간결함
public class prac {
public static void main(String[] args) {
int num = (int) (Math.random() * 6) + 1;
switch (num){
case 1:
System.out.println("1번이 나왔습니다!");
break;
case 2:
System.out.println("2번이 나왔습니다!");
break;
case 3:
System.out.println("3번이 나왔습니다!");
break;
case 4:
System.out.println("4번이 나왔습니다!");
break;
case 5:
System.out.println("5번이 나왔습니다!");
break;
default:
System.out.println("6번이 나왔습니다!");
break;
}
}}
break문이 없는 case: case값과 상관없이 실행됨
04-2 반복문:for문, while문, do-while문
for문
for ( 초기화식; 조건식; 증감식){실행문;}
for (Int i=0, j=100; i<=50 && j>=50; i++, j--){실행문}
초기화식에서 루프 카운터 변수 선언할 때 float 타입 사용하지 말아야함
중첩 for문
바깥쪽 for문이 한 번 실행할 대마다 중첩된 for문은 지정된 횟수만큼 반복해서 돌다가 다시 바깥쪽 for문으로 돌아감
구구단 출력하기
public class prac {
public static void main(String[] args) {
for (int m=2; m<=9; m++){
System.out.println("*** "+m+"단 ***");
for (int n=1; n<=9; n++) {
System.out.println(m + "x" + n + " = " + (m*n));
}
}
}}
while문
조건식이 true일 경우 반복 실행
조건식이 false가 되면 반복 행위를 멈추고 while문 종료
1부터 100까지 합을 출력
public class prac {
public static void main(String[] args) {
int sum = 0;
int i =1;
while(i<=100){
sum+=i;
i++;
}
System.out.println("1 ~ " + (i-1) + " 합 : " + sum);
}}
do-while문: 내부 실행문을 우선 실행하고 실행 결과에 따라서 반복 실행을 계속할지 결정
break문: 반복문의 실행을 중지할 때 사용
대게 if문과 같이 사용되어 If문의 조건식에 따라 for문과 while 문을 종료할 때 사용
반복문이 중첩되어 있을 경우 break문은 가장 가까운 반복문만 종료하고 바깥쪽 반복문은 종료하지 않음
continue문은 블록 내부에서 실행되면 for문의 증감식 또는 while문, do-while문의 조건식으로 이동
If랑 사용시 특정 조건을 만족하는 경우에 continue문을 실행해서 그 이후의 문장을 실행하지 않고 다음 반복으로 넘어감
1에서 10 사이 중 짝수만 출력 (continue를 사용한 for문)
public class prac {
public static void main(String[] args) {
for(int i=1; i<=10; i++){
if(i%2 !=0){
continue;
}
System.out.println(i);
}
}}
확인문제
3. while문과 Math.random() 메소드를 사용해 2개의 주사위를 던졌을 때 나오는 눈을 (눈1, 눈2) 형태로 출력; 눈의 합이 5이면 실행을 멈추는 코드
public class prac {
public static void main(String[] args) {
int sum = 0;
while (true) {
int num1 = (int) (Math.random() * 6) + 1;
int num2 = (int) (Math.random() * 6) + 1;
System.out.println("" + num1 + "와" + num2 + "합은" + (num1 + num2));
if ((num1 + num2) == 5) {
break;
}
}
}
}
4. 중첩 for문을 이용하여 방정식 4x + 5y=60의 모든 해를 구해서 (x,y) 형태로 출력
public class prac {
public static void main(String[] args) {
for(int x=0; x<=10; x++) {
for (int y =1; y<=10; y++){
if(4*x+5*y== 60){
System.out.println(x+" , "+y);
}}
}
}
}
5, 6. for문 이용해서 출력하기
public class prac {
public static void main(String[] args) {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= i; j++) { /*i가 2면 j는 2번 실행됨*/
System.out.print("*");
if (i == j) {
System.out.println();
}
}
}
}
}
public class prac {
public static void main(String[] args) {
for (int i = 1; i < 5; i++) {
for (int j = 4; j > 0; j--) {
if (i < j) {
System.out.print(" ");
} else{ System.out.print("*");}
}
System.out.println();
}
}
}
i=1, j =4 일 때: 1<4 -> " "
i=1, j=3 일 때: 1<3 -> " "
i=1, j=2 일 때: 1<2 -> " "
i=1, j=1 일 때: 1=1 -> "*"
중첩for문 이해할 것...😇😇😇
7. while문과 Scanner의 NextLine()를 이용해서 입력된 데이터로 예금, 출금, 조회, 종료 기능을 제공하는 코드 작성
public class prac {
public static void main(String[] args) {
boolean run = true;
int balance = 0;
Scanner scanner = new Scanner(System.in);
while (run) {
System.out.println("----------------------------");
System.out.println("1.예금 | 2. 출금 | 3.잔고 | 4.종료");
System.out.println("----------------------------");
System.out.println("선택> ");
int menuNum = Integer.parseInt(scanner.nextLine());
switch (menuNum) {
case 1:
System.out.print("예금액> ");
balance += Integer.parseInt(scanner.nextLine());
break;
case 2:
System.out.print("출금액> ");
balance -= Integer.parseInt(scanner.nextLine());
break;
case 3:
System.out.print("잔고> ");
System.out.println(balance);
break;
default:
run = false;
break;
}
System.out.println();
}
System.out.println("프로그램 종료");
}
}