使用stb库保存图片时文件名生成异常,如何正确生成带序号的PNG文件名?
问题描述
使用stb库处理图像后保存到磁盘,图像本身生成正常,但文件名总是出错,生成的文件名是诸如"mnn"、"mfn"这类乱码短串,必须手动添加.png后缀才能正常查看图像。
我的代码如下:
for(unsigned int rep = 0; rep < 3; rep++) { //Execute image transformation create_square(50, 75, 100, 300, rand()%255, rand()%255, rand()%255); char* downloadName = (char *)malloc(sizeof( ("modified_image_" + std::to_string(rep) + ".png").c_str() )); *downloadName = *("modified_image_" + std::to_string(rep) + ".png").c_str(); std::cout << downloadName << " completed." << std::endl; //Write modified image to disk stbi_write_png(downloadName, width, height, channels, modified_image, width*channels); free(downloadName); }
我第一次用malloc()和.c_str(),可能忽略了明显问题。另外stbi_write_png()要求第一个参数是const char*类型,我以为不能直接用std::string,希望得到帮助。
解决方案
你的代码在文件名生成环节有两个致命错误:
1. malloc的内存大小计算完全错误
sizeof(xxx.c_str())得到的是指针的字节数(32位系统是4,64位是8),不是字符串的实际长度。这导致你只分配了极小的内存空间,根本装不下完整的文件名。
2. 字符串复制只拷贝了第一个字符
*downloadName = *xxx.c_str(); 这行代码仅仅把字符串的第一个字符赋值给了downloadName指向的内存,没有复制整个字符串,所以后续输出和保存时只会读取到第一个字符,剩下的都是内存里的乱码。
最简单的修复(推荐)
你完全误解了stbi_write_png的参数要求——它接受const char*,而std::string::c_str()正好返回const char*,直接用就行,根本不需要手动malloc:
for(unsigned int rep = 0; rep < 3; rep++) { //Execute image transformation create_square(50, 75, 100, 300, rand()%255, rand()%255, rand()%255); std::string downloadName = "modified_image_" + std::to_string(rep) + ".png"; std::cout << downloadName << " completed." << std::endl; //直接用c_str()传参,完全符合要求 stbi_write_png(downloadName.c_str(), width, height, channels, modified_image, width*channels); }
如果你非要手动管理内存(不推荐)
如果坚持要用malloc,必须正确计算字符串长度(要加1,给字符串结束符\0留位置),并用strcpy完整复制:
for(unsigned int rep = 0; rep < 3; rep++) { //Execute image transformation create_square(50, 75, 100, 300, rand()%255, rand()%255, rand()%255); std::string fileNameStr = "modified_image_" + std::to_string(rep) + ".png"; //分配足够的内存:字符串长度 + 1(\0) char* downloadName = (char *)malloc(fileNameStr.size() + 1); //完整复制字符串 strcpy(downloadName, fileNameStr.c_str()); std::cout << downloadName << " completed." << std::endl; stbi_write_png(downloadName, width, height, channels, modified_image, width*channels); free(downloadName); }
关键提醒
std::string是C++里最安全的字符串处理方式,除非特殊需求,不要手动用malloc管理字符串内存,容易出各种内存错误。- 任何时候用malloc分配字符串内存,都要记得给
\0留位置,否则会出现字符串截断或乱码。
内容的提问来源于stack exchange,提问作者Game_Freeze
相关产品推荐
相关产品推荐

