IT 프로그래밍/자료구조

[C언어] 주소록 프로그램 strtok에 대한 설명

기술1 2024. 9. 6. 21:43
반응형

C를 통한 주소록 프로그램

#include <iostream>
#include <string>
using namespace std;
#define MAX_PERSON 1000
#define MAX_LEN 300

struct person {
	char* name, * address;
	char* phone, * email, * web;
};
typedef struct person Person;

Person directory[MAX_PERSON];
int n = 0;

구조체 Person의 배열을 사용합니다. n은 저장된 사람수이며 최대 1000명을 저장할 수 있습니다. 

 

typedef 을 이용해서 struct person를 Person이라고 부르겠다라는 뜻입니다. 파이썬의 Numpy as np와 비슷한 기능이라고 생각하시면 됩니다. 

 

Person에 directory[MAX_PERSON]을 통해 배열을 만든 것입니다. 구조체 안에 배열을 만든 것입니다. 

 

데이터 파일 읽기

#include <iostream>
#include <string>
using namespace std;
#define MAX_PERSON 1000
#define MAX_LEN 300

struct person {
	char* name, * address;
	char* phone, * email, * web;
};
typedef struct person Person;

Person directory[MAX_PERSON];
int n = 0;

void load_data(char* file_name) {
	char line[MAX_LEN];

	FILE* fp = fopen(file_name, "r");

	while (fgets(line, MAX_LEN, fp) != NULL) {
		printf("%s\n", line);
	}
	fclose(fp);
}

int main() {
	load_data("address.tsv");
	return 0;
}

먼저 읽을 파일을 오픈합니다. "r"은 읽기 목적으로 파일을 오픈한다는 것을 의미하며 쓰기 목적일 경우 "w"로 사용해주시면 됩니다. fgets 함수로 한 번에 한 라인씩 읽습니다. 

 

그리고 읽은 라인을 그대로 출력해주도록 printf("%s\n", line);을 썼습니다. 

 

 테스트를 위해서 printf를 해본 것입니다. NULL 값이 나올 때까지 즉 마지막 줄이 나올 때까지 진행되도록 while문을 사용하였습니다. 이후 fclose를 통해 닫아주는 방식입니다. 

 

이제 라인으로 입력된 나열되어 있는 이름, 주소, 번호, 이메일, 웹사이트를 자르는 작업을 해야합니다. 해당 문서는 \t 즉 탭으로 나뉘어져 있다고 가정할 때 문자열 자르기를 알아보도록 하겠습니다.

 

문자열 자르기 (tokenizing)

구분 문자(delimiter)를 이용하여 하나의 긴 문자열을 작은 문자열들로 자르는 작업을 문자열  tokenizing이라고 합니다. 잘라진 작은 문자열들을 주로 token이라고 부릅니다.

 

C언어에서는 주고 strtok 함수를 이용합니다. 

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

int main() {
	char str[] = "now # is the time # to start preparing ### for the exam #";
	char delim[] = "#";
	char* token;

	token = strtok(str, delim);

	while (token != NULL) {
		printf("next token is : %s:%d\n", token, strlen(token));
		token = strtok(NULL, delim);
	}
	return 0;
}

여기선 delimiter가 하나의 문자(char)이 아닌 C string 즉 여러개가 나올 것임을 대비해서 char delim[] = "#"로 배열로 만들어주었습니다. 

 

token = strtok(str, delim); 이라고 하면 첫번째 호출을 해줍니다. strtok은 더 이상 잘라낼 token이 남아있지 않으면 NULL을 ``입력을 해줍니다. 그래서 NULL이 나오기 전까지 next token을 계속 출력을 해주는 것입니다. 

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

int main() {
	char str[] = "study hard, or sleep. ";
	char delim[] = " ";
	char* token;

	token = strtok(str, delim);

	while (token != NULL) {
		printf("next token is : %s:%d\n", token, strlen(token));
		token = strtok(NULL, delim);
	}
	return 0;
}

이번에는 공백으로 delimiter를 지정해줬을 때의 코드입니다. strtok에서는 2개 이상의 delimiter가 연속되어 존재하고 있을 때는 하나의 delimiter로 구분을 하고 처리를 합니다. 

 

strtok은 정확하게 이해하지 않으면 실수를 할 가능성이 높은 함수입니다.

 

strtok은 원본 문자열을 변화시킵니다('\0'를 삽입합니다.) 따라서 만약 원본 문자열이 보존되어야 한다면 복제한 후에 strtok를 해야합니다. 즉 이말은 문자 배열이어야 하지 포인터에 대한 수정은 불가능하다는 것을 의미하기도 합니다.

 

또한 strtok은 새로운 배열을 생성하지 않습니다. 즉 동적 메모리할당을 하지 않습니다.

반응형