재귀 함수 호출을 쓰는데 에러가 발생합니다.
조회수 885회
#include <iostream>
#include <string>
std::string reverseParentheses(std::string s) {
int strLen = (int)(s.size());
int parStart = 0;
int parEnd = 0;
int parInnerLen = 0;
int isParExist = 0;
char temp;
//괄호 탐색
for (int i = 0; i < strLen; i++) {
if (s[i] == '(') {
parStart = i;
isParExist++;
} else if (s[i] == ')') {
parEnd = i;
isParExist++;
break;
}
}
//괄호 존재 여부와 괄호 안 문자의 개수 결정
if (isParExist == 0) {
return s;
} else {
parInnerLen = parEnd - parStart - 1;
}
//바괄호 내 모든 문자 뒤집기
for (int i = parStart + 1, j = parEnd - 1; i < (parInnerLen / 2) + (parStart + 1); i++, j--) {
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
//괄호 삭제
s.erase(s.begin() + parStart);
s.erase(s.begin() + parEnd - 1);
reverseParentheses(s);
}
int main() {
std::string str = "co(de(fight)s)";
//예상 결과: cosfighted
std::string revStr = reverseParentheses(str);
for (const char& cIdx : revStr) {
std::cout << cIdx;
}
std::cout << "\n";
return 0;
}
괄호 안에 있는 글자만 역으로 뒤집는 알고리즘을 짜고 있는데요. 괄호가 중첩되는 경우를 고려하면 함수를 재귀적으로 호출하는 것이 나을 것 같아서 그렇게 짰는데
Control may reach end of non-void function
이런 경고가 뜨고 컴파일을 강제 수행하면 SIGSEGV 에러가 납니다.
어디가 문제인 건가요?
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
원인은 간단합니다.
반환 값을 갖는 함수가 반환을 하지 않아서
Control may reach end of non-void function
와 같은 경고를 컴파일러가 발생시킨 것이고, 실행 중 std::string이 반환 될것으로 동작하나 실제로 반환되지 않았기에 잘못된 메모리에 접근하게 되어 SIGSEGV와 같은 예외가 발생한 것 입니다.std::string reverseParentheses(std::string s) { int strLen = (int)(s.size()); int parStart = 0; int parEnd = 0; int parInnerLen = 0; int isParExist = 0; char temp; //괄호 탐색 for (int i = 0; i < strLen; i++) { if (s[i] == '(') { parStart = i; isParExist++; } else if (s[i] == ')') { parEnd = i; isParExist++; break; } } //괄호 존재 여부와 괄호 안 문자의 개수 결정 if (isParExist == 0) { return s; } else { parInnerLen = parEnd - parStart - 1; } //바괄호 내 모든 문자 뒤집기 for (int i = parStart + 1, j = parEnd - 1; i < (parInnerLen / 2) + (parStart + 1); i++, j--) { temp = s[i]; s[i] = s[j]; s[j] = temp; } //괄호 삭제 s.erase(s.begin() + parStart); s.erase(s.begin() + parEnd - 1); return reverseParentheses(s); }
- 그런데 코드 상에서는 괄호를 계속 삭제하고 있고, 괄호가 없으면 s를 리턴하며 종료되게 되어 있는데 그러면 값을 반환하는 것 아닌가요? 이 코드를 goto문으로 바꾸면 잘 동작합니다. 그런데 goto문은 되도록 쓰지 말라는 이야기가 많아서... 알 수 없는 사용자 2018.9.22 10:39
- 작성하신 함수에서 isParExist 가 0일 때만 정상적인 반환이 이루어집니다. 그렇다면 isParExist 가 0 이 아닐 경우는 어떻게 될까요? 제귀 함수란 꼬리에 꼬리를 무는 함수호출인데 isParExist가 0이되는 경우는 가장 마지막 호출이 될것 입니다. 최초의 호출은 reverseParentheses()의 반환 값을 얻길 원하지만 return을 사용한 곳은 reverseParentheses() -> reverseParentheses() -> ... -> reverseParentheses() 상황에서 가장 마지막 호출에서만 하게 되는데 그렇다면 최초 호출은 return 을 통해 값을 받지 못하는 경우가 되는 것이지요. 유동욱 2018.9.22 21:11
- 아...이해했습니다. 어이없는 실수를 했네요;; 답변 감사합니다. 알 수 없는 사용자 2018.9.22 22:11
댓글 입력