Help to filter read through reference file by using c language

Input_file

#tmp_2
werweraewghe
@tmp_2
123sdfs57a
#tmp_1
aewrgheheghe
@tmp_1
457awrerfa87
#tmp_4
trtyrghe
@tmp_4
8898rtyr2

reference_file

#tmp_4
#tmp_1

output_file

#tmp_4
trtyrghe
@tmp_4
8898rtyr2
#tmp_1
aewrgheheghe
@tmp_1
457awrerfa87

Logic thinking to solve the problem:

1. Based on the record of reference_file, print out those content that appear in Input_file into another output_file

Thanks for any advice.

Just translate this to C :rolleyes:

while read s; do
  while read t; do
    if echo "$t" | grep "${s#\#}"; then
      read q; echo "$q"
    fi
  done <Input_file
done <reference_file
#tmp_4
trtyrghe
@tmp_4
8898rtyr2
#tmp_1
aewrgheheghe
@tmp_1
457awrerfa87
1 Like

Try:

awk 'NR==FNR{sub("#","");a[$0]=1;next}/^#|@/{x=$1;sub("#|@","",x);if (x in a){print;getline;print}}' ref_file in_file
1 Like

But if seriously what did you try? Or do you just want somebody write a program for you?

Hi yazu,
I'm edited my source code now.
Will update to this thread soon.
Sorry for delay.

---------- Post updated at 03:42 AM ---------- Previous update was at 02:24 AM ----------

Hi yazu,
this is the c code that I tried:

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

int main(int argc, char**argv)
{
    FILE *fh, *fh1, *fout;
    char buf[4096];
    char buf1[4096];

    if (argc != 3)
    {
        printf("Usage: %s <input file> <reference file> <output file>\n", argv[0]);
        return -1;
    }

    if ((fh = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen");
        return -1;
    }
    if ((fh1 = fopen(argv[2], "r")) == NULL)
    {
        perror("fopen");
        return -1;
    }
    if ((fout = fopen(argv[3], "w")) == NULL)
    {
        perror("fopen");
        return -1;
    }


       while(fgets(buf1, sizeof(buf1), fh1))
       {
               if(buf[0]== '#')
               {
                       buf[0]='#';
                       fputs(buf1, fout);
                       if(fgets(buf, sizeof(buf), fh) ) continue;
                       fputs(buf, fout);
               }
       }
       fclose(fh);
       fclose(fh1);
       fclose(fout);
    return 0;


}

It can't do well :frowning:
Seems like wrong logic during the middle part of the code.
Thanks for any advice.

Ok. Let's try.

  1. Rename variables to work easier, For example fh - fref, fh1 - fsrc, buf - ref, buf1 - src.
  2. You need two loops - see my shell prototype.
  3. You need strings, not char buffers, so after reading add '\0' to the end of string (you should remember the value from fgets - use auxiliary variable).
  4. You need remove the first char from ref and src strings - use pointers (it's better to use two more variables).
  5. Use strcmp from standard library to compare strings (find what header you need).
  6. If there is a match, print src string and get and print the next string.

But before starting to code try to write the algorithm in words or (better) in pseudocode.

I believe you can to write a good program - you have the good start. If you would have some difficulties, try to write some simple programs at first - for example - the program which will be read one line from reference file, remove the first char, print it, and then print all lines from input file. Or the program which looks for constant string ("#tmp4") in the input file and print matching lines. Then improve it - it should print the matching and the next lines. And so on.

PS Sorry for my English.

If fgets didn't null-terminate for you, how could you possibly know where the NULL belongs? fgets terminates for you, like most string functions.

2 Likes

@Corona688

Yes, you're right. I have not used C much.

Hi Corona688,
do you have any idea to edit my code?
I'm facing error once editing it :frowning:
Thanks first.

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

int main(int argc, char**argv)
{
    FILE *finp, *fref;
    char inp[4096];
    char ref[4096];
    char * pinp = inp+1;
    char * pref = ref+1;

    if (argc != 3)
    {
        printf("Usage: %s <input file> <reference file>", argv[0]);
        return -1;
    }

    if ((finp = fopen(argv[1], "r")) == NULL)
    {
        perror("fopen");
        return -1;
    }
    if ((fref = fopen(argv[2], "r")) == NULL)
    {
        perror("fopen");
        return -1;
    }


    while (fgets(ref, sizeof(ref), fref))
    {
        rewind(finp);
        while (fgets(inp, sizeof(inp), finp)) {
            if (strcmp(pref, pinp) == 0) {
                printf("%s", inp);
                printf("%s", fgets(inp, sizeof(inp), finp));
            }
        }
    }

   fclose(finp);
   fclose(fref);
   return 0;
}
1 Like

Do you know what makes up argc...and realise the reason why the line below is wrong.

hi shamrock,
Kindly to point out if I'm wrong using of argc.
Based on what I understand, argc is using for command line arguments purpose.
Kindly correct me if I'm wrong coding.
I'm appreciate for any advice.

Hi yazu,

Many thanks for your code.
After I read through and try to understand the logic of your code.
I'm find the following doubts that need your advice:

  1. Can I know why you will set "char * pinp = inp+1; char * pref = ref+1;" ?
  2. Sad to said that I can't really get the meaning of "rewind(finp);" in the code :frowning:
    This is the first time I deal with "rewind" function.

Many thanks for your advice.

It ignores the first character in both buffers when comparing them.

I think it would have been simpler to write if (strcmp(ref+1, inp+1) == 0) { so the logic's in the strcmp instead of way high where you might forget it later.

The man command is your new friend, then.

$ man rewind
REWIND(3P)                 POSIX Programmer's Manual                REWIND(3P)



PROLOG
       This  manual  page is part of the POSIX Programmer's Manual.  The Linux
       implementation of this interface may differ (consult the  corresponding
       Linux  manual page for details of Linux behavior), or the interface may
       not be implemented on Linux.

NAME
       rewind - reset the file position indicator in a stream

SYNOPSIS
       #include <stdio.h>

       void rewind(FILE *stream);

DESCRIPTION
       The call:


              rewind(stream)

       shall be equivalent to:


              (void) fseek(stream, 0L, SEEK_SET)
1 Like

You are providing 4 arguments since your executable is counted in argc and if the command line looks like...

# <your_executable>  <input_file>  <reference_file>  <output_file>

then argc is 4 not 3.

1 Like