PA1

ewillwin·2022년 6월 2일
0

System Programming Lab

목록 보기
13/15

word search ver.2.0

1) Ask filename want to search.
2) Ask what function wan to use.
3) If you select 1 or 2, ask what word want to find.
4) If you select 3, ask words want to find and to replace.
5) If you select 4, quit the program.

Constraints: You can't use stdio.h and stdlib.h headers.

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

void itoa(int fd, int line, int col)
{
	char buf1[6]; //line is lower than 99999?
	char buf2[6]; //line is lower than 99999?
	buf1[5] = ' ';
	buf2[5] = '\n';
	int target1 = line;
	int length1 = 5;
	int target2 = col;
	int length2 = 5;

	//char inst1[] = "line : ";
	char inst1[7];
	inst1[0] = 'l';
	inst1[1] = 'i';
	inst1[2] = 'n';
	inst1[3] = 'e';
	inst1[4] = ' ';
	inst1[5] = ':';
	inst1[6] = ' ';
	//char inst2[] = "col : ";
	char inst2[6];
	inst2[0] = 'c';
        inst2[1] = 'o';
        inst2[2] = 'l';
        inst2[3] = ' ';
        inst2[4] = ':';
        inst2[5] = ' ';

	while(target1){
		char tmp = (target1 % 10) + '0';
		buf1[--length1] = tmp;
		target1 /= 10;
	}
	while(target2){
		char tmp = (target2 % 10) + '0';
		buf2[--length2] = tmp;
		target2 /= 10;
	}

	write(fd, inst1, sizeof(inst1));
	write(fd, buf1 + length1, 6 - length1);
	write(fd, inst2, sizeof(inst2));
	write(fd, buf2 + length2, 6 - length2);
}

-> headers 선언 및 itoa 함수 구현/ column index 출력 기능 추가 (기존에는 line만 출력).
-> .txt file을 열 때, 인코딩에 문제가 있었는데 일단 instruction array에 char를 하나씩 담는 방식으로 해결함

void find(int fd1, int fd2)
{
	char buf;
	int nbytes;
	char target[21];

	char inst[] = "Input target word : ";
        if((nbytes = write(1, inst, sizeof(inst))) < 0){
                perror("write");
                exit(1);
        }
	int len = 0;
	while(nbytes = read(0, &buf, 1)){
		if(nbytes <= 0) break;
		if(buf == '\n') break;
		else{
			target[len] = buf;
			len++;
		}
	} //get target word

	int line = 1;
	int col = 1;
	int idx = 0;
	while(read(fd1, &buf, 1) > 0){
		if(buf == '\n'){
			line++;
			col = 0;
		}
		else
			col++;
		if(buf == target[idx]){
			idx++;
			if(idx == len){
				lseek(fd1, -idx+1, SEEK_CUR);
				col = col - idx + 1;
				itoa(fd2, line, col);
				idx = 0;
			}
		}
		else{
			lseek(fd1, -idx, SEEK_CUR);
			col = col - idx;
			idx = 0;
		}
	}
}

-> find 함수 구현/ line이랑 column indexing만 잘 신경 써주면 됨

void findwo(int fd1, int fd2)
{
 	char buf;
	int nbytes;
        char target[21];

        char inst[] = "Input target word : ";
        if((nbytes = write(1, inst, sizeof(inst))) < 0){
                perror("write");
                exit(1);
        }
        int len = 0;
        while(nbytes = read(0, &buf, 1)){
                if(nbytes <= 0) break;
                if(buf == '\n') break;
                else{
			if (buf >= 65 && buf <= 90){
				target[len] = buf + 32;
				len++;
			} //target word is changed lower case !!
			else{
                        	target[len] = buf;
                        	len++;
			}
                }
        } //get target word

        int line = 1;
        int col = 1;
        int idx = 0;
        while(read(fd1, &buf, 1) > 0){
                if(buf == '\n'){
                        line++;
                        col = 0;
                }
                else
                        col++;

                if(target[idx] == buf || target[idx] == (buf + 32)){
                        idx++;
                        if(idx == len){
                                lseek(fd1, -idx+1, SEEK_CUR);
                                col = col - idx + 1;
                                itoa(fd2, line, col);
                                idx = 0;
                        }
                }
                else{
                        lseek(fd1, -idx, SEEK_CUR);
                        col = col - idx;
                        idx = 0;
                }
        }
}

