C언어 자습/혼자공부하는 C언어 (저자 서현우)

문자열과 포인터 버퍼,scanf의 이해

막뇌 2023. 4. 20. 09:42

문자열 상수가 주소라는 증거

#include<time.h>
#include<stdlib.h>
#include<stdio.h>

int main() {
	printf("apple 이 저장된 시작 주소 값 : %p\n", "apple");	//주소값
	printf("두 번째 문자의 주소 값: %p\n", "apple" + 1);	//주소값2
	printf("첫 번째 문자 : %c\n", *"apple");	//간접 참조 연산
	printf("두 번째 문자 : %c\n", *("apple" + 1));	//포인터 연산식
	printf("배열로 표현한 세번째 문자: %c", "apple"[2]);	//배열 표현식
	
	return 0;
}

printf를 사용해서 묻지도 따지지도 않고 상수 apple의 주소값을 호출 했다.

상수 문자 1개당 주소값 1개가 할당되는것을 알 수 있다.

마치 배열처럼 연속된 주소값에 주소값1개당 상수문자가1개가 할당되는 형태이다.

#include<time.h>
#include<stdlib.h>
#include<stdio.h>

int main() {
	char* desseert = "apple";	//포인터에 문자열 초기화

	printf("오늘 후식은 %s입니다. \n", desseert);
	desseert = "banana";	//새로운 문자열 대입
	printf("내일 후식은 %s입니다. \n", desseert);
		
	return 0;
}

포인터에는 문자열 상수의 시작위치 값만 저장되지만 문자열상수가 연속적인 주소값에 위치하기 때문에 포인터 연산으로 간접 참조가 가능하다.

포인터에는 첫 문자의 주소만 저장되지만 null이 나올때까지 연속된 주소값을 따라가다 보면 연속된 문자열 전체를 사용할 수 있게 되는것이다.

 

printf 함수의 %s 변환 문자는 포인터 연산으로 문자열을 출력하는 형태이다.

printf 함수에서 %s 변환문자를 사용하면 함수안에서 다음 코드와 같은 일을 수행합니다.

	while (*dessert != 0)
	{
		putchar (*dessert);
		dessert++;
	}

 

 

버퍼의 이해 / scanf 함수를 사용한 문자열 입력

#include<time.h>
#include<stdlib.h>
#include<stdio.h>

int main() {
	char str[80];
	printf("문자열 입력 : ");
	scanf("%s", str);
	printf("첫 번째 단어 : %s\n", str);
	scanf("%s", str);
	printf("버퍼에 남아 있는 두 번째 단어 : %s\n", str);

	return 0;
}

첫번째 scanf 함수는 공백이 나올때 까지 동작 한다.

그러므로 apple 을 str에 넣고, 첫번째 단어로 출력한다.

 

출력이후 자동으로 두번째 scanf로 넘어오게 되는데 이때, 남은 문자열 jam보다 앞에 있는 모든 공백이나 개행문자를 없애고 시작한다. 사용자가 입력을 apple(공백x10)jam 으로 입력한다고 하자.

apple과 jam 사이에 공백 문자가 10개나 있는데. 이는 apple을 출력하고 난 뒤에 getchar()를 활용해서 버퍼를 빼보면 알 수가 있다. 여전히 버퍼에는 공백이 남아있음에도 불구하고 두번째 scanf 를 사용할 때는 앞에있는 공백을 전부 없애버리고j부터 시작하여 str에 담는다는 이야기다. (공백을 3개까지만 출력 했는데  남은 공백 7개는 실제로 버퍼에서 사라졌다.)

 

 jam\0을 str에 담은 후 개행문자는 여전히 버퍼안에 남아있는걸 알 수 있었다. (아래 코드 참조)

#include<time.h>
#include<stdlib.h>
#include<stdio.h>

int main() {
	char str[80];
	char ch, ch1, ch2, ch3;
	printf("문자열 입력 :");
	scanf("%s", str);
	ch1 = getchar();
	ch2 = getchar();
	ch3 = getchar();
	printf("첫 번째 단어 :%s%c%c%c", str, ch1, ch2, ch3);
	scanf("%s", str);
	printf("버퍼에 남아 있는 두 번째 단어 :%s\n", str);
	ch = getchar();	//버퍼 비우기 (개행문자 남아있음)
	printf("%c", ch);
	return 0;
}

 

공백3개 출력 이후 남은 7개의 공백이 버퍼에서 사라졌다.