🏃‍♀️ 코테 연습

[C++] 문자열 문법 정리

ji-hyun 2023. 2. 23. 23:00

제출한 코드

#include <iostream>
#include <string>
using namespace std;

 int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	int n;
	string s;
	cin >> n;
	cin >> s;
	int sum = 0;
	for(int i=0; i<n; i++){ 
	    sum += (s[i] - '0');
	}
	cout << sum;
	return 0;
}

 

 

이론 정리

string 의 인덱스 접근

  • 배열처럼 접근하기

string str = "TEST";

일 때, str[0] 은 "T" 반환한다. 이때 반환되는 문자는 char형임에 주의하자

 

 

char 형 숫자를 int 형으로 변환하는 법

  • 숫자의 아스키 값은 48번부터 0~9를 할당하고 있으므로, char형 '1' 은 정수값 49를 가진다
  • 따라서 0의 아스키 값인 48을 char 형의 값에서 빼주면 순수한 숫자를 얻어낼 수 있다
char c = '1';
int n = c - 48;
// n = 1
  • 위와 같은 코드는 정상적으로 작동은 하지만, 가독성면에서는 좋지 않을 수 있다. 왜냐하면 다른 개발자들이 봤을 때, 48이라는 숫자가 어디서 나온건지 이해가 가지 않을 수도 있기 때문이다
  • 아래와 같이 작성을 추천
char c = '1';
int n = c - '0';
// n = 1

다시 말해 0이라는 문자는 숫자 48값을 가진다

 

 

 

 


내가 제출한 코드

#include <iostream>
#include <string>
using namespace std;

 int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	int arr[26];
	fill_n(arr, 26, -1); // -1 로 초기화
	string s;
	cin >> s;
	for(int i=0; i<s.length(); i++){
	    int z = s[i] - 'a'; // 자리: a 이면 z 는 0 이다
	    arr[z] = s.find(s[i]); 
	}

	for (int v : arr) cout << v << " ";

	return 0;
}

 

(내 생각)

 

  1. 알파벳 26개를 int 형 배열로 만들어서 모든 원소를 -1 로 초기화 (fill_n 메서드 활용)
  2. 입력받은 문자 첫번째가 만약 b 라고 가정해보자
  3. 알파벳 자리는 b - a 를 아스키코드로 변환하면 1 이라는 자리를 찾게 된다
  4. 배열[자리] = 해당 문자 위치 인덱스
  5. 해당 문자 위치 인덱스 는 find 함수를 활용해보았다

 

 

다른 사람 코드

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    string alphabet = "abcdefghijklmnopqrstuvwxyz";
    cin >> s;
    for(int i = 0; i < alphabet.length(); i++)
        cout << (int)s.find(alphabet[i]) << " ";
    return 0;
}

 

(int) 를 붙이는 이유를 찾아보았다

 

만약 없는 문자열을 찾으려 할 경우에는 string::npos가 반환된다.

npos의 값은 -1로 정의되어있지만, string::npos의 자료형이 unsigned이므로 2의 보수 개념에 의해 표현할 수 있는 최대 크기의 양수가 출력된다. 이를 방지하기 위해서는 unsigned가 아닌 일반 int형으로 캐스팅을 진행하여 출력하면 된다.

그래서 18446744073709551615 (unsigned형의 -1이므로 표현할 수 있는 최대 크기의 양수) 를 반환한다고 한다 이를 int 형으로 바꾸면 -1 됨

 

 

 

 


C 와 C++ 의 경우에는 배열 선언은 기본적으로 컴파일 타임에 크기가 결정된다

반대로 가변 길이 배열의 경우에는 int arr[n] 라고 작성하게 되면 컴파일 타임에는 해당 변수에 대한 타입 정보 정도만 갖고 있고 런타임에 n 이 주어지게 되면 그때 되어서야 n의 크기를 읽고 할당을 하게 된다

 

int main() {
	int size;
	cin >> size;
 
	int arr[size];
}

 

int arr[size] 형태를 가르치지 않는 이유는 C++ 표준 문법이 아니다

해당 문법은 C99 의 문법인데, C++의 경우 C의 환경도 포함되어 있다보니 가능해진 것이다 실제 C++ 표준으로만 컴파일을 하게 되면 에러가 나거나, 컴파일러마다 차단된 경우들이 있다

 

int* arr = new int[size];

 

위처럼 선언하는 방식이 올바른 방식이다

