Click to See Complete Forum and Search --> : stdio file manipulation
RHLinuxNewbie
10-03-2003, 04:05 PM
I’m trying to learn how to use the file manipulation included with the stdio header. I’m experimenting with different functions, and I am currently trying to disable the append option when writing to files.
I saved the following as a.cpp :
#include <stdio.h>
int main() {
FILE* pFile;
char str [100];
pFile = fopen ("a.cpp" , "rb+");
if (pFile == NULL) {
//error
} else {
while(!feof(pFile)) {
fgets(str, 100, pFile);
if (str[0] == '#') {
fputs("x", pFile);
}
puts(str);
}
}
fclose (pFile);
return 0;
}
As you can see it opens itself. I'm attempting to write to the file an ‘x’ before any line that begins with an ‘#’. So the only change should be:
#include <stdio.h>
To
x#include <stdio.h>
However, the program is appending the ‘x’s to the end of the file, in what appears to be an infinite loop. Any ideas? man fopen says this is how you do it :\
Morphine Drip
10-03-2003, 05:12 PM
from what i can tell you need to .... (from msdn)
When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, or fseek operation. The current position can be specified for the fsetpos or fseek operation, if desired.
but anyhow...i would say the file pointer is off. each time you read, that file pointer gets incremented 100 bytes further into the file.....so when you write to it that file pointer is already 100 bytes past that last line read....or up the nearest newline.
maybe rewind 100 bytes before the write?
plus i would open in text mode...not binary....
since fgets doesnt tell you how many bytes it read maybe you can rewind to the size of the string read in? and i guess take into account how many bytes your newline is...1 or 2. carriage return and line feed or just a line feed. off by one errors stink =)
tecknophreak
10-03-2003, 05:22 PM
I'd say do a fgetpos before you read a new line in, then if you have a '#', use fsetpos to write at the correct position, then do that read again. If that doesn't make sense the first time you read it, try again, I think it's there, it is Friday after all.
Also, I believe, and a test or two showed me, that the only place you can ADD chars is at the end of a file. When you go back, you are only writing over the char that is previously there, i.e.
#include
becomes
xinclude
Also, just a question, how come FILE, fopen, etc and not fstream since you're using c++?
RHLinuxNewbie
10-04-2003, 04:16 PM
Thanks guys, it worked and I'm well on my was to writing a class using it as an example.
Originally posted by tecknophreak
#include
becomes
xinclude
I suspected this would happen :eek:
I'm looking for a way to add characters to the file, such that the output in this example would be
x#include
Additionally I’m looking for a method of deleting characters. For deletion, I was thinking just replace it with a NULL, I have not tried it yet though.
I'm searching around google and reading up on it all, but any help would be much appreciated. :D
Originally posted by tecknophreak
Also, just a question, how come FILE, fopen, etc and not fstream since you're using c++?
I wanted to take this opportunity to learn a bit more about stdio :)
tecknophreak
10-04-2003, 04:24 PM
Originally posted by RHLinuxNewbie
I'm looking for a way to add characters to the file, such that the output in this example would be
x#include
Additionally I’m looking for a method of deleting characters. For deletion, I was thinking just replace it with a NULL, I have not tried it yet though.
Well, you have 2 different ways of doing this. 1 take the whole file into ram, then reopen it as write-only and write the changed file. 2, create a temp file, put your output in there, copy that file to your original and delete then temp file.
Check out how unix2dos does it, it does what you are trying to do, essentially. unix2dos adds a char and dos2unix deletes a char.
RHLinuxNewbie
10-04-2003, 06:16 PM
To delete a line in the middle of a file, I tried copying the data after that line over it, leaving some garbage at the end.
Looking through stdio functions I was unable to find a way to truncate the file. I really don't want to use a second file unless I absolutely HAVE to.
I heard there was a function called ftruncate() which would do this, but is not part of stdio and can't be ported to win32 platforms. Does anyone know of a similar function?
dchidelf
10-04-2003, 08:06 PM
ftruncate is a standard C library function.
You should be able to use it with stdio FILE streams by getting the underlying file descriptor with fileno(FILE *filex).
As far as *nix compatability with this function, some platforms don't support "growing" the file, but I believe all should be able to truncate.
tecknophreak
11-06-2003, 03:58 PM
I was bored on a plane and was writing a prog like this, now this is in c++, but use similar functions in c and it'll work:
#include <iostream>
#include <fstream>
using namespace std;
fstream &insert(fstream &stream, char ch, int pos) {
int end;
char *buff;
// Get the size of the file
stream.seekg(0, ios::end);
end = stream.tellg();
// Create a buffer to fit the chars
// from the position to insert the new
// char to the end of the file
buff = new char[end - pos];
// Read from the point of insertion
// to the end of the file
stream.seekg(pos, ios::beg);
stream.read(buff, end - pos);
// Position the put pointer back to the
// point of insertion and write the new char
stream.seekp(pos);
stream.write(&ch, 1);
// Finally, put the rest of the file in
// the right spot
stream.write(buff, end - pos);
delete [] buff;
return stream;
}
int main() {
int pos;
char ch;
fstream stream("stuff", ios::in | ios::out);
while (!stream.eof()) {
stream.get(ch);
if (ch == '#') {
pos = stream.tellg();
insert(stream, ' ', pos - 1);
stream.seekg(pos + 1, ios::beg);
}
}
}
This code opens the file for read/write and only copies what it needs to. You can do copies of 1024 or something like that instead of the whole chunk like i did in the function.
jim mcnamara
11-07-2003, 04:40 PM
#include <stdio.h>
#include <stdlib.h>
#define NUMBER_OF_LINES 100
void addx(char *);
int main() {
FILE* pFile;
char str[NUMBER_OF_LINES][100];
int cnt=0,
i=0;
pFile = fopen ("a.cpp" , "rb+");
if (pFile == NULL) {
//error
} else {
while(!feof(pFile)) {
if(fgets(str[cnt++], 99, pFile)!=NULL){
if (str[0] == '#') {
addx(str[i]);
}
}
}
fseek(pFile,0,SEEK_SET);
for(i=0;i<cnt;i++)fprintf(pFile,"%s",str[i]);
}
fclose (pFile);
return 0;
}
void addx(char *src){
char tmp[256];
memset(tmp,0x00,sizeof(tmp));
strcpy(tmp,"x");
strcat(tmp,src);
strcpy(src,tmp);
}