我想写一个文件到我下面的目录中,但是由于某种原因,我一直出错,我认为是因为缓冲区的文件标签结尾。像cd ..然后是cd directoryToWriteTo之类的名称必须是当前时间戳。 它总是告诉我开头为空,文件名是日期+ EOF,我认为这是问题所在吗?文件名也必须是静态的。
static char * filename ;
int main(){
generateName();
FILE * opening;
opening = fopen(filename,"aw");
if(opening == null){
fprintf("couldn't write to file");
fprintf(filename);
}
}
void generateName(){
time_t current_time;
struct tm *localtime;
char buffer[80];
current_time = time(NULL);
localtime= localtime(¤t_time);
if (localtime== NULL ){ exit(-1);}
strftime(buffer,sizeof(buffer),"%Y_%m_%d_%H_%M", localtime);
filenaam = buffer;
// How can i make it so it goes to a directory under him ?
}
它还必须与linux和Windows兼容。
答案 0 :(得分:2)
数组缓冲区的内存仅在generateName函数期间有效。 即使您使用filenam [sic]变量保留了指向缓冲区的指针, 指针在您返回主函数时不再有效,因为变量缓冲区是generateName函数的局部变量。
您应该声明并将字符数组分配为静态数组 只是分配一个指针,然后将该指针作为参数传递给generateName函数,然后在其中写入生成的文件名。
我希望这会有所帮助!
答案 1 :(得分:0)
您遗漏了两个要点,然后是小错误。
此示例在linux上编译并运行。它将创建一个新目录,该目录在从日期开始的子文件夹中带有文件“ junk.txt”。
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<sys/stat.h>
void generateName(char* buffer);
int main(int args_c, char** args){
char buffer[80];
generateName(buffer);
FILE * opening;
mkdir(buffer, 0755);
char out[89];
sprintf(out, "%s/junk.txt", buffer);
opening = fopen(out,"aw");
if(opening == NULL){
printf("couldn't write to file\n");
printf("%s \n",out);
}else{
printf("writing to %s\n", out);
fprintf(opening, "written in directory %s\n", buffer);
}
}
void generateName(char* buffer){
time_t current_time;
struct tm *actual;
time( ¤t_time );
actual = localtime( ¤t_time );
if (localtime== NULL ){ exit(-1);}
strftime(buffer,sizeof(buffer)*80,"%Y_%m_%d_%H_%M", actual);
}
首先,由于您在generateName
范围内声明了数组,因此生成的文件名被破坏了,一旦超出范围,就可以将其清除或重新使用。为了解决这个问题,我在main中创建了缓冲区,然后将其作为参数传递给generateName
。
第二,该程序使用mkdir
写入子目录。
答案 2 :(得分:0)
考虑一下:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
char *create_filename(const char *prefix,
const struct tm *timestamp,
const char *suffix)
{
/* YYYYMMDD-HHMMSS is 15 characters. */
const size_t timestamp_len = 15;
const size_t prefix_len = (prefix) ? strlen(prefix) : 0;
const size_t suffix_len = (suffix) ? strlen(suffix) : 0;
char *buffer;
size_t len;
/* Abort if no timestamp provided. */
if (!timestamp) {
fprintf(stderr, "create_filename(): No timestamp! (timestamp == NULL)\n");
exit(EXIT_FAILURE);
}
/* Allocate enough memory for prefix, timestamp, suffix,
and the end-of-string nul byte, '\0'. */
buffer = malloc(prefix_len + timestamp_len + suffix_len + 1);
if (!buffer) {
fprintf(stderr, "create_filename(): Out of memory.\n");
exit(EXIT_FAILURE);
}
/* Copy the prefix part, if any. */
if (prefix_len > 0)
memcpy(buffer, prefix, prefix_len);
/* Copy the timestamp part. */
len = strftime(buffer + prefix_len, timestamp_len + 1, "%Y%m%d-%H%M%s", timestamp);
if (len < 1 || len > timestamp_len) {
free(buffer);
fprintf(stderr, "BUG in create_filename(): timestamp_len is too small for strftime() pattern.\n");
exit(EXIT_FAILURE);
}
/* Copy the suffix part, if any. */
if (suffix_len > 0)
memcpy(buffer + prefix_len + len, suffix, suffix_len);
/* Add the terminating nul byte. */
buffer[prefix_len + len + suffix_len] = '\0';
return buffer;
}
希望这些注释足够清楚,以供新程序员使用。
请注意,表达式const size_t prefix_len = (prefix) ? strlen(prefix) : 0;
使用三元运算符(expression) ? (if-true) : (if-false)
。 strlen(NULL)
不安全,因此我们需要单独检查; (prefix)
进行检查。 (它等效于(prefix != NULL)
,并且可以读作“如果前缀为非NULL” 。)简单地说,如果prefix
为NULL,则其值为零,否则为字符串的长度:
size_t prefix_len;
if (prefix != NULL) {
prefix_len = strlen(prefix);
} else {
prefix_len = 0;
}
在主要功能中,您可以这样使用create_filename()
功能:
int main(void)
{
time_t now;
struct tm *nowtm;
char *path;
now = time(NULL);
nowtm = localtime(&now);
path = create_filename(NULL, &nowtm, ".txt");
printf("The path is '%s'.\n", path);
free(path); path = NULL;
return EXIT_SUCCESS;
}
在path
调用(已分配位置)之后,可以将create_filename()
当作字符数组来使用。当您不再需要它时,请致电free(path)
。这就是真正的动态内存管理多么简单。
程序退出时(使用主功能的return
或exit()
或_Exit()
功能),操作系统将自动释放所有动态分配的内存。因此,从技术上讲,不需要从主功能开始free()
之前或return
之前exit()
。尽管如此,出于学习目的,养成跟踪free()
s的习惯也是一个好主意。
大多数常见的错误是一对一的,可以免费使用。在create_filename()
中,不可能计算出一对一的错误,因为会计算前缀和后缀的长度,并明确检查strftime()
生成的模式的长度。
为避免释放后使用,通常在释放指针后将其显式设置为NULL。 (这在编程中通常称为“中毒” :将值设置为可识别的通常无效的值,以便更容易检测出使用后使用。)许多程序员都不会打扰,但他们只是愚蠢。并不是说它会使程序变慢或造成任何伤害;但这确实使调试更加容易。在这种情况下,如果在释放path
并将其设置为NULL后尝试使用它,则程序应崩溃(由于段冲突,NULL指针取消引用或类似的错误;这取决于您使用的操作系统) 。简而言之,它使查找错误变得更加容易。
如果您没有在path = NULL;
之后设置free(path);
,而在其后不小心添加了printf("path is now '%s'\n", path);
,则它可能起作用,或者可能不起作用,取决于系统,月亮的相位以及可能由于某一天的不确定行为而有一天可能从您的鼻子飞出的鼻翼的情绪。 (这是一个笑话:未定义的行为实际上是未定义的行为,尽管可能发生任何事情,但它不会破坏您的计算机,也不会破坏您的鼻子。只是,要使程序以可靠的方式运行确实很困难。如果您有任何未定义行为,则访问未释放的指针或NULL指针就是未定义的行为。)