강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

변상윤님의 프로필 이미지
변상윤

작성한 질문수

홍정모의 따라하며 배우는 C++

6.6 C언어 스타일의 배열 문자열

cstr직접구현

작성

·

30

0

스크린샷 2025-12-17 000543.png스크린샷 2025-12-17 000552.png

피드백 부탁드립니다.

답변 3

1

안녕하세요? 질문&답변 도우미 durams입니다.

StrCpy_s

복사 이후 destination 문자열의 끝에 널 문자를 추가하는 코드가 누락되어 있습니다.

StrCat_s

이곳에도 concat 이후 destination의 끝에 널 문자를 추가하는 코드가 없습니다.

StrCmp

C 표준 라이브러리의 strcmp는 두 문자열을 사전순(lexicographical)으로 비교해서 첫 번째 문자열이 사전순으로 앞에 위치하는 경우 음수를, 두 번째 문자열이 사전순으로 앞에 위치하는 경우 양수를, 그리고 동일하면 0을 반환합니다. 강의에서의 설명인 '같으면 0, 다르면 -1'은 어느정도 간소화된 설명이라고 볼 수 있습니다.

그런데 질문자님의 코드는 강의에서 설명하는 것과 실제 C 라이브러리 둘 모두와 다른 것으로 보입니다. 어떤 조건이 있을 때 어떻게 반환해야 할 지 한 번 정리해보시는 것을 추천드립니다.


코드만 제시하시고 별다른 말씀이 없으셔서 정확히 어떤 피드백을 요구하시는지 답변해드리기 어려운 느낌이 있습니다. 제가 모두 다 알려드리기에는 질문자님이 수동적으로 공부를 하실 것이 염려되기 때문에, 강의 자체에 대해 어느정도 이해가 되었다고 판단이 되시면 스스로 고민하고 디버깅해보는 시간을 갖는 것이 무척이나 도움이 될 것이라고 확신합니다. 이와 별개로 강의 내용 중 잘 이해가 가지 않는 부분이나 궁금한 내용 등에 대한 질문은 언제나 환영입니다. 또한, 코드를 첨부하시는 경우 이미지보다는 코드 블록 기능을 활용하시면 더 시인성 좋은 글쓰기가 가능하니 다음에 활용해보세요.

변상윤님의 프로필 이미지
변상윤
질문자

널 문자 추가하는걸 잊고있었네요.

cmp같은경우 출력이 양수 1도 출력이 되는걸 보고

"앞에 문자가 같지만 문자열 길이가 다르면 1을 출력되는구나"라고 생각해서 짰었는데,

사전순으로 비교했었군요

네, C 스타일 문자열을 다루는 함수의 경우 널 문자를 기반으로 동작하는 경우가 많기 때문에 언제나 염두에 두는 것이 중요합니다.

0

변상윤님의 프로필 이미지
변상윤
질문자

#include<iostream>
#include<cstring>

bool SafeCheck(char dest[], const unsigned int destSize, const char resource[], const unsigned int resourceSize)
{
	using namespace std;

	int destIndex = 0;
	int srcIndex = 0;
	// Safe Check
	while (destIndex < destSize && dest[destIndex] != '\0')
		destIndex++;

	// destSize와 같으면 \0을 만나지 못했다는 뜻이니
	// 이상함을 감지하고 다시 초기화 해달라고 부탁한다.
	if (destIndex >= destSize)
	{
		cout << "Try again destination initialization..." << endl;
		return false;
	}

	// resource배열이 제대로 들어왔는지 확인
	while (srcIndex < resourceSize && resource[srcIndex] != '\0')
		srcIndex++;

	// resourceSize와 같으면 \0을 만나지 못했다는 뜻이니
	// 이상함을 감지하고 다시 초기화 해달라고 부탁한다.
	if (srcIndex >= resourceSize)
	{
		cout << "Try again resource initialization..." << endl;
		return false;
	}

	return true;
}

void StrCpy_s(char dest[], const unsigned int destSize, const char resource[], const unsigned int resourceSize)
{
	using namespace std;

	if (SafeCheck(dest, destSize, resource, resourceSize) == false)
		return;

	if (destSize < resourceSize)
	{
		cout << "You can not push in destination array beacause lack memory space" << endl;
		return;
	}

	for (int i = 0; i < resourceSize; i++)
	{
		dest[i] = resource[i];
	}

	cout << "StrCpy Result : " << dest << endl;
}

void StrCat_s(char dest[], const unsigned int destSize, const char resource[], const unsigned int resourceSize)
{
	using namespace std;
	
	if (SafeCheck(dest, destSize, resource, resourceSize) == false)
		return;

	int startIndex = 0;
	while (dest[startIndex] != '\0') startIndex++;

	for (int i = 0; i < resourceSize; i++)
	{
		int checkIndex = startIndex + i + 1;
		// nextIndex는 다음 인덱스를 확인하기 위한 변수
		// nextIndex가 destSize사이즈 보다 크거나 같으면
		// 공간 부족 마지막에 \0찍어서 마무리
		if ((checkIndex) == destSize)
		{
			dest[destSize - 1] = '\0';
			continue;
		}
		else if( checkIndex > destSize)
		{
			cout << "You can not push in destination array beacause lack memory space" << endl;
			return;
		}

		dest[startIndex + i] = resource[i];
	}

	cout << "StrCat Result : " << dest << endl;
}

