473,657 Members | 2,294 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

remove entry from text file [NOT A HOMEWORK]

Hello, All!

I implemented simple program to eliminate entry from the file having the
following structure (actually it's config file of 'named' DNS package for
those who care and know):

options {
directory "/var/named";
listen-on { 192.168.11.22; 127.0.0.1; };
forwarders { 168.126.63.1; };
pid-file "/var/run/named.pid";
};

controls {
unix "/var/run/ndc" perm 0600 owner 0 group 0;
};

zone "." {
type hint;
file "root.cache ";
};

zone "localhost" {
type master;
file "localhost" ;
};

zone "my.local" {
type master;
file "my.local";
allow-update { 127.0.0.1; 192.168.11.0/24; };
};
....

I bother only about "zone" entries and the goal of code to remove them only.
Here is the source code I'm done with. I'd like to hear reasonable criticism
and useful advices :-) on optimization, bugs etc.

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

#define BUFSIZE 100

int main(int argc, char **argv)
{
FILE *f; /* original */
FILE *fn; /* new */
char buf[BUFSIZE] = { 0 };
register char *idx;
char sidx[BUFSIZE];
int found = 0; /* set if zone found */
int i = 0;

if (argc != 3) {
fprintf(stderr, "Usage: %s <zonename> <configfile>\n" , *argv);
return (0);
}

printf("%s %s\n", argv[1], argv[2]);

/* open original */
if ( (f = fopen(argv[2], "r")) == NULL )
return -1;

if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )
return -1;

while ( !feof(f) ) {
fgets(buf, BUFSIZE, f);

/* skip leading spaces */
for (idx = buf; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* look for 'zone' token */
if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {
if (!found) {
fprintf(fn, buf);
fflush(fn);
}
continue;
}

idx += sizeof("zone ") - 1;

/* skip spaces inside of token */
for (; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* extract token from commas */
if (*idx++ != '"')
continue;

/* put token into buffer to compare */
while (*idx != '\0' && *idx != '"')
sidx[i++] = *idx++;

sidx[i] = '\0'; i = 0;
if (strcasecmp(sid x, argv[1]) != 0) {
found = 0;
fprintf(fn, buf);
fflush(fn);
}
else
found = 1;
}

fclose(f);
fclose(fn);

return 0;
}

Thank you in advance.

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 23 '06 #1
36 2591

Roman Mashak wrote:
Hello, All!

I implemented simple program to eliminate entry from the file having the
following structure (actually it's config file of 'named' DNS package for
those who care and know):

options {
directory "/var/named";
listen-on { 192.168.11.22; 127.0.0.1; };
forwarders { 168.126.63.1; };
pid-file "/var/run/named.pid";
};

controls {
unix "/var/run/ndc" perm 0600 owner 0 group 0;
};

zone "." {
type hint;
file "root.cache ";
};

zone "localhost" {
type master;
file "localhost" ;
};

zone "my.local" {
type master;
file "my.local";
allow-update { 127.0.0.1; 192.168.11.0/24; };
};
...

I bother only about "zone" entries and the goal of code to remove them only.
Here is the source code I'm done with. I'd like to hear reasonable criticism
and useful advices :-) on optimization, bugs etc.

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

#define BUFSIZE 100

int main(int argc, char **argv)
{
FILE *f; /* original */
FILE *fn; /* new */
char buf[BUFSIZE] = { 0 };
register char *idx;
char sidx[BUFSIZE];
int found = 0; /* set if zone found */
int i = 0;

if (argc != 3) {
fprintf(stderr, "Usage: %s <zonename> <configfile>\n" , *argv);
return (0);
}

printf("%s %s\n", argv[1], argv[2]);

/* open original */
if ( (f = fopen(argv[2], "r")) == NULL )
return -1;

if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )
return -1;

