【C语言】文件名处理问题

C语言处理文件名

** 代码是写给人看的,不是写给机器看的,只是顺便计算机可以执行而已 ——《计算机程序的构造和解释》**
首先放上这句话来说明写代码的时候不必过分的“咬文嚼字”。然而,这篇文章记录的似乎就是一个“咬文嚼字”的故事。

背景

事情是这样的,最近找到一个音频降噪的库,想要写个demo测试一下。程序流程很简单,打开文件 --> 读取数据 --> 处理数据 --> 保存到文件。 编译、运行,得到的结果也没什么问题,准备整理整理代码归个档。
突然发现程序中的输入文件"input.pcm"、输出文件 “output.pcm” 是不是有点太low了,更换了输入文件还要改名,每次的输出文件不做备份还会被覆盖,这看起来也太不“高级”了。
想想平时用过的一些开源工具,都是命令后面加上一些选项,看起来很“高级”,照着它们的模样搞起来。

使用main函数传参

使用main函数的参数传入输入文件和输出文件名也是很常见的做法,这种方法比较简单,代码如下:

int main(int argc, char *argv[ ])
{
	printf("input: %s\n", argv[1]);
	printf("output: %s\n", argv[2]);                                                                                                                                
    return 0;
}

上述代码中,argv[1] 和 argv[2] 表示执行程序时的第2和第3个参数,编译程序,执行的时候加上输入输出文件名即可。

./test test.wav test_resample.wav

一切看起来正常,但是测了几次后发现每次输入两个文件名有点烦,就想改进一下程序,只给输入文件的名字,让程序自动生成输出文件的文件名。

自动生成输出文件名

这里涉及到简单的字符串处理,流程是,首先去掉 输入文件的后缀名,即只保留 ‘.’ 前面的内容,然后使用 strcat 函数接上相应的标识字符串即可。于是乎有了下面的代码。

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

int main(int argc, char *argv[ ])
{
    int i;
    printf("input: %s\n", argv[1]);
    char output_file[128] = {0};
    /* 拷贝'.'前面的内容 */
    for (i = 0; argv[1][i] != '.'; i++)
        output_file[i] = argv[1][i];
    /* 连接上新的后缀 */
    strcat(output_file, "_resample.wav");
    printf("output: %s\n", output_file);
    return 0;
}

编译运行,可以实现;

root@MRS:test# gcc -Wall test.c
root@MRS:test# ./a.out test.wav
output: test_resample.wav

本想这样移植到工程中,但看着for循环有点不舒服,就想有没有什么方法可以代替这个for循环。

使用标准函数

在 string.h 中找了一圈,发现 strncpy 和 strcspn。

**strncpy() ** 是比较常用的函数,功能是,拷贝字符串 src 前 n 个字符 到字符串 dest 中;

原型

	char *strncpy(char *dest, const char *src, size_t n);

参数

  • dest: 目标字符串指针
  • src: 源字符串指针
  • n: 要复制的字符数

返回值
返回复制后的目标字符串

**strcspn()**是一个比较陌生的函数,查了其描述:

原型

	size_t strcspn(const char *str1, const char *str2);

参数

  • str1:被检索的字符串
  • str2:用于匹配的字符串

返回值
返回str1中连续不包含str2中字符的字符数。

参考描述,strcspn函数功能是 获得 str1 连续多少个字符不包括 str2 中的字符。说起来有点绕,举个例子:
str1 = “abcd1234”;
str2 = “3df”;
可以看到字符串 str1 中 ‘d’ 之前都没有包含 str2 中的任何字符,于是 strcspn(str1, str2); 返回 3。
于是新的代码为:

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

int main(int argc, char *argv[ ])
{
    char output_file[128];
    printf("input: %s\n", argv[1]);
    // 复制‘.’前的内容,strcspn(argv[1], ".")用于判断输入文件名'.'前的字符个数
    strncpy(output_file, argv[1], strcspn(argv[1], ".") + 1);
	// 连接上 标识符和后缀
    strcat(output_file, "_resample.wav");
    printf("output: %s\n", output_file);

    return 0;
}     

编译运行,没有问题。

root@MRS:test# gcc -Wall test.c 
root@MRS:test# ./a.out test.wav
output: test_resample.wav

到此,强迫症已被治愈大半。但是,关闭 string.h 时突然又瞥见一个陌生的函数。

再简单一点

strtok
一个没怎么用过的函数,先看声明:
原型

char *strtok(char *str, const char *delim)

参数

  • str : 要被分解的字符串
  • delim : 包含分隔符的字符串

返回值
返回分解后的第一个子字符串,如果没有发现可检索的字符,返回NULL;
作用很简单,就是检索字符串 str 中有没有包含字符串 delim 中的字符,如果有,就将str分解,并返回分解得到的第一个子字符串。理解以后,继续修改代码

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

int main(int argc, char *argv[ ])
{
    char *file_name = argv[1];
    printf("input: %s\n", file_name);
    strcat(strtok(file_name, "."), "_resample.wav");
    printf("output: %s\n", file_name);

    return 0;
}

root@MRS:test# gcc -Wall file_name.c 
root@MRS:test# ./a.out test.wav
input: test.wav
output: test_resample.wav

编译、运行,没有问题,归档。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值