What's a good way to remove a line from a file (database.txt :P)? I remember in VB I used to read the file, store the information in an array, then simply rewrite the file. I don't know how to do that in C, because there's no way for me to know how large to make the array. Ideas?
You could read it line-by-line until you reached EOF. Then restart from the top and read it line-by-line into an array. Or you could use a std::vector (a dynamic array). Or you could make one big-ass array of pointers and hope for the best (although this solution is nonoptimal).
How am I suppost to make an char array without a... uh... hardcoded size?
void *malloc(size_t length)
Reading it line by line into an array is the method I use. However it may be better to use a linked list rather than an array.
Quote from: NicoQwertyu on October 03, 2005, 01:16 PM
How am I suppost to make an char array without a... uh... hardcoded size?
Did you even read my post? "Or you could use a
std::vector (a dynamic array)."
Here's a website (http://www.codeguru.com/Cpp/Cpp/cpp_mfc/arrays/article.php/c4071/) I found using Google (http://www.google.com) searching for std::vector class (http://www.google.com/search?hl=en&q=std%3A%3Avector+class).
Or you could do what Shout suggested:
char *lines[] = (char**)malloc(max_string_size_per_line * number_of_lines);
It depends if you're using C or C++. If you're using C, malloc is the right way to go; there's no new operator and no std::vector class. If you're using C++, use the STL method (std::vector).
**OR** you could create your own dynamic array with a set of structures in a linked list.
struct db_line // node type
{
db_line *next;
int lineLength;
char *line;
}
struct db_list
{
int number_of_lines;
db_line *first;
}
db_list createNewList()
{
db_list db;
db.number_of_lines = 0;
db.first = NULL;
return db;
}
// adds a new line to the end of the list.
void addToList(db_list *list, db_line *line)
{
if (list == NULL) return;
if (list->first == NULL)
{
list->first = line;
}
else
{
db_line *cursor = list->first;
while (cursor->next != NULL) cursor = cursor->next;
cursor->next = line;
}
list->number_of_lines++;
}
// removes the first occurance of db_line from the list
void removeFromList(db_list *list, db_line *line)
{
if (list == NULL) return;
if (list->first == NULL) return;
db_line *cursor = list->first;
if (cursor == line)
{
// the head is the first instance, remove it.
list->first = cursor->next;
// do some action to clean up the memory from the first item. This structure is pointed
// to still by cursor. If you do not, it will result in a memory leak of at least 8 bytes.
}
else
{
// track it down.
do
{
if (cursor->next == line)
{
db_line *to_delete = cursor->next;
cursor->next = cursor->next->next;
// again, do something to clean up this memory to avoid a memory leak.
// this time, the line to clean up is in to_delete.
break;
}
} while (cursor->next != NULL);
}
}
You're on your own for the rest.
Yes, I read your post. I ignored the comment about std::vector because I'm using C (not C++), which I clearly stated in my post; guess you missed it. Thanks for your help, thusfar though, I do appreciate it. I'll go with malloc(). Thanks, guys.
Malloc is working beautifully. Thanks for all your help. :)
Why store it in an array or vector if you are just rewriting it with one line removed? Read and write in parallell!
How do you mean? :o
// Remove line 72 from a file
// Max line length 255 chars
FILE *in = fopen("infile", "rt"), *out = fopen("outfile", "wt");
char line[256];
int lineno = 0;
while(fgets(line, 256, in))
if(++lineno != 72)
fputs(line, out);
If you are using malloc(), remember to use free()!
Quote from: Adron on October 04, 2005, 09:29 AM
// Remove line 72 from a file
// Max line length 255 chars
FILE *in = fopen("infile", "rt"), *out = fopen("outfile", "wt");
char line[256];
int lineno = 0;
while(fgets(line, 256, in))
if(++lineno != 72)
fputs(line, out);
On Linux and
only Linux, you can use getline() instead of fgets() which is a GNU extension to stdio.h.
getline man page (http://linux.ctyme.com/man/man0933.htm)