Originally Posted by
fat32
Would it be too much to ask someone to post a working solution that use two or three files on disk as my project requires? I should have asked in the first place.
Since you apparently managed to get it to work, here's how I might have done it:
Code:
/**
* C program to copy text from a file to another file, without the given word
* to remove.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Configuration variables */
#define INPUT_FILENAME "1.txt"
#define OUTPUT_FILENAME "2.txt"
#define WORD_TO_REMOVE "remove me"
#define VERBOSE 1
size_t copyWithoutRemovedWord(FILE *output_fp,
FILE *input_fp,
const char *word_to_remove);
size_t removeAll(char *text, const char *word_to_remove);
int main(void)
{
FILE *input_fp;
FILE *output_fp;
size_t remove_count;
if (!(input_fp = fopen(INPUT_FILENAME, "r")))
{
fprintf(stderr,
"Error: could not open '%s' for input.\n",
INPUT_FILENAME);
return EXIT_FAILURE;
}
if (!(output_fp = fopen(OUTPUT_FILENAME, "w")))
{
fprintf(stderr,
"Error: could not open '%s' for output.\n",
OUTPUT_FILENAME);
fclose(input_fp);
return EXIT_FAILURE;
}
remove_count = copyWithoutRemovedWord(output_fp, input_fp, WORD_TO_REMOVE);
fclose(output_fp);
fclose(input_fp);
if (VERBOSE)
{
printf("%zu occurrences of '%s' removed successfully.\n",
remove_count, WORD_TO_REMOVE);
}
return 0;
}
/**
* Copy all text from the input stream to the output stream without any
* occurrences of the removed word.
*/
size_t copyWithoutRemovedWord(FILE *output_fp,
FILE *input_fp,
const char *word_to_remove)
{
size_t remove_count = 0;
char buffer[BUFSIZ];
while (fgets(buffer, BUFSIZ, input_fp))
{
/* There is a potential bug when a line is too long to fit in the
buffer, so we shall warn the user if that condition occurs: */
if (!strchr(buffer, '\n'))
{
fprintf(stderr,
"Warning: the word to remove might not be found as the "
"line was only partially read for the searching.\n");
}
remove_count += removeAll(buffer, word_to_remove);
fputs(buffer, output_fp);
}
return remove_count;
}
/**
* Remove all occurrences of the word to remove from the text.
*/
size_t removeAll(char *text, const char *word_to_remove)
{
const size_t word_to_remove_len = strlen(word_to_remove);
size_t removal_count = 0;
char *removal_point = NULL;
char *found;
while ((found = strstr(text, word_to_remove)))
{
if (removal_point)
{
/* Shift the substring between the previous removal point and the
current word found to overwrite the previous removal point: */
while (text != found)
{
*removal_point++ = *text++;
}
}
else
{
/* Do not overwrite the word to remove yet, but rather record the
removal point: */
removal_point = found;
}
text = found + word_to_remove_len;
++removal_count;
}
/* Since we avoid doing extra work by only shifting when the next removal
point is found, we need to shift the remaining substring to overwrite
the last removal point: */
if (removal_point)
{
while ((*removal_point++ = *text++));
}
return removal_count;
}
Notice that you only need to change the configuration variables. I added VERBOSE because when everything works fine, one convention is to print nothing (so VERBOSE would be set to 0), but sometimes people do want something to be printed as a positive confirmation that all went well, in which case VERBOSE would be set to 1.
Clearly, a disadvantage of this approach is that you have to recompile whenever you want to change the value of a configuration variable, but as that is apparently what you want, you have to live with it. Typically, better approaches would involve things like command line arguments or a configuration file (e.g., in an INI format). Also, instead of requiring the user to specify an input filename and an output filename, another approach is to read from standard input and write to standard output, then the user can use I/O redirection to read/write from/to the input/output files.
Originally Posted by
fat32
Could someone tighten it up for me. I’m reading everything that I can about it including here at the C Tutorial to try to do what I been crying about through-out this entire thread. Other then that, which type is the fastest and the most reliable out the two listed in the thread posted above?
The two implementations have different capabilities, so it doesn't make sense to talk about "fastest and most reliable" when they don't do the same thing. What exactly do you have in mind when you say "substr"?