我们的编程任务要求我们将文本文件分成一组名为(filename)partx.txt
的较小文件。例如,如果传递给程序的参数是名为stack.txt
的文本文件,则输出应为stackpart1.txt, stackpart2.txt etc
,其中每个文件的最大大小为250字节。
获得part_x的最佳方法是什么?
我学会了用##来实现宏。这种方法有什么缺点,有没有更好的方法? 以这种方式生成变量名称是一个好习惯吗?
答案 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)
你可以:
snprintf()
来生成文件名。(运行时)。这可以基于一些用于测量文件大小的算法动态使用。那就是说,最好的方法:使用snprintf()
。