努力构建可移植代码以使用 C 在任何操作系统中生成文件
Struggling to build a portable code to generate a file in any operating system using C
我正在尝试构建一个 C 可移植代码(适用于 Windows、MacOS 和 Linux),它创建一个输出 .txt
文件来接收数值模拟的结果。
总而言之,该代码采用文件名和扩展名,并检查该文件是否已存在于目录中。如果是这样,它会创建另一个同名文件,但在末尾的括号 (#) 之间加上一个数字以区分旧文件和新文件。
问题是:它在mac环境下正常工作,但是当我在windows上编译并运行它时,执行结束时没有创建文件.我找不到我做错了什么。
此外,我正在使用 Intel C/C++ Classic 编译器。如果我使用另一个编译器,例如 Intel® oneAPI DPC++/C++ Compiler for windows,当我调用 sizeof(src)
时,它会抱怨使用 sizeof(src)
=13=]函数。
到目前为止,这是代码的版本:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
bool file_exists(char *filename);
FILE *create_output_file(char *name, char *ext, bool (*file_exists)(char *));
#define funcname "test"
int main(void) {
// Create output files to store results
char *output_filename = malloc(200 * sizeof(*output_filename));
sprintf(output_filename, "%s_out", funcname);
printf("output_filename = %s\n", output_filename);
char *ext = ".txt";
FILE *output_file = create_output_file(output_filename, ext, file_exists);
}
bool file_exists(char *filename) {
// Try to open file with same name as filename
FILE *testfile = fopen(filename, "r");
// Bool variable to check the existence of file
bool exists = false;
// Check the existence of a file called filename
if (testfile != NULL) {
// Returns true if the file exists
exists = true;
}
// Close the file
fclose(testfile);
// Returns the existence of a file (1) = does exist, (0) = does not exist
return exists;
}
FILE *create_output_file(char *name, char *ext, bool (*file_exists)(char *)) {
// Form the full filename
name = strncat(name, ext, sizeof(ext));
printf("fullfilename = %s\n", name);
// Check if a file with the filename exists in the directory
if (file_exists(name)) {
// If exists, assign the same name with "(number)" to differentiate the new version
int j = 1;
char *numb = malloc(10 * sizeof(*numb));
sprintf(numb, "(%i)", j);
// Remove the extension from the name string
name[strlen(name) - strlen(ext)] = '[=10=]';
// Add (number) to the name and then add the file extension again
name = strncat(name, numb, sizeof(numb));
name = strncat(name, ext, sizeof(ext));
// Check if the name with numbers exists until it doesn't
int limit = 1e1;
while (file_exists(name)) {
j++;
sprintf(numb, "(%i)", j);
if (j == limit) {
name[strlen(name) - strlen(numb) + 1 - strlen(ext)] = '[=10=]';
limit = limit*10;
} else {
name[strlen(name) - strlen(numb) - strlen(ext)] = '[=10=]';
}
name = strncat(name, numb, sizeof(numb));
name = strncat(name, ext, sizeof(ext));
}
// Free allocated memory
free(numb);
}
// After assign the proper name, create the output file
FILE *output_file = fopen(name, "w");
// Returns the file
return output_file;
}
我在这里错过了什么?
存在多个问题:
在 file_exists
中你调用 fclose(testfile)
即使 fopen
失败了这有未定义的行为。
在 create_output_file
中,您对 sizeof
的用法不正确:在 strncat(name, ext, sizeof(ext));
中,sizeof
应用于指针,因此它的计算结果为指针的大小,而不是它指向的字符串的长度。你可以写
strncat(name, ext, strlen(ext));
但它完全等同于 strcat(name, ext);
函数strncat
定义为
char *strncat(char *dest, const char *src, size_t n);
它从src
指向的字符串到dest
指向的字符串的末尾最多复制n
个字符加上一个空终止符。
代码太复杂,你有多次内存泄漏,而且你在编写文件名时没有检查缓冲区溢出。
这是一个简化版本:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define funcname "test"
bool file_exists(const char *filename) {
// Try to open file with same name as filename
FILE *testfile = fopen(filename, "r");
if (testfile != NULL) {
fclose(testfile);
return true;
} else {
return false;
}
}
#define MAX_FILE_NUM 10000
FILE *create_output_file(char *name, size_t size,
const char *ext,
bool (*file_exists)(const char *))
{
size_t len = strlen(name);
int i = 0;
snprintf(name + len, size - len, "%s", ext);
while (file_exists(name)) {
if (++i > MAX_FILE_NUM) {
// all file versions tried.
return NULL;
}
snprintf(name + len, size - len, "(%d)%s", i, ext);
}
return fopen(name, "w");
}
int main() {
// Create output files to store results
char output_filename[200];
snprintf(output_filename, sizeof output_filename, "%s_out", funcname);
printf("output_filename = %s\n", output_filename);
const char *ext = ".txt";
FILE *output_file = create_output_file(output_filename,
sizeof output_filename, ext, file_exists);
if (output_file == NULL) {
printf("could not open output file, last try: %s\n", output_filename);
} else {
printf("actual output_filename = %s\n", output_filename);
fclose(output_file);
}
return 0;
}
我正在尝试构建一个 C 可移植代码(适用于 Windows、MacOS 和 Linux),它创建一个输出 .txt
文件来接收数值模拟的结果。
总而言之,该代码采用文件名和扩展名,并检查该文件是否已存在于目录中。如果是这样,它会创建另一个同名文件,但在末尾的括号 (#) 之间加上一个数字以区分旧文件和新文件。
问题是:它在mac环境下正常工作,但是当我在windows上编译并运行它时,执行结束时没有创建文件.我找不到我做错了什么。
此外,我正在使用 Intel C/C++ Classic 编译器。如果我使用另一个编译器,例如 Intel® oneAPI DPC++/C++ Compiler for windows,当我调用 sizeof(src)
时,它会抱怨使用 sizeof(src)
=13=]函数。
到目前为止,这是代码的版本:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
bool file_exists(char *filename);
FILE *create_output_file(char *name, char *ext, bool (*file_exists)(char *));
#define funcname "test"
int main(void) {
// Create output files to store results
char *output_filename = malloc(200 * sizeof(*output_filename));
sprintf(output_filename, "%s_out", funcname);
printf("output_filename = %s\n", output_filename);
char *ext = ".txt";
FILE *output_file = create_output_file(output_filename, ext, file_exists);
}
bool file_exists(char *filename) {
// Try to open file with same name as filename
FILE *testfile = fopen(filename, "r");
// Bool variable to check the existence of file
bool exists = false;
// Check the existence of a file called filename
if (testfile != NULL) {
// Returns true if the file exists
exists = true;
}
// Close the file
fclose(testfile);
// Returns the existence of a file (1) = does exist, (0) = does not exist
return exists;
}
FILE *create_output_file(char *name, char *ext, bool (*file_exists)(char *)) {
// Form the full filename
name = strncat(name, ext, sizeof(ext));
printf("fullfilename = %s\n", name);
// Check if a file with the filename exists in the directory
if (file_exists(name)) {
// If exists, assign the same name with "(number)" to differentiate the new version
int j = 1;
char *numb = malloc(10 * sizeof(*numb));
sprintf(numb, "(%i)", j);
// Remove the extension from the name string
name[strlen(name) - strlen(ext)] = '[=10=]';
// Add (number) to the name and then add the file extension again
name = strncat(name, numb, sizeof(numb));
name = strncat(name, ext, sizeof(ext));
// Check if the name with numbers exists until it doesn't
int limit = 1e1;
while (file_exists(name)) {
j++;
sprintf(numb, "(%i)", j);
if (j == limit) {
name[strlen(name) - strlen(numb) + 1 - strlen(ext)] = '[=10=]';
limit = limit*10;
} else {
name[strlen(name) - strlen(numb) - strlen(ext)] = '[=10=]';
}
name = strncat(name, numb, sizeof(numb));
name = strncat(name, ext, sizeof(ext));
}
// Free allocated memory
free(numb);
}
// After assign the proper name, create the output file
FILE *output_file = fopen(name, "w");
// Returns the file
return output_file;
}
我在这里错过了什么?
存在多个问题:
在
file_exists
中你调用fclose(testfile)
即使fopen
失败了这有未定义的行为。在
create_output_file
中,您对sizeof
的用法不正确:在strncat(name, ext, sizeof(ext));
中,sizeof
应用于指针,因此它的计算结果为指针的大小,而不是它指向的字符串的长度。你可以写strncat(name, ext, strlen(ext));
但它完全等同于
strcat(name, ext);
函数
strncat
定义为char *strncat(char *dest, const char *src, size_t n);
它从
src
指向的字符串到dest
指向的字符串的末尾最多复制n
个字符加上一个空终止符。代码太复杂,你有多次内存泄漏,而且你在编写文件名时没有检查缓冲区溢出。
这是一个简化版本:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define funcname "test"
bool file_exists(const char *filename) {
// Try to open file with same name as filename
FILE *testfile = fopen(filename, "r");
if (testfile != NULL) {
fclose(testfile);
return true;
} else {
return false;
}
}
#define MAX_FILE_NUM 10000
FILE *create_output_file(char *name, size_t size,
const char *ext,
bool (*file_exists)(const char *))
{
size_t len = strlen(name);
int i = 0;
snprintf(name + len, size - len, "%s", ext);
while (file_exists(name)) {
if (++i > MAX_FILE_NUM) {
// all file versions tried.
return NULL;
}
snprintf(name + len, size - len, "(%d)%s", i, ext);
}
return fopen(name, "w");
}
int main() {
// Create output files to store results
char output_filename[200];
snprintf(output_filename, sizeof output_filename, "%s_out", funcname);
printf("output_filename = %s\n", output_filename);
const char *ext = ".txt";
FILE *output_file = create_output_file(output_filename,
sizeof output_filename, ext, file_exists);
if (output_file == NULL) {
printf("could not open output file, last try: %s\n", output_filename);
} else {
printf("actual output_filename = %s\n", output_filename);
fclose(output_file);
}
return 0;
}