C언어
전처리기
💡 전처리기?
- 컴파일 전에 처리하는 것
❗define : 매크로
- 해당 변수 및 함수의 값을 미리 정해두는 것
● 단순 매크로 : 기존의 기호상수 기능에서 사용하는 것과 같다.
- 가독성이 높아진다.
- 상수의 변경이 매우 용이해진다.
● 함수 매크로 : 마치 함수인 것 처럼 흉내를 낼 수 있는 기능
❗include
Chapter 26
문제 4. start_with 함수를 구현
#include <stdio.h>
typedef int bool;
#define true 1 // 전처리기 true의 값을 1로 변환
#define false 0
int get_str_len(char* str) {
for ( int i = 0; true; i++ ) {
if ( str[i] == '\\0' ) {
return i;
}
}
}
bool starts_with(char* str, char* str2) {
int str_len = get_str_len(str);
int str2_len = get_str_len(str2);
if ( str_len < str2_len ) {
return false;
}
for ( int i = 0; i < str2_len; i++ ) {
if ( str[i] != str2[i] ) {
return false;
}
}
return true;
}
int starts_with2(char* str1, char* str2) {
for (int i = 0; str1[i] != '\\0'; i++) {
if (strstr(str1, str2) != NULL) {
return true;
}
}
return false;
}
int main(void) {
bool rs;
rs = starts_with("abc", "ab");
printf("rs : %d\\n", rs); // 출력 rs : 1
rs = starts_with("kbs", "kb");
printf("rs : %d\\n", rs); // 출력 rs : 1
rs = starts_with("mbc", "mc");
printf("rs : %d\\n", rs); // 출력 rs : 0
return 0;
}
문제 5. end_with 함수 구현
#include <stdio.h>
typedef int bool;
#define true 1
#define false 0
int get_str_len(char* str) {
for ( int i = 0; true; i++ ) {
if ( str[i] == '\\0' ) {
return i;
}
}
}
int ends_with(char* str1, char* str2) {
int s1_len = get_str_len(str1);
int s2_len = get_str_len(str2);
int start = s1_len - s2_len;
int end = s1_len;
if (s1_len > s2_len) {
return false;
}
for(int i = start; i < end; i++) {
if (str1[i] != str2[i - start]) {
return false;
}
}
return true;
}
int main(void) {
bool rs;
rs = ends_with("abc", "bc");
printf("rs : %d\\n", rs); // 출력 rs : 1
rs = ends_with("kbs", "kb");
printf("rs : %d\\n", rs); // 출력 rs : 0
rs = ends_with("kbs", "bs");
printf("rs : %d\\n", rs); // 출력 rs : 1
rs = ends_with("mbc", "mc");
printf("rs : %d\\n", rs); // 출력 rs : 0
return 0;
}
문제6. str_equals 함수 구현
#include <stdio.h>
#define true 1
#define false 0
typedef int bool;
int get_str_len(char* str) {
for ( int i = 0; true; i++ ) {
if ( str[i] == '\\0' ) {
return i;
}
}
}
int str_equals(char* str1, char* str2) {
if (strstr(str1, str2) != NULL) {
return true;
}
return false;
}
int str_equals2(char* str1, char* str2) {
int str1_len = get_str_len(str1);
int str2_len = get_str_len(str2);
if(str1_len != str2_len) {
return false;
}
int rst = 0;
for (int i = 0; i < str1_len; i++) {
if (str1[i] != str2[i]) {
return false;
}
}
return true;
}
int main(void) {
char* str1 = "abc";
char* str2 = "abc";
char* str3 = "abcd";
char* str4 = "bbc";
char str5[] = "abc";
printf("`%s` is equals to `%s` : %d\\n", str1, str1, str_equals2(str1, str1));
// 출력 => `abc` is equals to `abc` : 1
printf("`%s` is equals to `%s` : %d\\n", str1, str2, str_equals2(str1, str2));
// 출력 => `abc` is equals to `abc` : 1
printf("`%s` is equals to `%s` : %d\\n", str1, str3, str_equals2(str1, str3));
// 출력 => `abc` is equals to `abcd` : 0
printf("`%s` is equals to `%s` : %d\\n", str1, str4, str_equals2(str1, str4));
// 출력 => `abc` is equals to `bbc` : 0
printf("`%s` is equals to `%s` : %d\\n", str1, str5, str_equals2(str1, str5));
// 출력 => `abc` is equals to `abc` : 1
return 0;
}
Chapter 27.
문제 1. str_part_equals 함수 구현
#include <stdio.h>
#define true 1
#define false 0
int str_part_equals(char* str1, int start, int end, char* str2) {
int j = 0;
for(int i = start; i < end; i++) {
if(str1[i] != str2[j]) {
return false;
}
j++;
}
return true;
}
int main(void) {
printf("str_part_equals(\\"abcd\\", 0, 2, \\"ab\\") : %d\\n", str_part_equals("abcd", 0, 2, "ab"));
// 출력 => str_equals("abcd", 0, 2, "ab") : 1
printf("str_part_equals(\\"abcd\\", 1, 2, \\"b\\") : %d\\n", str_part_equals("abcd", 1, 2, "b"));
// 출력 => str_equals("abcd", 1, 2, "b") : 1
printf("str_part_equals(\\"abcd\\", 2, 2, \\"\\") : %d\\n", str_part_equals("abcd", 2, 2, ""));
// 출력 => str_equals("abcd", 2, 2, "") : 1
printf("str_part_equals(\\"abcd\\", 2, 4, \\"cb\\") : %d\\n", str_part_equals("abcd", 2, 4, "cb"));
// 출력 => str_equals("abcd", 2, 4, "cb") : 0
printf("str_part_equals(\\"abcd\\", 2, 4, \\"cd\\") : %d\\n", str_part_equals("abcd", 2, 4, "cd"));
// 출력 => str_equals("abcd", 2, 4, "cb") : 1
return 0;
}
문제2. 특정 문장 위치 반환 함수 구현
#include <stdio.h>
#define true 1
#define false 0
int get_str_len(char* str) {
for ( int i = 0; true; i++ ) {
if ( str[i] == '\\0' ) {
return i;
}
}
}
int starts_with(char* str, char* str2) {
int str_len = get_str_len(str);
int str2_len = get_str_len(str2);
if ( str_len < str2_len ) {
return false;
}
for ( int i = 0; i < str2_len; i++ ) {
if ( str[i] != str2[i] ) {
return false;
}
}
return true;
}
int str_part_equals(char* str1, int start, int end, char* str2) {
int j = 0;
for(int i = start; i < end; i++) {
if(str1[i] != str2[j]) {
return false;
}
j++;
}
return true;
}
int get_index_of_str(char* str1, char* str2) {
int str1_len = get_str_len(str1);
int str2_len = get_str_len(str2);
int compare = str1_len - str2_len + 1;
if (str2_len > str1_len) {
return -1;
}
for (int i = 0; i < compare; i++) {
if (starts_with(str1 + i, str2)) {
return i;
}
}
return -1;
}
int get_index_of_str2(char* str1, char* str2) {
}
int main(void) {
int index;
index = get_index_of_str("abc", "b");
printf("index : %d\\n", index);
// 출력 => index : 1
index = get_index_of_str("test", "es");
printf("index : %d\\n", index);
// 출력 => index : 1
index = get_index_of_str("abcd", "bd");
printf("index : %d\\n", index);
// 출력 => index : -1
return 0;
}
JAVA
💡 코드 작성 시 중요하게 생각할 것
- 가독성
- 높은 응집도, 낮은 결합도
- 중복 제거
- 변화하는 것을 변화하지 않는 것으로부터 분리
응집도와 결합도
💡 응집도와 결합도
→ 좋은 설계는 높은 응집도와 낮은 결합도를 가지도록 구성
● 응집도(Cohesion)
- 모듈에 포함된 내부 요소들이 하나의 책임 / 목적을 위해 연결되어 있는 연관된 정도
- 요소들간의 연관성 척도
- 높을수록 좋음
- 응집도가 높으면 변경 대상과 범위가 명확해지는 장점이 있어 유지보수 용이
● 결합도(Coupling)
- 모듈 수정을 위해 다른 모듈의 변경을 요구하는 척도
- 모듈이 다른 모듈에 의존하는 정도의 척도
- 모듈 간 상호 결합 정도
- 낮을수록 좋다
- 결합도가 높으면 검토해야 하는 소스의 수가 많아져 유지보수 어려움
상속과 구성
💡 상속(Inherit)
● 상위 클래스에 대해 종속적
→ 상위 클래스의 변화를 항상 감지해야 하고, 그에 맞추어 진화해야 한다.
● 상위 클래스에서 새로운 메소드 추가 시 하위 클래스에서 반환타입이 다를 경우 컴파일 에러 발생 가능성 있음
💡 구성(Composition)
● 상속의 문제점 보완
● 다른 객체의 인스턴스를 자신의 인스턴스 변수로 포함해서 메소드를 호출하는 기법
● 해당 인스턴스의 내부 구현이 변경되어도 영향을 받지 않음
Chapter 16.
문제 1. 전사의 무기변경 메소드 구현, 데미지 추가
public class c16p1 {
public static void main(String[] args) {
전사 a전사 = new 전사();
a전사.공격();
// 칼(으)로 공격합니다.
// 데미지 : 78
a전사.창_모드로_변경();
a전사.공격();
// 창(으)로 공격합니다.
// 데미지 : 80
a전사.지팡이_모드로_변경();
a전사.공격();
// 지팡이(으)로 공격합니다.
// 데미지 : 12
}
}
class 전사 { // 하나의 클래스 안에 넣는 것은 가장 좋지 않은 예
String 무기이름;
int 데미지;
전사() {
무기이름 = "칼";
데미지 = 78;
}
void 공격() {
System.out.println(무기이름 + "(으)로 공격합니다.");
System.out.println("데미지 : " + 데미지);
}
void 창_모드로_변경() {
this.무기이름 = "창";
this.데미지 = 80;
}
void 지팡이_모드로_변경() {
무기이름 = "지팡이";
데미지 = 12;
}
}
문제2 v1. 문제 1 + a무기 인스턴스 추가
- 좋은 예시
class c16p2 {
public static void main(String[] args) {
전사 a전사 = new 전사();
a전사.공격();
// 칼(으)로 공격합니다.
// 데미지 : 78
a전사.창_모드로_변경();
a전사.공격();
// 창(으)로 공격합니다.
// 데미지 : 80
a전사.지팡이_모드로_변경();
a전사.공격();
// 지팡이(으)로 공격합니다.
// 데미지 : 12
}
}
class 전사 {
무기 a무기;
전사() {
a무기 = new 칼();
}
void 공격() {
a무기.사용();
}
void 창_모드로_변경() {
a무기 = new 창();
}
void 지팡이_모드로_변경() {
a무기 = new 지팡이();
}
}
abstract class 무기 {
String 이름;
int 데미지;
void 사용() { // 중복을 줄여 상위 클래스에 통합
System.out.println(이름 + "(으)로 공격합니다.");
System.out.println("데미지 : " + 데미지);
}
}
class 칼 extends 무기 {
칼() {
이름 = "칼";
데미지 = 78;
}
}
class 창 extends 무기 {
창() {
이름 = "창";
데미지 = 80;
}
}
class 지팡이 extends 무기 {
지팡이() {
이름 = "지팡이";
데미지 = 12;
}
}
문제2 v2. 좋지 않은 예시
- 중복을 사용하여 응집도가 낮아지고, 결합도가 높아진다.
public class c16p2v1 {
public static void main(String[] args) {
전사 a전사 = new 전사();
a전사.공격();
// 칼(으)로 공격합니다.
// 데미지 : 78
a전사.창_모드로_변경();
a전사.공격();
// 창(으)로 공격합니다.
// 데미지 : 80
a전사.지팡이_모드로_변경();
a전사.공격();
// 지팡이(으)로 공격합니다.
// 데미지 : 12
}
}
class 전사 {
무기 a무기;
전사() {
칼_모드로_변경();
}
void 공격() {
a무기.사용();
}
void 창_모드로_변경() {
a무기 = new 창();
}
void 칼_모드로_변경() {
a무기 = new 칼();
}
void 지팡이_모드로_변경() {
a무기 = new 지팡이();
}
}
// 응집도는 높고 결합도가 낮은 것이 좋은 것.
abstract class 무기 { // 자유도는 높지만, 중복되는 것이 많다.
abstract void 사용();
}
class 칼 extends 무기 {
void 사용() {
System.out.println("칼(으)로 공격합니다.");
System.out.println("데미지 : 78");
}
}
class 창 extends 무기 {
void 사용() {
System.out.println("창(으)로 공격합니다.");
System.out.println("데미지 : 80");
}
}
class 지팡이 extends 무기 {
void 사용() {
System.out.println("지팡이(으)로 공격합니다.");
System.out.println("데미지 : 12");
}
}
배열 vs 리스트 and 스트림
배열
💡 ● 크기를 미리 정해야 한다.
● 크기에 따라 컴파일 타임이 정해진다.
● 상황에 따라 공간을 더 늘리거나 줄일 수 없다.
// 숫자 5개
int[] arr = new int[5]; // 크기가 정해져있다.
// 입력
int[0] = 10;
int[1] = 20;
// 출력
System.out.println(arr[1]);
private static void sol2() {
String[] sBits = line.split(" ");
int[] numbers = new int[sBits.length];
int numbersLastIndex = -1;
int sum = 0;
for( String bit : sBits ) {
if (bit.matches("\\\\d+")) {
numbers[++numbersLastIndex] = Integer.parseInt(bit);
}
}
for (int i = 0; i <= numbersLastIndex; i++) {
sum += numbers[i];
}
System.out.println(sum);
}
리스트
💡 ● 배열의 문제점 해결
● 빈틈없는 데이터의 적재
● 순차성을 보장하지 못한다.
// 데이터 N개
ArrayList list = new ArrayList(); // 크기를 직접 정할 필요가 없다.
// 입력
list.add(10);
list.add(20);
// 출력
System.out.println(list.get(1));
// 숫자 N개
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<Integer> list = new ArrayList<>();
List<Integer> list = new ArrayList<>();
private static void sol3() {
String[] sBits =line.split(" ");
ArrayList<Integer> numbers = new ArrayList<>(); // 기억할 능력이 있음
int sum = 0;
for( String bit : sBits ) {
if (bit.matches("\\\\d+")) {
numbers.add(Integer.parseInt(bit));
}
}
for (int number : numbers) {
sum += number;
}
System.out.println(sum);
}
스트림
💡 스트림?
● 데이터의 흐름
● 배열 or 컬렉션 인스턴스에 함수 여러개를 조합해 원하는 결과 필터링 및 가공 가능
● 람다를 이용해 코드의 양을 줄일 수 있다.
● 간단하게 병렬 처리가 가능하다.
private static void sol1() {
int sum = Arrays
.stream(line.split(" ")) // 배열 => 스트림
.filter((s) -> s.matches("\\\\d+"))
// "\\d+" : 10진수 정수 / .matches("\\\\d+") : 10진수 정수로만 이뤄져 있는지 / filter : 필터의 값이 true인 것만 남겨둠
.mapToInt(Integer::parseInt) // 정수 형변환
.sum();
System.out.println(sum);
}
후기 : 매우어렵다. 으악으악 그래도 재미있다 진짜로.. 즐기자 정말 즐기면서 해보자 화이팅
'멋쟁이 사자처럼 BE School' 카테고리의 다른 글
[멋쟁이사자처럼 Back-End School 1기] Day 16. 구조체, supe ,SSG (0) | 2022.07.07 |
---|---|
[멋쟁이사자처럼 Back-End School 1기] Day 14. C언어, JAVA, TDD (0) | 2022.07.05 |
[멋쟁이사자처럼 Back-End School 1기] Day 13. 문자열, GC, JAVA, TDD (0) | 2022.07.04 |
[멋쟁이사자처럼 Back-End School 1기] Day 12. C언어, Java (0) | 2022.06.30 |
[멋쟁이사자처럼 Back-End School 1기] Day 11. C언어, Java (0) | 2022.06.29 |