【问题标题】:Writing to file with name = date写入名称 = 日期的文件
【发布时间】:2018-10-28 10:11:37
【问题描述】:

我想写入一个文件,该文件是我下面的一个目录,但由于某种原因,我不断收到错误,我认为是因为我的缓冲区的文件标签结尾。像 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(&current_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。

【问题讨论】:

  • 目录是否存在?尝试时出了什么问题?
  • C中有null吗?
  • 目录存在,但目前我只是想让名称工作而不去其他目录,文件名是 2018_10_28_10_44@■f
  • 什么是“在我之下”和“在他之下”?
  • 所以目前我在 /maindir/afile 并且必须去 /maindir/other

标签: c


【解决方案1】:

数组缓冲区的内存仅在您的 generateName 函数期间有效。 即使您使用 filenam [sic] 变量保留指向缓冲区的指针, 当您返回主函数时,指针不再有效,因为变量缓冲区是 generateName 函数的局部变量。

您应该将字符数组声明并分配为静态数组 只需分配一个指针,并将该指针作为参数传递给 generateName 函数,然后将生成的文件名写入那里。

我希望这会有所帮助!

【讨论】:

  • 用malloc代替char buffer[80]怎么样?
  • malloc 也可以正常工作。请记住在不再需要时释放内存!
【解决方案2】:

你遗漏了两个要点,然后是小错误。

这个例子在 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( &current_time );
    actual = localtime( &current_time );
    if (localtime== NULL ){ exit(-1);}
    strftime(buffer,sizeof(buffer)*80,"%Y_%m_%d_%H_%M", actual);
}

首先,生成的文件名被破坏了,因为您在generateName 的范围内声明了数组,一旦超出范围,它就可以被清除或重新使用。为了解决这个问题,我在 main 中创建了缓冲区,然后将其作为参数传递给 generateName

其次,本程序使用mkdir写入子目录。

【讨论】:

    【解决方案3】:

    考虑一下:

    #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;
    }
    

    希望 cmets 足够清晰,可以让新程序员继续学习。

    请注意,表达式const size_t prefix_len = (prefix) ? strlen(prefix) : 0; 使用三元运算符(expression) ? (if-true) : (if-false)strlen(NULL) 不安全,因此需要单独检查; (prefix) 进行检查。 (相当于(prefix != NULL),可以读作"if prefix is non-NULL"。)简单来说,如果prefix为NULL,则计算为0,否则为长度字符串:

        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;
    }
    

    您可以在create_filename() 调用(分配它的位置)之后使用path,就好像它是一个字符数组一样。当您不再需要它时,请致电free(path)。这就是真正简单的动态内存管理。

    当程序退出时(使用主函数中的return,或exit()_Exit() 函数),操作系统将自动释放所有动态分配的内存。因此,从技术上讲,不需要在主函数的 return 之前或 exit() 之前使用 free()。不过,出于学习目的,养成跟踪free()s 的习惯是个好主意。

    最常见的错误是一个接一个,释放后使用。在create_filename() 中,不可能出现非一错误,因为会计算前缀和后缀的长度,并明确检查strftime() 生成的模式的长度。

    为了避免释放后使用,我通常在释放指针后将指针显式设置为 NULL。 (这在编程中通常被称为“中毒”:将值设置为可识别的,通常是无效的值,以便更容易检测到 use-after-free。)许多程序员不打扰,但他们'只是很傻。这不像它会减慢程序或造成任何伤害;但它确实使调试更容易。在这种情况下,如果您在 path 被释放并设置为 NULL 后尝试使用它,您的程序应该会崩溃(由于段冲突、NULL 指针取消引用或类似错误;这取决于您使用的操作系统)。简而言之,它只是让查找错误变得更加容易。

    如果您没有在free(path); 之后设置path = NULL;,并且不小心在其后添加了printf("path is now '%s'\n", path);它可能会起作用,也可能不会,具体取决于系统,月相,以及由于未定义的行为可能有朝一日飞出你的鼻子的鼻小鬼的情绪。 (开个玩笑:未定义的行为实际上是未定义的行为,尽管任何事情都可能发生,但我们相信它不会破坏您的计算机或破坏您的鼻子。只是让程序以可靠的方式运行真的很难如果您有任何未定义的行为。访问已释放的指针或 NULL 指针是未定义的行为。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多