0. 背景介绍
在之前的博客【获取指定目录下的所有文件名】中介绍了如何在指定文件目录下获取所有有效文件名,这个博客中将介绍一些关于文件名的常见操作。
1. 分离目录和文件名
- 需求:输入为一个文件的绝对或者相对路径,输出文件所在的目录和文件名表示
- 解决方案:在Linux平台下的头文件“libgen.h”中,提供了dirname和basename来实现目的。
- 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表明了对应参数的类型和解释。
specifier | type | example |
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
*/