int StrCmp(char dest[], const unsigned int destSize, const char resource[], const unsigned int resourceSize)
{
	if (SafeCheck(dest, destSize, resource, resourceSize) == false)
		return 1;

	for (int i = 0; i < destSize; i++)
	{
		if (dest[i] != resource[i])
		{
			if (dest[i] < resource[i])
				return -1;
			else
				return 1;
		}

		if (dest[i] == '\0' && resource[i] == '\0')
			return 0;
		else if (dest[i] == '\0' || resource[i] == '\0')
		{
			return dest[i] == '\0' ? -1 : 1;
		}
	}
}

int main()
{
	using namespace std;

	char myString[12]{};
	char strA[] = "Hello";
	char strB[] = "World";
	char strC[] = "HelloWorld";

	unsigned int myStringSize = sizeof(myString) / sizeof(char);
	unsigned int strASize = sizeof(strA) / sizeof(char);
	unsigned int strBSize = sizeof(strB) / sizeof(char);
	unsigned int strCSize = sizeof(strC) / sizeof(char);

	StrCpy_s(myString, myStringSize, strA, strASize);
	StrCat_s(myString, myStringSize, strB, strBSize);

	int result = StrCmp(myString, myStringSize, strC, strCSize);
	if ( result == 0)
		cout << "Same Text" << endl;
	else
	{
		cout << "result	: " << result << endl;
		cout << "Diffrent Text" << endl;
	}

	return 0;
}

다시 생각해서 한번 작성해봤습니다.

죄송하게도 열심히 작성해주셨지만, 이번에도 코드만 첨부하시고 별다른 말씀이 없으셔서 질문자님께서 정확히 무엇을 원하는지 제가 알기 어렵네요. 궁금하신 부분을 특정해서 말씀해주시면 답변드리기도 수월합니다. 질문자님의 코드에 반례가 되는 테스트 케이스를 하나하나 다 찾아드릴수도 없는 일이구요. (직접 여러 극단적인 케이스를 입력으로 전달해 보는 것도 방법입니다)

또한 현재 시점에서는 C 표준 라이브러리의 문자열 처리 기능을 완벽히 똑같이 구현하는 것이 목적이라기보다는, 이러한 기능이 존재한다는 것을 알고 비슷하게나마 구현해봄으로써 프로그래밍 연습을 한다는 의미가 더 큽니다. 이번 구현하시면서 공부도 많이 되셨을거에요. 질문자님께서는 주제에 대해 어느정도 깊은 고민을 거치신 듯 하니, 다음 강의로 넘어가셔도 될 듯 합니다.

0

안녕하세요, 인프런 AI 인턴입니다. 상윤님.

작성해주신 코드에 대한 피드백을 드리겠습니다. 먼저, 두 기능인 StrCpy_sStrCat_s는 문자열의 복사와 결합을 안전하게 구현하기 위한 함수입니다. 하지만 몇 가지 개선할 부분들이 보입니다.

1. StrCpy_s 함수

  • 이 함수는 목표대로 잘 작동하는 듯합니다. 특히 복사 과정에서 버퍼 오버플로우를 방지하려는 노력은 commendable합니다. 하지만 조금 더 명료성을 위해 주석을 달아주시면 좋겠습니다.

2. StrCat_s 함수

  • StrCat_s 함수에서는 조건문에 !’\0'와 같은 잘못된 조건이 있습니다. 이 부분은 일반적으로 '\0'을 사용해 문자열 끝을 확인합니다.
  • 문자열을 결합하는 과정에서 충분히 지원하는 destSize를 초과하지 않도록 주의해야 합니다.
  • 널 종료 처리를 추가하여 결합된 문자열의 끝에 올바르게 '\0'을 위치시켜야 합니다.

3. StrCmp 함수

  • 이 함수에서는 'WO'를 사용하는 것이 문제입니다. '\0'이 올바른 사용 예시입니다. 'WO'는 두 개의 문자로 인식될 수 있지만, C++에서는 하나의 문자(혹은 널 문자)를 비교할 때 '\0'을 사용합니다.
  • 문자열 비교 시 %c를 활용할 수 있지만, %s 포맷 문자열을 활용해 다른 방식으로도 접근 가능합니다.

기타 코드 작성에 있어서도 주석이나 코드의 논리 흐름을 더 명확히 설명해 주는 것도 좋은 개선점이 될 수 있습니다.

관련된 기존 질문 및 답변 사례로 더 깊이 있는 정보를 얻고 싶으시다면, 다음의 링크를 참고해 주시기 바랍니다:
- 직접 구현해본 implement_my_strcat/strcmp 입니다.
- C 언어 문자열 처리 및 구현에 관한 질문

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

변상윤님의 프로필 이미지
변상윤

작성한 질문수

질문하기