마지막으로 가장 편리한 방식이 있다

 

 

바로 vector 클래스를 사용하는 것이다

vector 의 경우 사이즈를 결정하지 않아도 자유롭게 원소를 추가, 삭제 등을 수행할 수 있는 자료구조 클래스이다

 

 

 

 

소수점 출력과 관하여..

다음 두 가지 방식으로 출력을 할 수 있다

 

printf("%.3lf%%", result);	// %기호를 출력하려면 %% 를 해야한다.
 
// or
 
cout << fixed;
cout.percision(3);
cout << result << "%";

 

 

 

 

다음은 vector 클래스를 사용하는 방식이다

int N;
cin >> N;
 
// 동적 배열 선언 및 생성
vector<int> vec;
 
for(int i = 0; i < N; i++) {
	int value;
	cin >> value;
	vec.push_back(value);	// 벡터의 맨 마지막 원소 뒤에 원소 추가
}

사실 vector 클래스를 사용하면 vector 자체가 가변적이라서 N을 넘겨줄 필요가 없다

 

 

 

 

 

 

방법 1)

#include <iostream>
 
using namespace std;
 
void func();
 
int main(int argc, const char *argv[]) {
 
	int C;
	cin >> C; // test case
 
	for (int i = 0; i < C; i++) {
		func();
	}
 
	return 0;
}
 
void func() {
	int N;
	cin >> N;
 
	// 동적 배열 선언 및 생성
	int *arr = new int[N]; // 혹은 int* arr = (int*)malloc(sizeOf(int) * size)
 
	for (int i = 0; i < N; i++) {
		cin >> arr[i]; // i ~ N - 1 까지 입력받은 요소로 초기화
	}
 
	// 평균 구하기
	double avg = 0;
	for (int i = 0; i < N; i++) {
		avg += arr[i]; // 모든 성적 누적합
	}
	avg = avg / N; // 누적합에 대해 N으로 나눈다.
 
	// 평균 점수를 넘는 인원 수 구하기
	double count = 0;
	for (int i = 0; i < N; i++) {
		if (arr[i] > avg) {
			count++;
		}
	}
 
	// 평균을 넘는 인원 %
	double result = (count / N) * 100;
	cout << fixed;
	cout.precision(3);
	cout << result << "%\n";
 
	delete[] arr; // 동적 할당을 할 경우에는 더이상 안쓰는 경우 반드시 메모리 해제를 해야한다.
}

 

delete 써줘야 함

 

 

 

방법 2)

#include <iostream>
#include <vector>
 
using namespace std;
 
void func();
 
int main(int argc, const char *argv[]) {
 
	int C;
	cin >> C; // test case
 
	for (int i = 0; i < C; i++) {
		func();
	}
 
	return 0;
}
 
void func() {
	int N;
	cin >> N;
 
	// 동적 배열 선언 및 생성
	vector<int> vec;
 
	for (int i = 0; i < N; i++) {
		int value;
		cin >> value;
		vec.push_back(value); // 벡터의 맨 마지막 원소 뒤에 원소 추가
	}
 
	// 평균 구하기
	double avg = 0;
	for (auto &val : vec) {
		avg += val; // 모든 성적 누적합
	}
	avg = avg / N; // 누적합에 대해 N으로 나눈다.
 
	// 평균 점수를 넘는 인원 수 구하기 (for-each)
	double count = 0;
	for (auto &val : vec) {
		if (val > avg) {
			count++;
		}
	}
 
 
	// 평균을 넘는 인원 %
	double result = (count / N) * 100;
	cout << fixed;
	cout.precision(3);
	cout << result << "%\n";
}

 

 

 

 

 


배열 선언 및 초기화

1. 일부 값만 초기화된 경우
int arr1[5] = {10, 20, 30};
-> 10, 20, 30, 0, 0

2. brace 만 선언된 경우 : 배열 값은 0으로 초기화됨
int arr2[5] = {}

3. 0으로 초기화하는 방법
-> int a[100];
-> int b[100] = {};
-> int c[100] = {0,};
-> int d[100] = {0};

 

 

 

 

'🏃‍♀️ 코테 연습' 카테고리의 다른 글

[C++] 백준 10951번  (0) 2023.02.10
[C++] 백준 15552번  (0) 2023.02.08
27. N!의 표현법  (0) 2021.06.23
26. 말아톤  (0) 2021.06.19
스터디 1일차  (0) 2021.06.17