C语言文件名处理

0. 背景介绍

在之前的博客【获取指定目录下的所有文件名】中介绍了如何在指定文件目录下获取所有有效文件名,这个博客中将介绍一些关于文件名的常见操作。

1. 分离目录和文件名

  • 需求:输入为一个文件的绝对或者相对路径,输出文件所在的目录和文件名表示
  • 解决方案:在Linux平台下的头文件“libgen.h”中,提供了dirname和basename来实现目的。
  1. dirname函数

        dirname函数以"/"为分隔符对路径进行分隔,返回值为文件目录路径。如果输入的文件路径没有"/",则返回"."。函数会对path进行修改。

      2. basename函数:获取文件名称

#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <iostream>
using namespace std;

int main()
{
    char filename[1024] = "/root/nVidia/deepstream_loulan_test/deepstream_loulan_detection.cpp";
    char buf[1024] = {0}; // 缓冲区
    char dname[1024] = {0}; // 目录
    char bname[1024] = {0}; // 文件名
    strcpy(buf, filename);

    cout << "buf 1: " << buf << endl;
    /* 
    Return directory part of PATH or "." if none is available.  
    extern char *dirname (char *__path) __THROW;
    */
   // dirname函数会对输入进行修改
    strcpy(dname, dirname(buf));
    cout << "buf 2: " << buf << endl;

    /* 
        Return final component of PATH.
        extern char *__xpg_basename (char *__path) __THROW;
        #define basename	__xpg_basename
    */
    strcpy(bname, basename(filename));
    std::cout << "dir name: " << dname << "   base name: " << bname << std::endl;
    return 0;
}
/** outputs
*buf 1: /root/nVidia/deepstream_loulan_test/deepstream_loulan_detection.cpp
*buf 2: /root/nVidia/deepstream_loulan_test
*dir name: /root/nVidia/deepstream_loulan_test   base name: deepstream_loulan_detection.cpp
*/

2. 分离文件名和后缀

  • 问题:将文件名的内容和后缀分离
  • 解决方案:c语言中的string.h头文件中,提供了strrchr函数来获取指定字符在字符串中最后一次出现的位置,返回值为一个指向目标字符的指针。
int main()
{
    char filename[256] = "deepstream_loulan_detection.cpp";
    char* pDest = NULL;
    int iNameLen = 0; // 不包括后缀名的文件名长度
    char iFileExt[256] = {0};   // 后缀
    char szFileTitle[1024] = {0};    // jpg文件名

    pDest = strrchr(filename, '.'); // 返回"."的char*
    if (NULL == pDest)
    {
        return -1;
    }
    iNameLen = pDest - filename;

    strncpy(szFileTitle, filename, iNameLen);
    printf("file name(no ext): %s\n", szFileTitle );
    strcpy(iFileExt, pDest+1);
    printf("file extension: %s\n", iFileExt);
    return 0;
}
/*
    file name(no ext): deepstream_loulan_detection
    file extension: cpp
*/

3. split函数实现

  • 问题:基于给定的分隔符,将字符串分割成字符串数组。
  • 解决方案:c语言中的string.h头文件中,提供了strtok函数来将字符串分割成字符串数组。
/**
 * @brief 指定分隔符将字符串分割,数据存到一个二维数组中去 
 * 
 * @param src : 需要分割分字符串
 * @param separator : 分隔符
 * @param dest : 二维数组用来保存分割后的数据
 * @param num : 字符串基于分隔符分割成了多少个字符串
 */
void split(char *src,const char *separator,char **dest,int *num) {
     char *pNext;
     //记录分隔符数量 
     int count = 0;
     //原字符串为空 
     if (src == NULL || strlen(src) == 0)
        return;
    //未输入分隔符
     if (separator == NULL || strlen(separator) == 0)
        return;   
	/*
		c语言string库中函数,
		声明: 
		char *strtok(char *str, const char *delim)
		参数: 
	    str -- 要被分解成一组小字符串的字符串。
    	delim -- 包含分隔符的 C 字符串。
    	返回值:
		该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。 

	*/
	 //获得第一个由分隔符分割的字符串 
    pNext = strtok(src,separator);
    while(pNext != NULL) {
     	//存入到目的字符串数组中 
        *dest++ = pNext; 
        ++count;
        /*
			strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。
			当strtok()在参数s的字符串中发现参数delim中包涵的分割字符时,则会将该字符改为\0 字符。
			在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。
			每次调用成功则返回指向被分割出片段的指针。

		*/  
        pNext = strtok(NULL,separator);  
    }  
    *num = count;
}    

4. 文本format

一个format specifier的语法原型如下:

%[flags][width][.precision][length]specifier

4.1 specifier

specifier表明了对应参数的类型和解释。

specifiertypeexample
d                 有符号整型        392
u无符号整型43215
f双精度浮点型392.65
c字符a
s字符串sample

4.2 flags

flags        描述
-       在给定的字段宽度内左对齐; 右对齐是默认设置
+即使对于正数,也强制在结果前面加上加号或减号(+ 或 -)。 默认情况下,只有负数前面带有 - 号。
space

在参数面前插入空格

0

给定字符宽度下,使用0填充而不是空格(整型)

4.3 width

width        描述
(number)指定最小的字符数需要被打印,如果打印参数长度小于这个值,使用空格填充
*占位符,用来指定在格式化参数前添加多少个空格填充

4.4  .precision

.precision       描述
.number对于 a、A、e、E、f 和 F 说明符:这是要在小数点后打印的位数(默认为 6)。

#include <stdio.h>

int main()
{
    int integral = 392;
    unsigned int uintegral = 43512;

    float single_float_point = 392.3;
    double de_float_point = 392.4444;

    char c = 'a';
    char str[256] = "sample";

    printf("%d\n", integral);
    printf("%u\n", uintegral);
    printf("%f\n", single_float_point);
    printf("%f\n", de_float_point);
    printf("%+d\n", integral);      // 在正数和负数前面,强制添加(+ or -)号
    printf("% d\n", integral);      // space在数字面前插入空格
    printf("%.2f", de_float_point);

    printf("%010d\n", integral);     // 给定字符宽度为10,使用0填充而不是空格
    printf("%*d\n", 5, integral);       // *为占位符用来表示字符宽度

    printf("%c\n", c);
    printf("%s\n", str);

    printf("%10s\n", str);      // 给定字符宽度为10, 默认情况下是使用空格填充, 并且是右对齐
    printf("%-10s\n", str);     // 左对齐

    return 0;
}
/*
392
43512
392.299988
392.444400
+392
 392
392.440000000392
  392
a
sample
    sample
sample  
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值