从 C 中的 stem 文件读取时出现问题

Problem while reading from the stem file in C

我有一个名为 myfile 的主干文件,它有 2 个子文件:myfile.datamyfile.names

现在我想写一段代码,它首先检查 .names 文件的最后一行,看看是否有零,如果有除零以外的任何其他数字,那么它会说 noisy data。如果 .names 文件最后一行有一个零,那么我需要读取 .data 文件并对那个 .data 文件做一些操作以产生有效的输出。

下面我给出了我尝试做的事情:

    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.
                }
            }
}

要执行此操作:<./executable_filename> <stemFileName> > <outputFileName>

所以每当我做的时候:./myFileName myfile output

它给我看:myfile.names.data: No such file or directory

为什么会这样?请帮忙

下面的示例展示了如何打开 *.names 文件,并包含检查文件的最后一行是否满足各种属性的逻辑。

#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;
}

请注意,您可能需要检查 snprintf 是否有足够的 space 来写入文件名,但这实际上不是必需的。如果路径太长而成为问题,则 fopen 将失败并且您将收到一条不错的错误消息。这可能会导致您的程序错误地处理名称被截断的文件,例如 ...bas.nam,学习如何处理该文件可能是一个很好的练习。