-3

I am making a task management system and I the users should be able to view tasks only with the status TO DO.

I have a file with entries looking like this:

8291 Math Homework Pg|1-2 2022/04/03 TD
8292 English Assignment Pg|1-2 2022/04/03 IP
8293 Science Homework Pg|1-2 2022/04/03 TD

if the user enter TD then I want the program to read only these lines from the file:

8291 Math Homework Pg|1-2 2022/04/03 TD
8291 Science Homework Pg|1-2 2022/04/03 TD

How can I do this in C?

HannahJ
  • 39
  • 7
  • 3
    What did you try already? Can you share your current code? – Markus Meyer Jun 19 '22 at 09:50
  • 1
    I am able to read all tasks but with this I am a little confused on how to start – HannahJ Jun 19 '22 at 09:51
  • 2
    I'd follow the same way you were told [here](https://stackoverflow.com/questions/72675342/how-can-i-read-specific-lines-from-a-file-on-c) : read the file line by line, qualifying whether the current line matches your criteria, and if it does, apply whatever logic you intended. In your case that would mean *not* ignoring lines ending with `TD` (apparently). – WhozCraig Jun 19 '22 at 09:52
  • But that is my question. How can I qualify a line and see if it matches my criteria – HannahJ Jun 19 '22 at 09:54
  • 2
    if line has 3 or more characters and If last character is a `'D'`, and the one before is `'T'`, and the one before is a space ... *accept* the line – pmg Jun 19 '22 at 09:55
  • I understand the logic of how to get this but I am not sure of how to implement it in C – HannahJ Jun 19 '22 at 09:56
  • `int linenen = strlen(line); if ((linenen >= 3) && isspace((unsigned char)line[linenen - 3]) && (line[linenen - 2] == 'T') && (line[linenen - 1] == 'D') { /* accept line */ }` – pmg Jun 19 '22 at 09:57
  • Oh... damn ... I forgot pesky little `'\n'`. Thanks @xing – pmg Jun 19 '22 at 10:02
  • But this is specifc to TD. I have TD, IP and CT so how can I implement this – HannahJ Jun 19 '22 at 10:25
  • Can I please have an example of the code for my scenario? I am really struggling. – HannahJ Jun 19 '22 at 10:38
  • @HannahJ: Which part of the problem are you having trouble with? Reading the file line-by-line using the function `fgets`? Determining whether a line meets the criteria or not using the function `strstr`? Outputting the line if it does meets the criteria? – Andreas Wenzel Jun 19 '22 at 10:43
  • I am struggling with determining if a line meets my criteria and how I can read only those lines – HannahJ Jun 19 '22 at 10:47
  • @xing: Using `strstr` with a newline character in the substring will only work if the input file has POSIX file endings, i.e. if the last line of the file ends with a newline character. If that is not the case, then `strstr` will never report a match on the last line of the file. See my answer for further information. – Andreas Wenzel Jun 19 '22 at 13:22
  • In case you are wondering why your question has been downvoted and closed, I suspect that the reason for this is that you did not focus your question on a specific issue, as I suggested in [this comment](https://stackoverflow.com/questions/72675825/how-can-i-check-if-a-line-in-a-file-contains-a-certain-value-in-c/72676864?noredirect=1#comment128374220_72675825). However, this is probably not your fault, because you were unable to focus your question, because you were under the false impression that it was possible to read only specific lines from the file, instead of reading all lines. – Andreas Wenzel Jun 19 '22 at 15:40

2 Answers2

1

Your comment brings your question to the point "a line meets my criteria and how I can read only those lines".
In this clear but strict phrasing the answers is that you can't.
You can only read all the lines and then ignore those which do not match your requirements.

I understand that the details of doing that you do not need help with because you state "I am able to read all tasks" and there are hints in other user comments on how to qualify a read line (in contrast to not reading a line which does not qualify) and you only focus on not reading unqualified lines. So I assume that once you change your goal to reading and ignoring instead of not reading you are set. If you do need help with reading, testing, ignoring I propose to ask that in a separate focused question.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • My goal is to read the lines with the status inputted from the user..that's what I need help with – HannahJ Jun 19 '22 at 11:21
  • No, your comments have already clarified that you do not need help with that. You are asking about not reading what does not qualify. If you want to ask about how exactly you can read all and ignore those which do not match you will have to create a new question (changing this one to ask that different question would be considered a "moving target" question). Leaving this question as is (with a non-negative score and some reputation) will not hurt your account on the other hand. – Yunnosch Jun 19 '22 at 11:24
0

You will have to read all lines in the file. There is no way to read only the lines that meet a certain criteria.

Therefore, you should read all lines in the file in a loop, using the function fgets, so that in every loop iteration, exactly one line is processed. In every loop iteration, you can then check whether the current line meets the criteria using the function strstr, and if it does, you can then print that line. Otherwise, you will do nothing in that loop iteration (i.e. not print that line).

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

int main( void )
{
    FILE *fp;
    char line[500];

    //open input file
    fp = fopen( "input.txt", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //read exactly one line per loop iteration
    while ( fgets( line, sizeof line, fp ) != NULL )
    {
        //print the line, if it meets the criteria
        if ( strstr( line, "TD\n" ) != NULL )
        {
            printf( "%s", line );
        }
    }

    //cleanup
    fclose( fp );
}

For the input

8291 Math Homework Pg|1-2 2022/04/03 TD
8292 English Assignment Pg|1-2 2022/04/03 IP
8293 Science Homework Pg|1-2 2022/04/03 TD

this program has the following output:

8291 Math Homework Pg|1-2 2022/04/03 TD
8293 Science Homework Pg|1-2 2022/04/03 TD

However, this program will only work if the input file has POSIX-compliant file endings, i.e. if the last character in the file is a newline character. If the last character in the file is not a newline character, then strstr( line, "TD\n" ) will never report a match on the last line, because it will be unable to find the newline character.

One way to solve this would be to use

strstr( line, "TD" )

instead of:

strstr( line, "TD\n" )

However, this is not an ideal solution, because if the first part of the line happens to contain the substring "TD", then you will get a false positive. You only want "TD" at the end of the line to be a match.

Therefore, the best solution would probably be to not use strstr on the whole line, but to use strcmp on the last 2 characters in the line:

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

int main( void )
{
    FILE *fp;
    char line[500], *p;

    const char *search_string = "TD";
    const int   search_string_len = strlen( search_string );

    //open input file
    fp = fopen( "input.txt", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //read exactly one line per loop iteration
    while ( fgets( line, sizeof line, fp ) != NULL )
    {
        if ( ( p = strchr( line, '\n' ) ) != NULL )
        {
            //remove newline character
            *p = '\0';
        }
        else
        {
            //make p point to null terminating character
            p = line + strlen(line);
        }

        //if the line has less characters then the search
        //string, then a match is not possible
        if ( p - line < search_string_len )
            continue;

        //compare the last characters on the line with the
        //search string
        if ( strcmp( p - search_string_len, search_string ) != 0 )
            continue;

        //all tests were passed, so print the line
        printf( "%s\n", line );
    }

    //cleanup
    fclose( fp );
}
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • This an amazing solution! Thank you so much the help! much appreciated. I had porblems understading the strstr but now its all clear after this solution – HannahJ Jun 21 '22 at 10:48