write set 인 wfds를 출력으로하는 select 문 예제

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/select.h>

#define BUF_SIZE 30

int main(int argc, char *argv[])
{
	fd_set reads, temps, wset; //fd선언
	int result, str_len;
	char buf[BUF_SIZE];
	struct timeval timeout;

	FD_ZERO(&wset); // fd배열을모두 0값으로 초기화
	//FD_SET(0, &reads); // 0 is standard input(console)
  FD_SET(1, &wset);

  
	/*
	timeout.tv_sec=5;
	timeout.tv_usec=5000;
	*/

	while(1)
	{
		temps=wset;
		timeout.tv_sec=5;
		timeout.tv_usec=0;
    //printf("select 직전 \n");
		result=select(9, 0, &wset, 0, &timeout);
		if(result==-1)
		{
			puts("select() error!");
			break;
		}
		else if(result==0)
		{
			puts("Time-out!");
		}
		else 
		{
			if(FD_ISSET(1, &wset)) 
			{
				//str_len=read(0, buf, BUF_SIZE);
				//buf[str_len]=0;
				//printf("message from console:");
        sleep(5);
			}
		}
    printf("끝\n");
	}
  //printf("끝\n");
	return 0;
}

구조체안의 멤버를 처리 해본다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct tagAddress
{
	char name[6];		// 이름
	char phone[20];		// 전화
	char address[72+1];	// 주소
	char detail[200];	// 디테일
};

