使用C语言拆分csv文件名以获取数据

使用C语言拆分csv文件名以获取数据,c,csv,C,Csv,我有c变量文件\u路径- "a/b/c/xx.xxx_LOB_xxxx.caseno_YYYYMMDD.seq_no.csv" 从这个file_path变量中,我想得到file_name的值,不包括路径、LOB、caseno、file_date(yyyyymmdd)和seq_no,它们在不同的变量中使用C语言。我尝试了strtok(),但无法获得值 您能建议如何获得每个变量的值吗 谢谢。您有几个选项来分隔字符串。(在C中解析字符串时,您总是有几个选项)您总是可以使用一对指针

我有c变量
文件\u路径
-

"a/b/c/xx.xxx_LOB_xxxx.caseno_YYYYMMDD.seq_no.csv"
从这个
file_path
变量中,我想得到
file_name
的值,不包括路径、LOB、caseno、file_date(yyyyymmdd)和seq_no,它们在不同的变量中使用C语言。我尝试了
strtok()
,但无法获得值

您能建议如何获得每个变量的值吗


谢谢。

您有几个选项来分隔字符串。(在C中解析字符串时,您总是有几个选项)您总是可以使用一对指针沿着输入字符串向下移动,将两个指针之间的任何字符集括起来并进行复制。(您可以对不可变字符串(如字符串文字)进行操作,因为原始字符串未修改)

您可以使用
strtok()
来帮助将原始文件分解成更小的部分(有时甚至分解成您需要的部分)。但是,在这种情况下,由于
'.
既可以是分隔符,也可以是提取内容中包含的字符,因此仍然需要手动解析由
strtok()
分隔的标记中所需的内容。(
strtok()
修改它所操作的字符串,因此它必须是可变的)

第三个选项是创建一个格式字符串,并使用
sscanf()
解析输入中的变量。因为您的格式是固定的,所以您很幸运,您可以简单地使用
sscanf
来分隔您需要的内容。如果您对
sscanf
格式字符串以及所有修饰符和转换说明符不太熟悉,请花一个小时阅读和理解,所花的时间将为您节省十倍的时间

假设字符串中没有一个变量大于127个字符(根据需要进行调整),您的固定格式可以与格式字符串配合使用:

    " %*[^_]_%127[^_]%*[^.].%127[^_]_%127[^.].%127[^.]"
该字符串分为4个字符串。使用赋值抑制运算符
“*”
丢弃字符串中不需要的部分。如果要将输入分离为字符串数组
arr
,则可以编写一个简单的函数来处理分离,例如

 int varsfrompath (char (*arr)[MAXLEN], char *str)
{
    int i = sscanf (str, " %*[^_]_%127[^_]%*[^.].%127[^_]_%127[^.].%127[^.]",
                    arr[0], arr[1], arr[2], arr[3]);
    
    return i == EOF ? 0 : i;   /* return no. of vars separated */
}
返回从字符串中成功解析的项数。(如果发生输入故障,则为零)

一个有效的例子是:

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

#define NELEM  4
#define MAXLEN 128

int varsfrompath (char (*arr)[MAXLEN], char *str)
{
    int i = sscanf (str, " %*[^_]_%127[^_]%*[^.].%127[^_]_%127[^.].%127[^.]",
                    arr[0], arr[1], arr[2], arr[3]);
    
    return i == EOF ? 0 : i;   /* return no. of vars separated */
}

int main (void) {
    
    char fname[] = "a/b/c/xx.xxx_LOB_xxxx.caseno_YYYYMMDD.seq_no.csv",
        results[NELEM][MAXLEN] = { "" };
    int n = varsfrompath (results, fname);
    
    for (int i = 0; i < n; i++)
        printf ("results[%2d] = '%s'\n", i, results[i]);
}
这是迄今为止处理固定格式的最简单方法。使用一对指针进行手动解析更需要考虑(从字符串的角度来看),但并不困难。(乏味可能是个词)

仔细看看,如果我误解了你的分离需求,请告诉我,我可以调整它

使用一对指针手动解析

如果您不愿意花时间在
man 3 scanf
手册页上,而愿意花时间在一张8.5x11的纸和铅笔上,戴着会计帽,用一对指针做同样的事情,那么您可以做类似于以下的事情

您有一个起始指针
sp
和结束指针
ep
,您只需沿着输入行向下,将
sp
定位在要提取的变量之前,将
ep
定位在变量的末尾,然后使用
memcpy()
复制它们之间的字符。(有时,您必须按
1
进行调整,这取决于您是指向所需变量的开头,还是指向分隔符前的一个字符。(当在字符串下工作时,正确地获得算术的简单方法是只考虑在起始指针和结束指针之间存在1个字符)——这样,您是否需要添加或减去1来围绕定界符进行工作)将是明显的。 您可以将上面的
varsfrompath
函数替换为下面的函数,并接收相同的结果,例如:

