Search code examples
cprintffopen

fopen a file and skip character


Is there a clean way to open a file like this without system calls:

ID*_LogConfig.csv

I tried the following but it didn't worked.

/*Read setup file*/
getcwd(cwd, sizeof(cwd));
snprintf(source, sizeof(source),"%s/ID%*d_LogConfig.csv",cwd);
if( NULL == (input = fopen(source,"r")))
{
    snprintf(errbuffer,sizeof(errbuffer), "Could not open file %s - check existence/rights\n", source);
    exitHandler(1, errbuffer);
}

It outputs:

/mnt/dataflash/canfilter.d/ID*_LogConfig.csv not found

But with e.g. cat /mnt/dataflash/canfilter.d/ID*_LogConfig.csv it shows the file content.

My compromise solution would be a system call ll ID*_LogConfig.csv and using the output as filename.


Solution

  • Is there a clean way to open a file like this without system calls

    No. fopen() makes use of a system call. You cannot 'open' a file without a system call.

    If you're referring to the system(3) function, then you're probably in for some pain - it's best to avoid it if possible, from a performance, reliability and security point of view.

    If you want to open 'all files that match the pattern', then look at glob(3), which is likely what your shell is using to handle such wildcards. You will need to iterate over each of the resulting paths, calling fopen(), fread() and fclose() on each.

    Example usage of glob(3):

    #include <stdio.h>
    #include <glob.h>
    
    void main(void) {
        int ret;
        int i;
        glob_t glob_info;
    
        ret = glob("*.csv", 0, NULL, &glob_info);
        if (ret != 0)
        {
            fprintf(stderr, "glob() failed: %d\n", ret);
            return;
        }
    
        for (i = 0; i < glob_info.gl_pathc; i++) {
            printf("%d: %s\n", i, glob_info.gl_pathv[i]);
        }
    
        globfree(&glob_info);
    }
    

    It is not really a good idea to open lots of files and treat the stream as a single 'thing' (as you are doing with your cat example).

    As @Andrew has pointed out, you must be careful with your use of printf() format strings... You have provided the following: %s/ID%*d_LogConfig.csv. A % denotes the beginning of a format specifier, you have thus given the following:

    • %s - a char * (string) parameter follows
    • %*d - similar to %d, but the * means that the precision is provided as an int parameter, followed by the number itself.

    For example:

    printf(">%s< >%*d<\n", "Hello", 5, 3);
    

    Will output: (note the 5 characters that the %d outputs)

    >Hello< >    3<
    

    If you are after a *, then just put a * in the format string. If you are after a %, then you need to escape the % but putting %% in the format string.