작성
·
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언어에서 배열의 이름은 포인터와 호환이 되는 형태입니다.
배열의 이름이 함수의 인수로 전달될 때 포인터로 변환이 되는 것은 맞습니다.
하지만, 배열의 시작 주소를 가리키는 포인터로 변환되는 것이기 때문에, 이 포인터를 통하여 함수 내부에서 배열의 내용을 변경하는 것이 가능합니다.
즉, 배열의 이름이 함수의 인수로 전달될 때 포인터로 변환되더라도, 배열의 내용을 변경할 수 있는 유효한 메모리 주소를 가리키는 포인터 이기 때문에 함수 내에서 해당 배열의 내용을 변경하는 것이 가능합니다.