File searching, replacing, copying...
A. First Edition
This is comp444 lab1 and it is concentrated on file operations such as searching, replacing, copying...
I want to keep this simple version for possible future modification.
From point of view of compiler project, it is a toy scanner with much simplified functionality. But it is
difficult for me to debug c in Linux. Another reason is the awkward C grammar. There is no "bool" type, there
is no function overloading, there is no ...
E.Further improvement
F.File listing
1. myhead.h
2. searchString.h
3. searchString.c
4. main.c
5. errHandle.c
6. makefile
file name: myhead.h
#ifndef MYHEAD_H #define MYHEAD_H #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <dirent.h> #include <unistd.h> #include <string.h> #include <fcntl.h> typedef int bool; #define TRUE 1 #define FALSE 0 #define BuffSize 128 void errHandle(char* msg); #endif
file name: searchString.h
#ifndef SEARCHSTRING_H #define SEARCHSTRING_H #include "myhead.h" struct FileBuf { int fd; int size; int offset; int cur; char buf[128]; //char buf[BuffSize]; }fileBuf; typedef struct FileBuf* FilePtr; int findString(char* fileName, char* str); //define three mode and it is purely like DFA=Deterministic Finite Automaton #define FindNextWord 0 #define SkipTillNext 1 #define Comparing 2 //search in a file with my own file information struct FileBuf*, //target is the string for searching //repeating call this function and return each location, //return -1 indicating end of file int searchString(FilePtr stream, char* target); //specify if it is white space char //notice here, in C, there is no boolean type and I define it //as alias of int in "myhead.h" bool isBreak(char ch); //my edition of getc FilePtr openFile(int fd); //a-z, A-Z bool isChar(char ch); //my edition of getc char nextChar(struct FileBuf* stream); #endif
file name: searchString.c
#include "myhead.h"
#include "searchString.h"
bool findString(char* fileName, char* str)
{
int fd, n=0;
FilePtr stream;
bool result=FALSE;
if ((fd=open(fileName, O_RDONLY))<0)
{
errHandle("cannot open searching files\n");
}
if ((stream=openFile(fd))==NULL)
{
errHandle("openfile error\n");
}
while ((n=searchString(stream, str))!=-1)
{
result=TRUE;
printf("test: find target at %d\n", n);
}
return result;
}
//my edition of "fopen"
FilePtr openFile(int fd)
{
fileBuf.fd=fd;
fileBuf.offset=0;
if ((fileBuf.size=read(fd, fileBuf.buf, BuffSize))<0)
{
return NULL;
}
fileBuf.cur=0;
return &fileBuf;
}
//getc
char nextChar(FilePtr stream)
{
//if buff is fully read
if (stream->cur >= stream->size)
{
if (stream->size==0)//must be end of file
{
return -1;
//return EOF;
}
//if erro happened during reading
if ((stream->size=read(stream->fd, stream->buf, BuffSize))<0)
{
errHandle("read error of file buf\n");
}
//reset cur
stream->cur=0;
}
//offset is always inc for each call
stream->offset++;
return stream->buf[stream->cur++];
}
//what is white space
bool isBreak(char ch)
{
return (ch==' '||ch=='\t'||ch=='\n');
}
bool isChar(char ch)
{
return ((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'));
}
//starting a particular file offset and search the target string
//if found return the file offset of target, else return -1
int searchString(FilePtr stream, char* target)
{
int stringLength=strlen(target);
char ch;
int result=-1;//this is the starting offset of word
//the length of word compared
int length;
int mode;
length=0;
mode=FindNextWord;//initial status
//-1 means EOF
while ((ch=nextChar(stream))!=-1)
{
switch (mode)
{
case FindNextWord:
if (isChar(ch))
{
//check the very first
if (ch==target[0])
{
mode=Comparing;
length=1;//need to compare with next
result=stream->offset-1;//as it already passed it
}
else
{
mode=SkipTillNext;
}
}
//else keep going
break;
case SkipTillNext:
if (isBreak(ch))
{
mode=FindNextWord;
}
break;
case Comparing:
//it is a match
if (ch==target[length])
{
//a match then keep going
length++;
//a white space
if (length==stringLength)
{
return result;
}
}
else
{
//it means mis-match
mode=SkipTillNext;
}
break;
}//switch
}//while
return -1;
}
file name: errHandle.c
#include "myhead.h" void errHandle(char* msg) { if (msg!=NULL) { perror(msg); } else { strerror(errno); } exit(errno); }
file name: makefile
all: searchString.o main.o errHandle.o @echo "make complete for searchString.o " errHandle.o : errHandle.c myhead.h @echo "compiling errHanle module\n" gcc -g -c errHandle.c -o errHandle.o main.o : searchString.o main.c errHandle.o gcc -g main.c searchString.o errHandle.o -o main.o @echo "compiling main.o ..." searchString.o : searchString.h searchString.c myhead.h gcc -g -c searchString.c -o searchString.o @echo "compiling searchString.o as searchString.c is modified..."
How to run?
1. You need the file name as argument in command line
[qingz_hu@alamanni ~/lab1] % ./main.o test.txt test: find target at 0 test: find target at 39 test: find target at 92 test: find target at 127 test: find target at 334 ok