Home > Software engineering >  Problem while reading from the stem file in C
Problem while reading from the stem file in C

Time:11-09

I have a stem file named myfile, it has 2 sub files : myfile.data and myfile.names.

Now I want to write a code where it will first check the .names file's last line and see whether there is a zero or not, if there is any other number other than zero then it will say noisy data. And if the .names files last line has a zero, then I need to read the .data file and do some operations on that .data file to produce a valid output.

Now below I am giving what I have tried to do:

    int main(int argc, char **argv)
    {
                char *path = argc > 1 ? argv[1] : "stdin";
                sprintf(path, "%s.names", argv[1]);
                
                
                FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
                
                char buff[1024];
                int check = 0;

                fseek(in, 0, SEEK_SET); 

                while(!feof(in))
                {
                    memset(buff, 0x00, 1024); 
                    fscanf(in, "%[^\n]\n", buff);
                }
                
                if(strchr(buff, '0') != NULL){
                    check = 1;
                }
                
                if(check == 0){
                    printf("Noisy data...\n");
                }
                
                else if(check == 1){
                    
                    char *path = argc > 1 ? argv[1] : "stdin";
                    sprintf(path, "%s.data", argv[1]);
                    FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
                    char buf[1024];
                    
                    if( fgets(buf, sizeof buf, in) == NULL ){
                        fputs("Input error\n", stderr);
                        return 1;
                    }
                    
                    ...
                    ...
                    produces the perfect output.
                }
            }
}

To execute this : <./executable_filename> <stemFileName> > <outputFileName>

So whenever I am doing : ./myFileName myfile output

It is showing me : myfile.names.data: No such file or directory

Why is it happening? Please help.

CodePudding user response:

Here's an example which shows how to open the *.names file and includes logic to check if the final line of the file satisfies various properties.

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

int
main(int argc, char **argv)
{
    if( argc < 2 ){
        fprintf(stderr, "root filename required\n");
        return 1;
    }
    const char *base = argv[1];
    char input_path[PATH_MAX];
    snprintf(input_path, sizeof input_path, "%s.names", base);
    FILE *ifp = fopen(input_path, "r");
    if( ifp == NULL ){
        perror(input_path);
        return 1;
    }
    char buf[1024];
    /* Read the entire file one line at a time.  You could fseek to the
    end of the file and seek backwards to the start
    of the last line, but that seems to be an unnecessary
    complication for this example. */
    while( fgets(buf, sizeof buf, ifp) != NULL ){
        ;
    }
    /* When you get to the end, the last `fgets` returned NULL
    but did not write anything into buf, so buf contains the last
    line of the file */

    /* Check for read errors.
    ferror does not modify errno, but I can't find that
    in the language standard, so we'll make a copy.  Restoring
    errno ensures that `perror` reports the error that occurred
    during fgets rather than an error that occurs in the call to
    ferror.  This is probably overkill for this simple example.  It
    would be more important to check that `fgets` read a full line
    and handle that.  If the last line of the file is too large
    to fit in `buf`, the program should handle it; probably by aborting
    with an error message, but I don't know what you want to do in that
    case so I'm not bothering to check.
    */
    int errno_sav = errno;
    if( ferror(ifp) ){
        errno = errno_sav;
        perror(input_path);
        return 1;
    }

    puts("The last line is:");
    fputs(buf, stdout);
    /* Check if the last line contains a '0' */
    if( strchr(buf, '0') ){
        puts("The last line contains a 0");
    }
    /* Check if the last line is exactly the string "0\n" */
    if( strcmp(buf, "0\n") == 0 ){
        puts("The last contains nothing but a single 0");
    }

    char *end;
    /* Check if the last line is exactly some string representation
    of the integer 0.  (ie, "0000\n"  "0x0") */
    if( strtol(buf, &end, 0) == 0 && end != buf && *end == '\n'){
        puts("The last line is the integer 0");
    }
    return EXIT_SUCCESS;
}

Note that you might want to check that snprintf had enough space to write the filename, but that is not practically necessary. If the path is so long that it is an issue, the fopen will fail and you'll get a decent error message. It is possible that this will cause your program to incorrectly process a file with a truncated name like ...bas.nam, and it might be a good exercise to learn how to deal with that.

  • Related