void main(void)
{
	struct tagAddress ad1; //일반 구조체변수 선언
	struct tagAddress* pad1; //포인터 구조체변수 선언
	//포인터 구조체를 선언하면 일반 구조체변수를 포인터 구조체에 저장 해야한다.
	pad1 = &ad1;

	struct tagAddress ad2; //일반 구조체변수 선언
	struct tagAddress* pad2; //포인터 구조체변수 선언
	//포인터 구조체를 선언하면 일반 구조체변수를 포인터 구조체에 저장 해야한다.
	pad2 = &ad2;

	struct tagAddress ad3; //일반 구조체변수 선언
	struct tagAddress* pad3; //포인터 구조체변수 선언
	//포인터 구조체를 선언하면 일반 구조체변수를 포인터 구조체에 저장 해야한다.
	pad3 = &ad3;

	//구조체에 각각 값넣기
	strcpy(ad1.name, "name1");
	strcpy(ad1.phone, "phoneNumber1");
	strcpy(ad1.address, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa72");

	strcpy(ad2.name, "name2");
	strcpy(ad2.phone, "phoneNumber2");
	strcpy(ad2.address, "abcdefghijklmbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb22");

	strcpy(ad3.name, "name3");
	strcpy(ad3.phone, "phoneNumber3");
	strcpy(ad3.address, "abcdefghijklmcccccccccccccccccccccccccccccccccccccccc33");
	strcpy(ad3.detail, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa72_sssdddsd__");

	printf("이름1 : %s \n", ad1.name);
	printf("전화1 : %s \n", ad1.phone);
	printf("주소1 : %s \n\n", ad1.address);

	printf("이름2 : %s \n", ad2.name);
	printf("전화2 : %s \n", ad2.phone);
	printf("주소2 : %s \n", ad2.address);

	printf("이름3 : %s \n", ad3.name);
	printf("전화3 : %s \n", ad3.phone);
	printf("주소3 : %s \n\n", ad3.address);
	printf("디테일3 : %s \n", ad3.detail);

	//2구조체의 이름을 1에 복사
	//(*pad1).name = &pad2 -> name;
	
	//첫번째 네임의 1열부분에 두번째 네임 복사.
	//memcpy(&ad1.name[1], pad2->name, sizeof(ad1.name)-1);

	//100열에 해당하는 어드레스를 5열 네임에 해당하는 5바이트로 짤라서 네임에 저장
	//memcpy(ad1.name, ad2.address, sizeof(ad1.name)-1);  //스트링의 마지막은 0이어야 하므로 마지막 0을 제외한것을 잘라줘야함
	//memcpy(pad1->name, pad2->address, sizeof(ad1.name) - 1);
	
	//strncpy(ad1.name, ad2.address, sizeof(ad1.name)-1); //배열 마지막에 0이 들어가야하므로 -1

	//아드레스2의 5열부터 복사해서 디테일3에 저장. 즉 아드레스2열의 0~4열까진 버림 // +1은 1부터시작이고 [1]는 0부터시작임 즉 +156은 앞에 156자리수를 버리고 157부터 처리
	//memcpy(pad3->detail, pad2->address+5, sizeof(ad2.address));

	/********중요*************/
	// 헤더와 전문이 같이 있는 디테일3을 앞에 72자리를 자른 뒤73바이트 길이를 가진 아드레스1에 넣는다.
	//memcpy(pad1->address+0, pad3->detail + 72, sizeof(ad1.address)); //+로 쓰는 문장
	//memcpy(pad1->address, &ad3.detail[72], sizeof(ad1.address)); //배열로 쓰는 문장
	//memcpy(ad1.address, &ad3.detail[72], sizeof(ad1.address)); //0번배열부터 쓴다면 [0]은 생략해도 된다
	//memcpy(&ad1.address, &ad3.detail+72, sizeof(ad1.address)); 
	
	//포인터 꺽쇠는 가르키는 것이라 +로만 써야한다. 배열로 쓰려면


	//printf("사이즈 sizeof(ad1.name) : %d \n", sizeof(ad1.name));
	printf("\n======포인터 구조체 적용====\n\n");


	printf("이름1 : %s \n", ad1.name);
	printf("전화1 : %s \n", ad1.phone);
	printf("주소1 : %s \n", ad1.address);

	printf("이름2 : %s \n", ad2.name);
	printf("전화2 : %s \n", ad2.phone);
	printf("주소2 : %s \n", ad2.address);

	printf("이름3 : %s \n", ad3.name);
	printf("전화3 : %s \n", ad3.phone);
	printf("주소3 : %s \n\n", ad3.address);
	printf("디테일3 : %s \n", ad3.detail);

	//값 입력
	//strcpy((*pad1).name, "홍길2");
	//strcpy((*pad1).phone, "02-1234-5672");
	//strcpy((*pad1).address, "서울시 양천구 목동아파트 2단지");

	//printf("이름 : %s \n", pad->name);
	//printf("전화 : %s \n", pad->phone);
	//printf("주소 : %s \n", pad->address);
}

 

 

'C언어' 카테고리의 다른 글

select 함수  (0) 2023.03.10
4. 구조체를 함수에서 사용하기  (0) 2022.08.15
3. 구조체 포인터  (0) 2022.08.15
2. 문자포인터와 정수 포인터  (0) 2022.08.15
1. C언어 콘솔 찍기  (0) 2022.05.31

struct로 만든 구조체를 함수에 넣어주려면 &를 붙여야하고

함수에서 파라미터 선언을 할때는 *를 붙여야 한다.

 

예제코드로 살펴보자

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

void print(struct tagAddress* pad);

struct tagAddress
{
	char name[30];		// 이름
	int *phone;		// 전화
	char address[100];	// 주소
};

void main(void)
{
	struct tagAddress ad;

	strcpy(ad.name, "홍길동");
	ad.phone = 12345678;
	strcpy(ad.address, "서울시 양천구 목동아파트 13단지");

	print(&ad);
}

void print(struct tagAddress* pad) //함수에서 포인터 구조체로 선언을 해주었다.
{
	printf("이름 : %s \n", pad->name);
	printf("전화 : %d \n", pad->phone);
	printf("주소 : %s \n", pad->address);

	//파라미터를 가져와 저장을 한번 해본다.
	printf("======파라미터 저장 후===== \n");
	
	strcpy(pad->name, "정쓰1");
	pad->phone =1234;
	//memcpy(*((*pad).phone), tempPhone, sizeof(int));
	strcpy(pad->address, "정쓰1의 주소");

	printf("이름2 : %s \n", pad->name);
	printf("전화2 : %d \n", pad->phone);
	printf("주소2 : %s \n", pad->address);

}

 

*는 쓸때는 2가지이다.

1. 포인터 변수를 선언 할때

2. 포인터로 선언한 A에 B를 복사하고 싶을 때 *를 A앞에 씀. 그리고 B는 주소값이 아니라 실제값이어야 함.

(만약 주소 값을 복사하고 싶으면 A는 그대로 B앞엔 &를 붙혀줌)

1. 기본 구조체 포인터 (* 선언에 없음)

struct로 구조체를 만드는데 java로 따지면 hashmap정도가 되겠다.

마침표 .을 이용해서 값을 저장하고 꺼내올 수 있다.

#include <stdio.h>
#include <string.h>

struct tagAddress
{
	char name[30];		// 이름
	char phone[20];		// 전화
	char address[100];	// 주소
};

void main( void ) 
{
	struct tagAddress ad;

	strcpy( ad.name, "홍길동" );
	strcpy( ad.phone, "02-1234-5678" );
	strcpy( ad.address, "서울시 양천구 목동아파트 13단지" );

	printf( "이름 : %s \n", ad.name );
	printf( "전화 : %s \n", ad.phone );
	printf( "주소 : %s \n", ad.address );
}

결과값

이름 : 홍길동
전화 : 02-1234-5678
주소 : 서울시 양천구 목동아파트 13단지

 

2.  구조체를 포인터 구조체로 선언함. 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct tagAddress
{
	char name[30];		// 이름
	char phone[20];		// 전화
	char address[100];	// 주소
};

void main(void)
{
	struct tagAddress ad; //일반 구조체변수 선언
	struct tagAddress *pad; //포인터 구조체변수 선언
	//포인터 구조체를 선언하면 일반 구조체변수를 포인터 구조체에 저장 해야한다.
	pad = &ad;

	strcpy(ad.name, "홍길동");
	strcpy(ad.phone, "02-1234-5678");
	strcpy(ad.address, "서울시 양천구 목동아파트 13단지");

	printf("이름 : %s \n", ad.name);
	printf("전화 : %s \n", ad.phone);
	printf("주소 : %s \n", ad.address);
	printf("\n======포인터 구조체 적용====\n\n");

	//값 입력
	strcpy((*pad).name, "홍길2");
	strcpy((*pad).phone, "02-1234-5672");
	strcpy((*pad).address, "서울시 양천구 목동아파트 2단지");

	printf("이름 : %s \n", pad->name);
	printf("전화 : %s \n", pad->phone);
	printf("주소 : %s \n", pad->address);
}

 

결과값

이름 : 홍길동
전화 : 02-1234-5678
주소 : 서울시 양천구 목동아파트 13단지

======포인터 구조체 적용====

이름 : 홍길2
전화 : 02-1234-5672
주소 : 서울시 양천구 목동아파트 2단지

 

3. 구조체 안에 포인터 변수가 있는 형태

구조체 안에 포인터 변수를 알아보자

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct tagAddress
{
	char name[30];		// 이름
	int phone;		// 전화
	char address[100];	// 주소
	char *email[100];  // 이메일  //구조체안에 변수는 포인터변수던 그냥이던 똑같이 변수를 넣고 반환할 수 있다.
	int *byear; //생년월일  //구조체안에 변수는 포인터변수던 그냥이던 똑같이 변수를 넣고 반환할 수 있다.
};

void main(void)
{
	struct tagAddress ad; //일반 구조체변수 선언
	struct tagAddress *pad; //포인터 구조체변수 선언
	//포인터 구조체를 선언하면 일반 구조체변수를 포인터 구조체에 저장 해야한다.
	pad = &ad;

	//값 입력
	strcpy(ad.name, "홍길동");
	//strcpy(ad.phone, "0212345678"); XX 사용안됨 int 형이므로 =이용

	ad.phone = 101234; //값 처음에 0이 들어가면 안된다.
	
	strcpy(ad.address, "서울시 양천구 목동아파트 13단지");
	strcpy(ad.email, "dream1@nate.com");
	ad.byear = 97090911; //값 처음에 0이 들어가면 안된다.

	//출력

	printf("이름 : %s \n", ad.name);
	printf("전화 : %d \n", ad.phone);
	printf("주소 : %s \n", ad.address);
	printf("이메일 : %s \n", ad.email);
	printf("생년월일 : %d \n", ad.byear);

	printf("\n======포인터 구조체 적용====\n\n");

	//값 입력
	strcpy((*pad).name, "홍길2");
	ad.phone = 201234; //값 처음에 0이 들어가면 안된다.
	strcpy((*pad).address, "서울시 양천구 목동아파트 2단지");
	strcpy((*pad).email, "dream1@nate.com2");
	ad.byear = 97090912; //값 처음에 0이 들어가면 안된다.

	//출력
	printf("이름 : %s \n", pad->name);
	printf("전화 : %d \n", pad->phone);
	printf("주소 : %s \n", pad->address);
	printf("이메일 : %s \n", pad->email);
	printf("생년월일 : %d \n", pad->byear);
}

결과값

이름 : 홍길동
전화 : 101234
주소 : 서울시 양천구 목동아파트 13단지
이메일 : dream1@nate.com
생년월일 : 97090911

======포인터 구조체 적용====

이름 : 홍길2
전화 : 201234
주소 : 서울시 양천구 목동아파트 2단지
이메일 : dream1@nate.com2
생년월일 : 97090912

 

4. 구조체안에 포인터멤버가 있고 메모리를 할당하는 형태

코드를 보기전에 설명을 하면은

 

* 일반 선언된 구조체안에 멤버에 값을 넣어줄 때는

d1.numPtr = &num, d1.c = 'x'형태로 쓴다. (포인터 멤버(*)든 일반 멤버든 상관 없음)

 

* 포인터로 선언된 구조체안의 멤버에 값을 넣어줄 때는

d2->numPtr = &num, d2->c = 'y' 형태로 쓴다. (포인터 멤버(*)든 일반 멤버든 상관 없음)

또는 (*d2).numPtr, (*d2).c 형태로 써도 된다.

 

화살표 꺽쇠모양은 -> 이 포인터의 값(*d2)을 불러와서 그 값안의 멤버(numPtr)를 호출하는 기능이다.

따라서 꺽쇠는 포인터로 선언된 구조체에만 써야한다.

 

 

(*d2).numPtr을 쉽게 설명하면  dr이라는 구조체를 호출하여 자물쇠*를 푼다. 그뒤 푼값의 numPtr을 가르킨다.

참고로 자물쇠를 풀지않은 d2의 멤버가 정수형일 경우 주소를 가르킨다.

 

그래서 정수형일 경우는 &num처럼 &를 붙혀줘야한다.

 

꺽쇠는 *를 붙혀 자물쇠를 풀고 값을 가르키는 2가지 기능이 있다는 것을 알아두자.

 

printf로 값을 볼 때는 주소값이 아닌 값을 봐야한다.

 

일반 선언된 구조체는

printf("*d1.numPtr : %d\n", *d1.numPtr);

printf("d1.c : %c\n", d1.c);

로 볼수 있다.

 

d1.numptr자체는 주소이므로 *를 붙혀서 자물쇠를 풀어줘야 한다.

 

포인터로 선언된 구조체는 아래와 같이 프린트해야 한다.

printf("*d1->numPtr : %d\n", *d2->numPtr);

printf("d1->c : %c\n", d2->c);

 

 

풀소스 코드

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

typedef struct Data_s {
    char c;
    int* numPtr;    // 포인터
}Data;

int main()
{
    int num = 10;
    Data d1;    // 구조체 변수 선언
    Data* d2 = malloc(sizeof(Data));  // 구조체 포인터 변수 선언 및 메모리 할당

    //값 저장
    d1.numPtr = &num; //구조체 d1의 멤버인 numPtr에 num의 메모리 주소를 전달
    d2->numPtr = &num; //d2에 있는 Data의 메모리 주소를 역참조하여 멤버인 numPtr에 num의 메모리 주소 전달
    
    d1.c = 'x';
              //
    printf("d1.c : %c\n", d1.c);
    printf("*d1.numPtr : %d\n", *d1.numPtr);   // 구조체의 멤버를 역참조
    
    printf("*d2->numPtr : %d\n", *d2->numPtr);  // 구조체 포인터의 멤버를 역참조
    
    //아래처럼도 쓸수 있음
    //printf("*d2->numPtr : %d\n", *((*d2).numPtr));
    
    printf("sizeof(Data) : %d\n", sizeof(Data));    // 구조체의 크기

    //  *d2->numPtr = *((*d2).numPtr)= *(numPtr)


    //값 저장
    d2->c = 'y';                 //구조체 포인터 역참조하여 멤버 c에 접근해 b 값 넣기

   printf("(*d2).c : %c\n", (*d2).c);      //  b: 구조체 포인터를 역참조하여 c에 접근
                                   // d2->c과 같음

   printf("%d\n", *(*d2).numPtr); // 10: 구조체 포인터를 역참조하여 numPtr에 접근한 뒤 다시 역참조
                                   // *d2->numPtr과 같음

    free(d2);

    return 0;
}

 

이 단원에서 가장 중요한 것은

-> 는 포인터의 자물쇠를 *를 붙혀서 풀어, 정수인 경우 주소값을, 문자열인경우 값을 반환 한다는 것이다.

d2->numPtr = &num    이것은 (*d2).numPtr = &num와 같다.

 

포인터*는 나중에 참조가 되는 값으로 먼저 참조하려면 반드시 소괄호를 붙혀줘야 한다.

 

문자열과 정수가 다른 이유는 문자열은 값자체가 1byte로 이루어져 있지만 정수는 int형인 경우 4바이트에 21억4700만까지이기 때문에 반드시 주소값으로 처리를 해줘야한다.

 

자바나 파이썬은 이런 것을 고려할 필요가 없지만 c언어는 고려해야한다.

 

같은 원리로 정수형의 경우 =라는 shallow copy가 아닌 deep copy로 해야한다.

 

memcpy와 strcpy는 malloc()으로 메모리를 할당하고 =으로 얕은 복사를 하는 두가지 기능을 다 담고 있다.

 

 

 

 

 

 

 

 

 

 

1. 문자 포인터

c언어에서 문자포인터는 선언은 *을 붙히지만 포인터변수에 값을 저장 할때 &를 안붙혀도 된다.

문자배열 자체가 포인터 이기 때문이다. 포인터변수=문자배열대표값

 

아래 코드를 참조

#define _CRT_SECURE_NO_WARNINGS //비쥬얼 스튜디오에서 strcpy를 쓰려면 붙혀줘야함
#include <stdio.h>
#include <string.h>

void main(void)
{
	//문자 포인터 배열
	char ochar[] = "Korea";
	char ochar2[5+1] = "China"; //5글자를 입력하려면 글자 총 길이에 +1을 해줘야함
	char* pchar;

	pchar = ochar; //&를 안붙혀줘도 된다.


	puts(ochar);		// "Korea"
	puts(pchar);		// "Korea"

	strcpy(pchar, "Japan");


	puts(ochar);		// "Japan"
	puts(pchar);		// "Japan"

	memcpy(ochar, ochar2, sizeof(ochar2));
	// 
	//아래와 같이 써도 된다.
	//memcpy(ochar, ochar2, sizeof(char)*5); //china가 5바이트 이므로 길이에 5를 넣어줬다.
	//memcpy(ochar, ochar2, (strlen(ochar2))); //strlen으로 스트링의 길이를 넣어줬다.
	//strcpy(ochar, ochar2);  //단순 스트링 카피
	//strncpy(ochar, ochar2, strlen(ochar2));  //단순 스트링 카피

	printf("ochar 배열마지막 %p \n", ochar[5]); //마지막 배열의 주소는 0인 것을 볼수 있다.

	puts(ochar);		// "Japan"
	puts(ochar2);		// "Japan"
	puts(pchar);		// "Japan"
}

결과값

Korea
Korea
Japan
Japan
China
China

 

2. 숫자 포인터

정수 포인터는 포인터 변수에 값을 넣을 때 주소를 넣어줘야 하므로 &를 붙혀야 한다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

void main(void)
{
	//정수 포인터 배열
	int oint=100;
	int* pint;

	pint = &oint; //포인터 변수에 주소 값 
	//문자배열과는 달리 포인터와 정수배열은 같지 않음

	printf("oint: %d \n", oint); //처음 넣었던 100이 나옴
	printf("pint: %d \n", *pint); // pint를 &oint로 연결 시켰으므로 100 나옴
	printf("pint: %p \n", pint); //pint의 주소값 출력


	//pint = 200;  //pint는 포인터 정수변수이므로 *를 붙혀줘야함
	*pint = 200; 
	//pint[0] = 200; //포인터변수는 배열이므로 이형태로 써도됨


	printf("oint 두번째: %d \n", oint);
	printf("pint 두번째: %d \n", *pint);
	printf("pint 두번째: %p \n", pint);
}

 

위에서는 숫자를 대입할 때 * pint를 썼는데 숫자형은 memcpy로 대입할 수도 있다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

void main(void)
{
	//정수 포인터 배열
	int oint = 100;
	int* pint;
	int oint2 = 300;

	pint = &oint; //포인터 변수에 주소 값 
	//문자배열과는 달리 포인터와 정수배열은 같지 않음. 따라서 &를 붙혀줘야함

	printf("oint: %d \n", oint); //처음 넣었던 100이 나옴
	printf("pint: %d \n", *pint); // pint를 &oint로 연결 시켰으므로 100 나옴
	printf("pint: %p \n", pint); //pint의 주소값 출력

	/* pint에 값을 대입할땐 아래와 같은 형식 사용 가능 */
	*pint = 200;
	//pint = 200; XX 이렇게 쓰면안됨  //pint는 포인터 정수변수이므로 *를 붙혀줘야함
	//*pint = oint2; 정수로 직접 써도 되고 값을 넣어도 됨
	
	//pint[0] = 200; //포인터변수는 배열이므로 이형태로 써도됨
	
	//memcpy로 써도 됨
	//memcpy(&oint, &oint2, sizeof(int)); //정수 변수는 값이 주소에서 꺼내온 것이므로 &를 붙혀줘야함 반면 문자 변수는 &를 안붙혀줘도됨

	/****************************************************/

	printf("oint 두번째: %d \n", oint);
	printf("pint 두번째: %d \n", *pint);
	printf("pint 두번째: %p \n", pint);
	printf("sizeof(int): %d \n", sizeof(int));
}

결과값

oint: 100
pint: 100
pint: 000000111C70F4E4
oint 두번째: 200
pint 두번째: 200
pint 두번째: 000000111C70F4E4
sizeof(int): 4

 

자바스크립트에서는 console.log()라는 명령어로 콘솔을 찍고

자바에서는 System.out.println()으로 찍는다.

 

하지만 C언어는 조금다르다.

 

콘솔을 찍으려는 문자 혹은 숫자의 형태를 앞에다 써줘야한다.

 

예를 들면 

 

틀린예

#include <stdio.h>

int main()
{
	int num1 = 10;
	int num2 = 20;
	int num3 = 30;

	printf(num1); //틀린예이다. 아무것도 출력되지 않는다.
	

	return 0;
}

여기서 printf에 num1을 넣어봐도 10이 출력되지 않는다.

 

맞는 예를보면

 

맞는예

#include <stdio.h>

int main()
{
	int num1 = 10;
	int num2 = 20;
	int num3 = 30;

	printf("%d %d %d \n", num1, num2, num3);


	return 0;
}

이렇게 %d처럼 변수의 형태를 써줘야 출력이 된다.

 

%d는 %i를 써도 된다. 또한 역슬래쉬n은 줄바꾸는 표시이므로 생략해도 된다.

 

 

+ Recent posts