如何在.txt中修复&localtime-C

时间:2019-07-19 23:00:35

标签: c file

我想在我的程序中实现一个功能,该功能将.txt发送给我的电子邮件,其中包含我当天必须执行的一些任务。这是代码:

void txtCreator(){
  /**file.dat and file.txt, respectively**/
  FILE *fp, *fp1;
  /**struct that contain the events**/
  struct evento *display = (struct evento *)malloc(sizeof(struct evento));

  char buffer[48];
  char email_events[] = {"dd_mm.txt"};//filename.txt
  char msg[]={"Nao ha eventos disponiveis para hoje!\n"};
  int count=0;
  time_t rawtime;
  time(&rawtime);
  struct tm timenow = *localtime(&rawtime);
  strftime(buffer, 48, "%d_%m", &timenow);
  fp = fopen(file_name, "rb");
  fp1 = fopen(email_events, "w");
  if(strcmp(buffer, email_events)!=0){  
    strcpy(email_events, buffer);
    while(fread(display, sizeof(struct evento), 1, fp)==1){
      if (feof(fp) || fp==NULL){
        break;
      }
      else if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1){
        fwrite(display, sizeof(struct evento), 1, fp1);
        fprintf(fp1, "%s", "\n");
        count++;
      }
    }
  }
  if(count==0){
    fprintf(fp1, "%s", msg);
  }
  fclose(fp);
  fclose(fp1);
}

一切正常,但是有两个问题:

1-

strcpy(email_events, buffer);

不起作用,并且:

2-

当我创建.txt文件时,它显示如下:

测试¹0(¹€(。€(.v™™­°'¹8¹uguese_Brazil.12

它正确显示了事件名称(测试),但日期不起作用。

我尝试了很多事情,但是没有用。

很抱歉英语不好,不是我的母语。

2 个答案:

答案 0 :(得分:0)

假设您要复制email_eventsbuffer中(因为已分配了静态字符串),则strcpy参数是向后的。

下面是strcpy

的声明
char *strcpy(char *dest, const char *src);

您可能是说:

strcpy(buffer, email_events);

答案 1 :(得分:0)

  

当我创建.txt文件时,它显示如下:

     

test ¹0(¹€(.v™ ™­ °'¹8¹uguese_Brazil.12

首先解决这个问题:您不是在.txt文件中写入文本。您正在编写一个结构。看起来像垃圾。

例如,假设display->dia是19。这意味着将数字19写入文件,而不是文本19,即数字19。作为文本读取,19是垃圾。 10是换行符。 65是A

如果您打算将结构转储到文件中,并假设struct evento没有指针,那很好。实际上,您可能不应该添加换行符,它会因结构的大小而干扰文件的读取。

如果您要生成人类可读的文本文件,则需要将每个结构片段转换为文本。例如,如果您想将日期和月份写为文本...

fprintf(fp1, "%d_%d", display->dia, display->mes);

我认为这会继续下去。


  

strcpy(email_events, buffer);不起作用

乍看之下,您的strcpy似乎是倒退的,它是strcpy(src, dest),大概是您想将email_events复制到bufferstrcpy(buffer, email_events)中。

进一步,您的代码在此之后对bufferemail_events都无效。 strcpy毫无意义。

更进一步,buffer07_19之类的月份和日期。 email_events始终为dd_mm.txt。那些永远不会匹配。 strcmp(buffer, email_events)!=0永远都是正确的,使得if的检查毫无意义。

我不确定bufferemail_events的意图是什么,但是它似乎正在尝试根据当前日期创建文件名?可以使用一个更好命名的变量outfile来简单得多。

time_t rawtime;
time(&rawtime);
struct tm timenow = *localtime(&rawtime);
char outfile[20];
strftime(outfile, 20, "%d_%m.txt", &timenow);

要解决其他问题,您不必检查fp1是否已打开。

您最终确实检查了fp,但是在之后对其进行了检查,您已经从可能为空的文件指针中读取了该内容。如果您compiling with an address sanitizer(应该这样做)将导致错误。使用null指针时导致错误很好,它将为您解决许多神秘的内存问题。

它更容易,更强大,并且可以立即检查地址是否友好。我们还可以更好地命名它们,以避免混淆输出inout的输入。

FILE *in = fopen(file_name, "rb");
if( in == NULL ) {
    perror(file_name);
    exit(1);
}

由于您正在使用rb读取二进制文件,因此您应该编写二进制文件,因此应该使用wb。这仅在Windows上很重要,但也可能是一致的。

FILE *out = fopen(outfile, "wb");
if( out == NULL ) {
    perror(outfile);
    exit(1);
}

无需检查feof(fp)while(fread(display, sizeof(struct evento), 1, fp)==1)在读取失败时将在文件末尾退出循环。通常,显式检查文件末尾会导致一些细微问题。

读取/写入循环现在更加简单。

while(fread(display, sizeof(struct evento), 1, in)==1){
    if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1) {
        fprintf(out, "%d_%d\n", display->dia, display->mes);
        count++;
    }
}

将它们放在一起...

void txtCreator(){
    const char *no_events_found_msg = "Nao ha eventos disponiveis para hoje!\n";

    // No need to cast the result of malloc, it just invites mistakes.
    struct evento *display = malloc(sizeof(struct evento));

    // Generate the output filename directly, no strcmp and strcpy necessary.
    time_t rawtime;
    time(&rawtime);
    struct tm timenow = *localtime(&rawtime);
    char outfile[20];
    strftime(outfile, 48, "%d_%m.txt", &timenow);

    // Immediatetly make sure the files are open and error immediately.
    FILE *in = fopen(file_name, "rb");
    if( in == NULL ) {
        perror(file_name);
        exit(1);
    }

    FILE *out = fopen(outfile, "wb");
    if( out == NULL ) {
        perror(outfile);
        exit(1);
    }

    // Now that we know the files are open, reading and writing is much simpler.
    int count=0;
    while(fread(display, sizeof(struct evento), 1, in)==1){
        if(display->dia==timenow.tm_mday && display->mes==timenow.tm_mon+1) {
            fprintf(out, "%d_%d\n", display->dia, display->mes);
            count++;
        }
    }

    if(count==0){
        fprintf(out, "%s", no_events_found_msg);
    }

    fclose(in);
    fclose(out);
}

请注意,我使用了一种在适当位置声明变量的样式。这使代码更易于阅读,限制了每个变量的范围,并且避免了声明从未使用过的变量。