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

현정님의 프로필 이미지
현정

작성한 질문수

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

14.4 구조체의 배열 연습문제

14.4 문자열을 받는 함수

작성

·

392

1

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX_TITLE 40
#define MAX_AUTHOR 40
#define MAX_BOOKS 3	/* maximum number of books */

char* s_gets(char* st, int n)
{
	char* ret_val;
	char* find;

	ret_val = fgets(st, n, stdin);  // vs. scanf()
	if (ret_val)
	{
		find = strchr(st, '\n');	// look for newline
		if (find)					// if the address is not NULL
			*find = '\0';			// place a null character there
		else
			while (getchar() != '\n')
				continue;			// dispose of rest of line
	}

	return ret_val;
}

struct book
{
	char title[MAX_TITLE];
	char author[MAX_AUTHOR];
	float price;
};

int main()
{
	struct book library[MAX_BOOKS] = { {"Empty", "Empty", 0.0f}, }; /* array of book structures */

	int count = 0;

	while (1)
	{
		printf("Input a book title or press [Enter] to stop.\n>>");
		if (s_gets(library[count].title, MAX_TITLE) == NULL) break;
		if (library[count].title[0] == '\0') break;


		printf("Input the author.\n>>");
		s_gets(library[count].author, MAX_AUTHOR);

		printf("Input the price.\n>>");
		int flag = scanf("%f", &library[count].price);
		while (getchar() != '\n')
			continue;

		count++;

		if (count == MAX_BOOKS)
		{
			printf("No more books.\n");
			break;
		}
	}

	if (count > 0)
	{
		printf("\nThe list of books:\n");
		for (int index = 0; index < count; index++)
			printf("\"%s\" written by %s: $%.1f\n",
				library[index].title, library[index].author, library[index].price);
	}
	else
		printf("No books to show.\n");

	return 0;
}

안녕하세요, 해당 코드에서 구조체에 대한 부분은 아니지만 궁금증이 생겨 질문 남깁니다.

문자열을 받아 구조체의 문자열 멤버에 넣는 사용자 정의함수 s_gets()에 대한 질문인데요,

해당 예제에서는 s_gets()의 arguments로 title, author 등의 배열 형태가 들어가는데, 사실 함수 안에서는 배열이 포인터로 decay된다고 알고 있습니다.

그렇게 된다면 함수 안에서는 문자열을 다룰 때 read-only가 되어 변경할 수 없게 되는 것 아닐까요? 그런데 해당 코드의 s_gets()함수에서는 '\n'을 찾아 '\0'으로 바꾸고 있어서 살짝 헷갈립니다.

argument인 library.title, library.author 등이 본체는 배열이기 때문에 문제가 없는 걸까요?

 

답변 1

1

안녕하세요, 답변 도우미 Soobak 입니다.

C언어에서 배열의 이름은 포인터와 호환이 되는 형태입니다.
배열의 이름이 함수의 인수로 전달될 때 포인터로 변환이 되는 것은 맞습니다.
하지만, 배열의 시작 주소를 가리키는 포인터로 변환되는 것이기 때문에, 이 포인터를 통하여 함수 내부에서 배열의 내용을 변경하는 것이 가능합니다.

즉, 배열의 이름이 함수의 인수로 전달될 때 포인터로 변환되더라도, 배열의 내용을 변경할 수 있는 유효한 메모리 주소를 가리키는 포인터 이기 때문에 함수 내에서 해당 배열의 내용을 변경하는 것이 가능합니다.

현정님의 프로필 이미지
현정

작성한 질문수

질문하기