int varsfrompath (char (*arr)[MAXLEN], const char *str)
{
    char *sp, *ep;      /* start pointer, end pointer */
    int i = 0;
    
    /* set sp to 1st '_' and ep to second '_', copy to arr and nul-terminate */
    if (!(sp = strchr (str, '_')) ||            /* can't find 1st '_' */
        !(ep = strchr (sp + 1, '_')) ||         /* can't find 2nd '_' */
        ep - sp - 2 > MAXLEN)                   /* chars between -1 > MAXLEN */
        return 0;
    memcpy (arr[i], sp + 1, ep - sp - 1);       /* copy ep - sp - 1 chars */
    arr[i++][ep - sp - 1] = 0;                  /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* set sp to next '.' and ep to next '_", copy to arr and nul-terminate */
    if (!(sp = strchr (sp, '.')) ||             /* can't find next '.' */
        !(ep = strchr (sp + 1, '_')) ||         /* can't find next '_' */
        ep - sp - 2 > MAXLEN)                   /* chars between -1 > MAXLEN */
        return i;
    memcpy (arr[i], sp + 1, ep - sp - 1);       /* copy ep - sp - 1 chars */
    arr[i++][ep - sp - 1] = 0;                  /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* set ep to next '.', copy to arr and nul-terminate */
    if (!(ep = strchr (sp, '.')) || ep - sp - 2 > MAXLEN)   /* no '.' or too long */
        return i;
    memcpy (arr[i], sp, ep - sp);               /* copy ep - sp chars */
    arr[i++][ep - sp] = 0;                      /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* repeate exact same steps for last var */
    if (!(ep = strchr (sp, '.')) || ep - sp - 2 > MAXLEN)
        return i;
    memcpy (arr[i], sp, ep - sp);
    arr[i++][ep - sp] = 0;
    sp = ++ep;
    
    return i;   /* return no. of vars separated */
}

它看起来可能更复杂,但实际上您只是使用简单的字符串函数,如
strchr()
来定位指针,然后提取它们之间的字符。比较并对比这两种方法。

您可以使用
strrchr()
来搜索最后一个
/
来找到目录的结尾。然后你可以使用
strtok()
来搜索
分隔符。我想我们可以使用basename(file\u path)来搜索文件名,但是我如何分割文件名来获得提到的每个值呢?所以你想要
“xx.xxx\u xxxx…csv”
?或者您想要分离并获得
“xx”
“xxx”
“xxxx”
?我们如何获得没有路径的文件名?只需使用
char*p=strrchr(str,“/”);
(注意:这两个
rr
)现在,指针指向最后一个
“/”
,因此文件名从
p+1
开始。因此,如果您有
char filename[2048];
您可以执行
strcpy(filename,p+1);
并将完整的文件名sans路径存储在
filename
中。
int varsfrompath (char (*arr)[MAXLEN], const char *str)
{
    char *sp, *ep;      /* start pointer, end pointer */
    int i = 0;
    
    /* set sp to 1st '_' and ep to second '_', copy to arr and nul-terminate */
    if (!(sp = strchr (str, '_')) ||            /* can't find 1st '_' */
        !(ep = strchr (sp + 1, '_')) ||         /* can't find 2nd '_' */
        ep - sp - 2 > MAXLEN)                   /* chars between -1 > MAXLEN */
        return 0;
    memcpy (arr[i], sp + 1, ep - sp - 1);       /* copy ep - sp - 1 chars */
    arr[i++][ep - sp - 1] = 0;                  /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* set sp to next '.' and ep to next '_", copy to arr and nul-terminate */
    if (!(sp = strchr (sp, '.')) ||             /* can't find next '.' */
        !(ep = strchr (sp + 1, '_')) ||         /* can't find next '_' */
        ep - sp - 2 > MAXLEN)                   /* chars between -1 > MAXLEN */
        return i;
    memcpy (arr[i], sp + 1, ep - sp - 1);       /* copy ep - sp - 1 chars */
    arr[i++][ep - sp - 1] = 0;                  /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* set ep to next '.', copy to arr and nul-terminate */
    if (!(ep = strchr (sp, '.')) || ep - sp - 2 > MAXLEN)   /* no '.' or too long */
        return i;
    memcpy (arr[i], sp, ep - sp);               /* copy ep - sp chars */
    arr[i++][ep - sp] = 0;                      /* nul-terminate */
    sp = ++ep;                                  /* set sp to 1-past ep */
    
    /* repeate exact same steps for last var */
    if (!(ep = strchr (sp, '.')) || ep - sp - 2 > MAXLEN)
        return i;
    memcpy (arr[i], sp, ep - sp);
    arr[i++][ep - sp] = 0;
    sp = ++ep;
    
    return i;   /* return no. of vars separated */
}