while ( !feof(f) ) {
fgets(buf, BUFSIZE, f);

/* skip leading spaces */
for (idx = buf; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* look for 'zone' token */
if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {
if (!found) {
fprintf(fn, buf);
fflush(fn);
}
continue;
}

idx += sizeof("zone ") - 1;

/* skip spaces inside of token */
for (; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* extract token from commas */
if (*idx++ != '"')
continue;

/* put token into buffer to compare */
while (*idx != '\0' && *idx != '"')
sidx[i++] = *idx++;

sidx[i] = '\0'; i = 0;
if (strcasecmp(sid x, argv[1]) != 0) {
found = 0;
fprintf(fn, buf);
fflush(fn);
}
else
found = 1;
}

fclose(f);
fclose(fn);

return 0;
}

Thank you in advance.

With best regards, Roman Mashak. E-mail: mr*@tusur.ru


Look for references about "lex" C source generator (or even "yacc" if
you have more complex requirements like this one)

Feb 23 '06 #2
Roman Mashak wrote:
Hello, All!

I implemented simple program to eliminate entry from the file having the
following structure (actually it's config file of 'named' DNS package for
those who care and know):
<snip>
if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )
return -1;


Here, because of opening the file for writing in present directory, it
will restrict the directory from which a user can run your program. If a
user does n't have write permission for the present directory, then he
will have to change the directory and run your program.

Probably you should have explained algorithm used in your program in
short paragraph.
Feb 23 '06 #3
boa
Roman Mashak wrote:
Hello, All!

I implemented simple program to eliminate entry from the file having the
following structure (actually it's config file of 'named' DNS package for
those who care and know):

options {
directory "/var/named";
listen-on { 192.168.11.22; 127.0.0.1; };
forwarders { 168.126.63.1; };
pid-file "/var/run/named.pid";
};

controls {
unix "/var/run/ndc" perm 0600 owner 0 group 0;
};

zone "." {
type hint;
file "root.cache ";
};

zone "localhost" {
type master;
file "localhost" ;
};

zone "my.local" {
type master;
file "my.local";
allow-update { 127.0.0.1; 192.168.11.0/24; };
};
...

I bother only about "zone" entries and the goal of code to remove them only.
Here is the source code I'm done with. I'd like to hear reasonable criticism
and useful advices :-) on optimization, bugs etc.

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

#define BUFSIZE 100

int main(int argc, char **argv)
{
FILE *f; /* original */
FILE *fn; /* new */
char buf[BUFSIZE] = { 0 };
register char *idx;
char sidx[BUFSIZE];
int found = 0; /* set if zone found */
int i = 0;

if (argc != 3) {
fprintf(stderr, "Usage: %s <zonename> <configfile>\n" , *argv);
return (0);
Maybe return EXIT_FAILURE to indicate an error?
}

printf("%s %s\n", argv[1], argv[2]);

/* open original */
if ( (f = fopen(argv[2], "r")) == NULL )
return -1;
Again, EXIT_FAILURE.

if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )
How about using tmpnam() instead?
return -1;

