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