-> find function (without case sensitive) 구현/ 이것도 그냥 find 함수에서 대소문자 +,- 32만 잘 해주면 됨. 입력받은 target word를 small letter로 일단 바꿔씀

void replace(int fd1, int fd2)
{
	char buf;
	int nbytes;
        char target[21];
	char replace[21];

        char inst1[] = "Input target word : ";
        if((nbytes = write(1, inst1, sizeof(inst1))) < 0){
                perror("write");
                exit(1);
        }
        int len1 = 0;
        while(nbytes = read(0, &buf, 1)){
                if(nbytes <= 0) break;
                if(buf == '\n') break;
                else{
                        target[len1] = buf;
                        len1++;
                }
        } //get target word

	char inst2[] = "Input replace word : ";
	if((nbytes = write(1, inst2, sizeof(inst2))) < 0){
		perror("write");
		exit(1);
	}
	int len2 = 0;
	while(nbytes = read(0, &buf, 1)){
		if(nbytes <= 0) break;
		if(buf == '\n') break;
		else{
			replace[len2] = buf;
			len2++;
		}
	} //get replace word

        int idx = 0;
        while(read(fd1, &buf, 1) > 0){
		write(fd2, &buf, 1);

                if(buf == target[idx]){
                        idx++;
                        if(idx == len1){
                                 lseek(fd2, -idx, SEEK_CUR);
                               	idx = 0;

				write(fd2, replace, len2);

				if(len1 >= len2){
					lseek(fd2, -(len1 - len2) + 1, SEEK_CUR); 
				}
				else{
					lseek(fd2, -(len2 - len1) + 1, SEEK_CUR);
				}
                        }
                }
                else{
			lseek(fd1, -idx, SEEK_CUR); 
			lseek(fd2, -idx, SEEK_CUR);
			idx = 0;
		}
	} //copy & find & replace
}

-> replace function 구현/ fd1를 일단 fd2에 다 복사하고 target word 찾아서 replace하려 했는데 잘 안되는 것 같아서 -> 그냥 fd1에서 한글자씩 while문 돌면서 fd2에 복사하고, target word랑 일치할 때 replace하고.. 이런식으로 구현함 (+ terminal에서 diff 로 정답이랑 결과값이랑 비교하는데 또 인코딩 이슈땜에 골치아팠는데 그냥 이건 내 VM virtual box가 이상한 것 같다)

//open, write, read, lseek
int main()
{
	int fd1, fd2;
	int retval1, retval2;
	char buf;
	int nbytes;
	char filename[21]; //file name
	char option[2]; //ask what function?

	char inst1[] = "File name : ";
	if((nbytes = write(1, inst1, sizeof(inst1))) < 0){
		perror("write");
		exit(1);
	}
	int len = 0;
	while(nbytes = read(0, &buf, 1)){
		if(nbytes <= 0) break;
		if(buf == '\n') break;
		else{
			filename[len] = buf;
			len++;
		}
	} //get file name

	char inst2[] = "(1) Find (2) Find w/o case sensitive (3) Replace (4) Exit : ";
	if((nbytes = write(1, inst2, sizeof(inst2))) < 0){
		perror("write");
		exit(1);
	}
	len = 0;
	while(nbytes = read(0, &buf, 1)){
		if(nbytes <= 0) break;
		if(buf == '\n') break;
		else{
			option[len] = buf;
			len++;
		}
	} //get option

	if((fd1 = open(filename, O_RDONLY)) < 0){
                perror("open");
                exit(1);
        }
        if((fd2 = open("result.txt", O_CREAT|O_WRONLY|O_TRUNC, 0666)) < 0){
                perror("open");
                exit(1);
        } //files open

	if(option[0] == '1') find(fd1, fd2);
	else if(option[0] == '2') findwo(fd1, fd2);
	else if(option[0] == '3') replace(fd1, fd2);
	else exit(0);

	if((retval1 = close(fd1)) < 0){
		perror("close");
		exit(1);
	}
	if((retval2 = close(fd2)) < 0){
		perror("close");
		exit(1);
	} //files close
}

-> main 함수 구성/ 그냥 file descriptor 두개 열고 option 입력받고 그에 맞는 함수 실행 후 close

profile
💼 Software Engineer @ LG Electronics | 🎓 SungKyunKwan Univ. CSE

0개의 댓글