自动将数字附加到C中的变量

时间:2015-04-16 10:10:56

标签: c macros

我们的编程任务要求我们将文本文件分成一组名为(filename)partx.txt的较小文件。例如,如果传递给程序的参数是名为stack.txt的文本文件,则输出应为stackpart1.txt, stackpart2.txt etc,其中每个文件的最大大小为250字节。

获得part_x的最佳方法是什么?

我学会了用##来实现宏。这种方法有什么缺点,有没有更好的方法? 以这种方式生成变量名称是一个好习惯吗?

3 个答案:

答案 0 :(得分:3)

不要将变量名称与其内容混淆;宏和变量名与您的作业无关。 ##用于连接在编译时的代码中使用的字符串(典型用法是在宏中以参数方式构建标识符或一般代码),这是一种相对罕见的非常专业的任务。

你想要做的是在运行时根据模式生成字符串(=>你将拥有相同的字符串变量,你将在每个字符串中填充不同的东西迭代);正确的功能是snprintf

答案 1 :(得分:2)

这很简单,我说:你打开一个文件(fopen返回FILE *),然后你可以使用{{1}循环读取一个文件指定每次迭代时要读取的最大字节数。鉴于您无论如何都要使用循环,您可以增加一个简单的int来跟踪块文件名,使用fread创建名称,写下snprintf读取的字符到每个文件,并继续,直到你完成。

Some details on fread that might be useful to you

一个基本的例子(仍然需要一些工作):

fread

请注意,此代码不能完全安全地使用。您需要检查int main( void ) { int chunk_count = 0, chunk_size = 256; char buffer[256] FILE *src_fp, *target_fp; char chunk_name[50]; while (chunk_size == fread(buffer, chunk_size, 1, src_fp)) {//read chunk ++chunk_count;//increase chunk count snprintf(chunk_name, 50, "chunk_part%d.txt", chunk_count); target_fp = fopen(chunk_name, "w"); //write to chunk file fwrite(buffer, chunk_size, 1, target_fp); fclose(target_fp);//close chunk file } //don't forget to write the last chunk, if it's not 0 in length if (chunk_size) { ++chunk_count;//increase chunk count snprintf(chunk_name, 50, "chunk_part%d.txt", chunk_count); target_fp = fopen(chunk_name, "w"); //write to chunk file fwrite(buffer, strlen(buffer) + 1, 1, target_fp); fclose(target_fp);//close chunk file } fclose(src_fp); printf("Written %d files, each of max 256 bytes\n", chunk_count); return 0 ; } 的返回值(可以,并在某个时刻返回fopen)。基于NULL的循环简单地假设,如果其返回值小于块大小,我们已经到达源文件的末尾,但情况并非总是如此。你仍然必须自己处理NULL指针和fread。无论哪种方式,要研究的功能是:

  • ferror
  • fread
  • fopen
  • fwrite
  • fclose
  • ferror

应该这样做。


更新,只是为了它的乐趣。

您可能希望填充块文件名(chunk_part0001.txt)的编号。要做到这一点,您可以尝试预测源文件的大小,将其除以256,以计算出您最终将要使用的块数并使用该数量的填充零。如何获取文件大小is explained here,但这是我前一段时间的一些代码:

snprintf

如果你愿意,我可以解释每一个陈述,但其中的要点是:

  • long file_size = 0, factor = 10; int padding_cnt = 1;//at least 1, ensures correct padding fseek(src_fp, 0, SEEK_END);//go to end of file file_size = ftell(src_fp); file_size /= 256;//divided by chunk size rewind(src_fp);//return to beginning of file while(10 <= (file_size/factor)) { factor *= 10; ++padding_cnt; } //padded chunk file names: snprintf(chunk_name, sizeof chunk_name, "chunk_part%0*d.txt", padding_cnt, chunk_count); + fseek获取文件的大小(以字节为单位),除以块大小(256),即可获得您要创建的块总数(+1)余数,这就是为什么ftell初始化为1)
  • padding_cnt循环将总计数除以10 ^ n,每次因子乘以10,填充计数增加
  • 传递给while的格式更改为snprintf,这意味着:_&#34;打印一个int,填充n次出现0(即固定宽度)。如果最终得到123个块,则第一个块文件将被称为%0*d,第十个文件将chunk_part001.txt一直到chunk_part010.txt
  • 参考链接的问题,接受的答案使用chunk_part100.txt来获取文件大小,这更可靠(尽管它可能会造成一些轻微的可移植性问题)Check the stat wiki for alternatives

为什么呢?因为它很有趣,它使输出文件更容易按名称排序。它还使您能够预测保存目标文件名的char数组的大小,因此如果您必须使用sys/stat.h分配该内存,您就可以确切地知道您需要多少内存,并且不要#39; t必须分配100个字符(无论哪种方式都应该足够),并希望你的空间不足。
最后:你知道的越多,IMO越好,所以我想我会给你一些链接,你可能想要检查一下。

答案 2 :(得分:1)

你可以:

  • 按建议使用MACRO(编译时)。这涉及在实现代码时有关文件大小(以及子文件的数字)的一些知识。
  • 在循环中使用snprintf()来生成文件名。(运行时)。这可以基于一些用于测量文件大小的算法动态使用。

那就是说,最好的方法:使用snprintf()