ccstdio

Edit txt file using library from C


I am facing problems scanning an existing file.

The challenge is that I have a source text file with some strings. I have to scan this file for the word "o'clock", and where I find it, I have to take the word before "o'clock" and enclose it in square brackets.

I found a function to find the trigger, but I don't understand what I need to do next. I would be grateful if you could explain how to replace the characters in the read string.

For example: We have a string:

"Let's go to the graveyard at night - at twelve o'clock!"

I need to replace the word twelve with [twelve].

Here is the code:

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

int main() {
    FILE * fp; //open exists file
    FILE * fn; //open empty file
    char c[1000]; // buffer
    char trigger[] = "o'clock"; // the word before which the characters should be added
    char name [] = "startFile.txt"; // name of source file
    char secondName[] = "newFile.txt"; // name of output file
    fp = fopen (name, "r"); // open only for reading
    if (fp == NULL) { // testing on exists
        printf ( "Error");
        getchar ();
        return 0;
    }
    fn = fopen(secondName, "w"); // open empty file for writing
    while (!feof(fp)) { // scanning all string in the source
        if(fgets(c,1000, fp) != NULL) { // reading charter from file
            fprintf(fn, c); // writing charter from buffer "c" to empty file
            if (strstr(c, trigger)) { // find triggered word
                // I tried compare string which has a trigger-word
            }
        }
    }

    fclose(fp); // closing file
    fclose(fn);
    return 0;
}

Solution

  • In your code, you copy the line to the output file and then, afterwards, look for the trigger word. But the goal is to find the trigger and edit the string, and only then write the line to the output file. Also, in order to edit the line, you need to know where the trigger was found so you need to save the output of the search.

    So, instead of:

        fprintf(fn, c); // writing charter from buffer "c" to empty file
        if (strstr(c, trigger)) { // find triggered word
            // I tried compare string which has a trigger-word
        }
    

    We need:

        char *p = strstr(c, trigger);
        if (p) {
            // I tried compare string which has a trigger-word
        }
        fputs(c, fn); // writing charter from buffer "c" to empty file
    

    So now we found the trigger and we need to search backwards to find the end and then the start of the word before it. When we find them we need to create a spot and insert the edits:

        char *p = strstr(c, trigger);
        if (p) {
            // ok we found the trigger - now we need to search backwards
            // to find the end and then the start of the word before
            while (p>c && p[-1]==' ') p--; // find the end of the word
            memmove(p+1, p, c+999 - p); // make a space for the ]
            *p = ']';
            while (p>c && p[-1]!=' ') p--; // find the start of the word
            memmove(p+1, p, c+999 - p); // make a space for the [
            *p = '[';
        }
        fputs(c, fn); // writing charter from buffer "c" to empty file
    

    Try it here: https://www.onlinegdb.com/H18Tgy9xu

    But then, what if there was more than one "o-clock" in the string? Something like this:

    Let's go to the graveyard at twelve o'clock and have dinner at six o'clock beforehand!

    In that case, you need to loop around until you have found all of them:

    Here is the final code:

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        FILE * fp; //open exists file
        FILE * fn; //open empty file
        char c[1000]; // buffer
        char trigger[] = "o'clock"; // the word before which the characters should be added
        char name [] = "startFile.txt"; // name of source file
        char secondName[] = "newFile.txt"; // name of output file
        fp = fopen (name, "r"); // open only for reading
        if (fp == NULL) { // testing on exists
            printf ( "Error");
            getchar ();
            return 0;
        }
        fn = fopen(secondName, "w"); // open empty file for writing
        if (fn == NULL) { // testing on create
            printf ( "Error");
            getchar ();
            return 0;
        }
        while (fgets(c, 1000, fp)) { // scanning all string in the source
            char *p = c; // we need to start searching at the beginning
            do {
                p = strstr(p+1, trigger); // find the next oclock after this one
                if (p) {
                    // ok we found the trigger - now we need to search backwards
                    // to find the end and then the start of the word before
                    while (p>c && p[-1]==' ') p--; // find the end of the word
                    memmove(p+1, p, c+999 - p); // make a space for the ]
                    *p = ']';
                    while (p>c && p[-1]!=' ') p--; // find the start of the word
                    memmove(p+1, p, c+999 - p); // make a space for the [
                    *p = '[';
                    p = strstr(p, trigger); // find that same oclock again
                    // (we couldn't save the location because memmove has changed where it is)
                }
            } while (p); // as long as we found one, search again
            fputs(c, fn); // writing charter from buffer "c" to empty file
        }
        fclose(fp); // closing file
        fclose(fn);
        return 0;
    }
    

    Try it here: https://onlinegdb.com/SJMrP15ld