while ( !feof(f) ) {
fgets(buf, BUFSIZE, f);
See http://c-faq.com/stdio/feof.html

/* skip leading spaces */
for (idx = buf; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* look for 'zone' token */
if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {
strlen("zone"), not sizeof().
if (!found) {
fprintf(fn, buf);
fflush(fn);
Why do you need to call fflush()?

}
continue;
}

idx += sizeof("zone ") - 1;

/* skip spaces inside of token */
for (; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;
How about a function that strips the white space?


/* extract token from commas */
if (*idx++ != '"')
continue;

/* put token into buffer to compare */
while (*idx != '\0' && *idx != '"')
sidx[i++] = *idx++;

sidx[i] = '\0'; i = 0;
if (strcasecmp(sid x, argv[1]) != 0) {
found = 0;
fprintf(fn, buf);
fflush(fn);
}
else
found = 1;
}

fclose(f);
fclose(fn);

return 0;
}


That's a start, HTH.

Boa
Feb 23 '06 #4
"Roman Mashak" <mr*@tusur.ru > writes:
Hello, All!

I implemented simple program to eliminate entry from the file having the
following structure (actually it's config file of 'named' DNS package for
those who care and know):
<snip>
zone "." {
type hint;
file "root.cache ";
};

zone "localhost" {
type master;
file "localhost" ;
};

zone "my.local" {
type master;
file "my.local";
allow-update { 127.0.0.1; 192.168.11.0/24; };
};
<snip> (here's the code:)
#include <stdio.h>
#include <string.h>
#include <strings.h>
The last of these is not Standard C; see my discussion later.

#define BUFSIZE 100

int main(int argc, char **argv)
{
FILE *f; /* original */
FILE *fn; /* new */
char buf[BUFSIZE] = { 0 };
register char *idx;
char sidx[BUFSIZE];
int found = 0; /* set if zone found */
int i = 0;

if (argc != 3) {
fprintf(stderr, "Usage: %s <zonename> <configfile>\n" , *argv);
return (0);
}

printf("%s %s\n", argv[1], argv[2]);

/* open original */
if ( (f = fopen(argv[2], "r")) == NULL )
return -1;
A return of -1 will have an implementation-defined meaning... slightly
better would be to #include <stdlib.h> and return EXIT_FAILURE; which
is guaranteed to have the obvious meaning on any current or future
implementation.

Also, it would really pay to emit some sort of message here. You'll
really thank yourself when you accidentally open a non-existant file,
or non-readable.... etc.
if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )
return -1;

while ( !feof(f) ) {
fgets(buf, BUFSIZE, f);

/* skip leading spaces */
for (idx = buf; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;

/* look for 'zone' token */
if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {
Whenever I find myself having to use the exact same string literal
twice like this, it's time to farm it out. Using something like:

const char zone_token[] = "zone ";
...
if (strncasecmp(id x, zone_token, (sizeof zone_token)-1) != 0)

saves you from the problem of accidental typos. If the number of
characters between the two of those were to accidentally get out of
sync, it'd be a bug. And even though you have them exactly right now,
you might later need to change the code to use a different literal,
and accidentally change only one.

BTW, strncasecmp() is not a Standard C function (it's POSIX, which is
not on-topic here). The residents on this newsgroup insist that you do
not post code containing functions that are (a) not Standard C
functions and (b) not defined in the provided code. For the sake of
example code on this newsgroup, the easiest way for you to avoid
difficulties is probably to use strncmp() instead. Or, define your own
implementation of strncasecmp().. .
if (!found) {
fprintf(fn, buf);
fflush(fn);
}
continue;
}

idx += sizeof("zone ") - 1;
If you decide to follow my advice, this would become:

idx += (sizeof zone_array) - 1;

Actually, my own preference has been to define a macro such as:

#define ARY_STRLEN(a) (sizeof(a)-1)

which leads to a slightly better expression, in terms of
self-documentation:

idx += ARY_STRLEN(zone _array) - 1;
/* skip spaces inside of token */
for (; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;
This is the same thing as:

idx += strspn(idx, " \t");

/* extract token from commas */
if (*idx++ != '"')
continue;

/* put token into buffer to compare */
while (*idx != '\0' && *idx != '"')
sidx[i++] = *idx++;

sidx[i] = '\0'; i = 0;
The second statement on the line above is easy to miss. I'd recommend
giving each of these a separate line.
if (strcasecmp(sid x, argv[1]) != 0) {
found = 0;
fprintf(fn, buf);
fflush(fn);
}
else
found = 1;
}

fclose(f);
fclose(fn);

return 0;
}


The last pair of fclose()s are not strictly necessary, if you're not
going to check their return value. However, I'd recommend that you do
check their return value, so you can emit an error message if fn
didn't flush properly... actually, you should check the return code of
your fflush() calls, too.

I'll point out that the code above won't work properly if your config
file contains lines longer than 100 characters.

-Micah
Feb 23 '06 #5
boa <bo*****@gmail. com> writes:
Roman Mashak wrote:
/* skip leading spaces */
for (idx = buf; *idx != '\0' && (*idx == ' ' || *idx == '\t'); idx++)
;
/* look for 'zone' token */
if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {


strlen("zone"), not sizeof().


You mean, strlen("zone ") (with the space); and there's nothing wrong
with sizeof: it's much more efficient.
if (!found) {
fprintf(fn, buf);
fflush(fn);


Why do you need to call fflush()?


Could be useful if he's using another program to view the temporary
file while it's being written (UNIX tail...).

Slightly better might be to set line buffering on fn with setvbuf().

-Micah
Feb 23 '06 #6
Micah Cowan wrote:
boa <bo*****@gmail. com> writes:
Roman Mashak wrote:
> /* look for 'zone' token */
> if ( strncasecmp(idx , "zone ", sizeof("zone ") - 1) != 0 ) {


strlen("zone"), not sizeof().


You mean, strlen("zone ") (with the space); and there's nothing wrong
with sizeof: it's much more efficient.


Hmmmm ???

What's the type of a literal string in code?
I thought it was `const char *'

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

int main(void) {
int a, b, c, d, e, f;
char * z1 = "forty two";
char z2[] = "forty two";

a = strlen("forty two");
b = (int)sizeof("fo rty two");
c = (int)sizeof(cha r*);
d = (int)sizeof(con st char*);
e = (int)sizeof z1;
f = (int)sizeof z2; /* Ah! A match */
printf("%d, %d, %d, %d, %d, %d\n",
a, b, c, d, e, f);
return 0;
}
No Micah, I wasn't doubting you (... well, maybe just a little)
I stand corrected.

--
If you're posting through Google read <http://cfaj.freeshell. org/google>
Feb 24 '06 #7
Pedro Graca wrote:
What's the type of a literal string in code?


An array of some number of char.
No implict const qualifier,
just trouble if you attempt to modify the object.

--
pete
Feb 24 '06 #8
pete <pf*****@mindsp ring.com> writes:
Pedro Graca wrote:
What's the type of a literal string in code?


An array of some number of char.
No implict const qualifier,
just trouble if you attempt to modify the object.


"trouble" being undefined behavior.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 24 '06 #9
Hello, boa!
You wrote on Thu, 23 Feb 2006 20:16:14 +0100:

??>> #include <strings.h>

b> strings.h?
I should've apologized for using of non-standard stuffs :)
??>> #define BUFSIZE 100
??>>
??>> int main(int argc, char **argv)
??>> if ( (fn = fopen("named.co nf.tmp", "w+")) == NULL )

b> How about using tmpnam() instead?
Manual of my system strongly recommends never to use this function cause of
being unsafe.
??>> return -1;
??>>
??>> while ( !feof(f) ) {
??>> fgets(buf, BUFSIZE, f);

b> See http://c-faq.com/stdio/feof.html
Yeas, that was the problem I run into: printing '\n' twice, BUT it happened
only if I removed entry from the middle of file, otherwise everything came
right.
Thanks for hint.

??>> if (!found) {
??>> fprintf(fn, buf);
??>> fflush(fn);

b> Why do you need to call fflush()?
I view the result file in the next console via "tail -f" (I'm using linux
presently).
??>> }
??>> continue;
??>> }
??>>

With best regards, Roman Mashak. E-mail: mr*@tusur.ru
Feb 24 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1468
by: BW | last post by:
Please ignore the rest of the code, except for the highlighted part (or the line 'ent1=Entry(topf, width=25)' to line 'ent1.insert(INSERT, wrong, if you cannot see the color). You can copy this into Python and make sure you have the GIF file in the same dir. Also, make sure that you have PIL installed. I cannot get this to work. I get an error after running it and what I'm trying to do it to evaluate what the person enters in the box for the...
163
14605
by: Shiperton Henethe | last post by:
Hi Know any good utilities to help me strip out the tags that Microsoft Excel 2002 leaved behind when you try and export an HTML format file? This is driving me NUTS. And really makes me hate microsoft with a passion. I literally just want "compact HTML" - ie just the data,
2
2103
by: rorley | last post by:
I'm trying to open a text file, remove all instances of the words "f=x;" and "i=x;" where x can be any number 0-14. Also, I want to remove all { " or ) or ( or ' } each time one of those characters occurs respectively. This is what I've been able to piece together... import os, string x = ("f=;") y = ("i=;) inputFile = open('abcd.txt','r')
10
18059
by: =?Utf-8?B?YmJn?= | last post by:
Hi all, I wanted to go through each entry(?) of ArrayList and remove some particular entry. So I tried following but it throws exception at runtime: foreach (myEntry entry in myArrayList) { // do something... if (entry.fieldA == 0)
1
1474
by: JoshPierce | last post by:
I want to allow users of my program to click File>Save and have a save dialog open and allow them to save all of their input. here is the background of my program. I have a program that allows students to calculate their grades as the class progresses. I want them to be able to type in their information and i already have the program written for them to be able to calculate everything via different types of work based on weights for homework...
6
4248
by: falconsx23 | last post by:
I am trying to write a code for a Phone Directory program. This program is suppose to allow the user to enter a name or directory and then program can either add, save or even delete an entry. Also this program has more then one class and also uses an interface. Right now I am working on ArrayBasedPD class. I am trying to write a code for the remove method (line 158) that allows the user to enter a name, once the program sees that the name is...
0
8407
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8739
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8612
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7347
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6175
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5638
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4171
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2739
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1969
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.