replace

Replace (little tool intended for UNIX)

    A. First Edition

    This is a little tool I want to use on UNIX. As you know, we have "grep" to find string among files, but we

    cannot replace string in files. (At least I don't know it.) So, I write this little tool for possible usage

    in near future.

    B.The problem

To find and replace the very first occurrence for a target string in a file. I only allow the first replacement.

กก

C.The idea of program
กก

    You need to find the string and you need to create another "reading" file pointer to copy everything you read back to file.

    D.The major functions

    There are few points to mention.

    The UNIX is a pain! Make sure you have the correct representation of punctuations! i.e.

    ./replace testfile \"sources_tring\"  \"target.with_quotes\"

    See the quotes must be used like this and I removed the restriction of "non-alpha-numeric". So, any string can

    be replaced now. Another dirty part of UNIX is the "new line" character. I highly suspect that it is the reason

    for me to debug for more than two hours!!! So, I simply add an extra condition for that.

    E.Further improvement

    กก

    F.File listing

    1. main.cpp (main)

    file name: main.cpp

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

    const int BackOffSet=20;
    const int MaxStringLength=BackOffSet+BackOffSet;

    bool getWord(FILE* stream, char* buffer, const char* delimeter);

    /*
    int main(int argc, char *argv[ ])
    {
    */
    //the input string must be trimmed which means the white space
    //at both side would be ignored. i.e. " string " will be not matched
    //with "string" unless it is input with "string".
    //int main()
    //int main(int argc, char *argv[ ])
    int main(int argc, char *argv[ ])
    {
    	//int argc=4;
    	//char *argv[ ]={"replace", "nick.txt", "that", "whywhywhywhy"};
    	FILE* stream;
    	FILE* reader;
    	int front, rear;
    	char ch;
    	char buffer[MaxStringLength];
    	char line[MaxStringLength];
    	int len;
    	long pos;
    	if (argc!=4)
    	{
    		printf("usage: replace filename source target\n");
    		exit(1);
    	}
    	if ((stream=fopen(argv[1], "r+w"))==NULL)
    	{
    		printf("cannot open file %s\n", argv[1]);
    		exit(2);
    	}
    	len=strlen(argv[2]);
    	while (!feof(stream))
    	{
    		//fscanf(stream,
    		//fgets(buffer, MaxStringLength, stream);
    		getWord(stream, buffer, " \t\0\n");
    		if (strcmp(buffer, argv[2])==0)
    		{
    			pos=ftell(stream);
    			fseek(stream, -BackOffSet, SEEK_CUR);
    			fgets(line, MaxStringLength, stream);
    			printf("replace string '%s' in '%s'\n(y/n) > ", argv[2], line);
    			scanf("%c", &ch);
    			if (ch=='y')
    			{
    				fseek(stream, pos-len-1, SEEK_SET);
    				reader=fopen(argv[1], "r");
    				fseek(reader, pos-1, SEEK_SET);
    				strcpy(buffer, argv[3]);
    				rear=strlen(buffer)-1;
    				front=0;
    				while (front!=rear)
    				{
    					if (!feof(reader))
    					{
    						rear=(rear+1)%MaxStringLength;
    						buffer[rear]=getc(reader);
    					}
    					putc(buffer[front], stream);
    					front=(front+1)%MaxStringLength;
    				}
    				fclose(stream);
    				break;
    			}
    		}
    	}
    	return 0;
    }
    bool isDelimeter(char ch, const char* delimeter)
    {
    	char* ptr=(char*)delimeter;
    	/*
    	if (!isalnum(ch))
    	{
    		return true;
    	}
    	*/
    	if (ch==10||ch==13)
    	{
    		return true;
    	}
    	while (*ptr!='\0')
    	{
    		if (ch==*ptr)
    		{
    			return true;
    		}
    		ptr++;
    	}
    	return false;

    }

    bool getWord(FILE* stream, char* buffer, const char* delimeter)
    {
    	bool isDelimeter(char ch, const char* delimeter);
    	char ch;
    	bool begin=false, result=false;
    	int counter=0;
    	while (!feof(stream))
    	{
    		ch=getc(stream);
    		if (!begin)
    		{
    			//skip white space
    			if (isDelimeter(ch, delimeter))
    			{
    				continue;
    			}
    			else
    			{
    				begin=true;
    			}
    		}

    		if (begin)
    		{
    			if (isDelimeter(ch, delimeter))
    			{
    				buffer[counter]='\0';
    				if (counter!=0)
    				{
    					result= true;
    				}
    				break;
    			}
    			buffer[counter++]=ch;
    		}
    	}
    	if (counter!=0)
    	{
    		result= true;
    	}
    	return result;
    }

    The result is like following:

    D:\PROGRA~1\MICROS~2\MYPROJ~1\replace\Debug>replace nick.txt from replaceform
    replace string 'from' in 'ion reads data from gavenewstring stand'
    (y/n) > y

    D:\PROGRA~1\MICROS~2\MYPROJ~1\replace\Debug>