【问题标题】:Log file rotation name日志文件轮换名称
【发布时间】:2009-07-16 09:37:33
【问题描述】:

我编写了这个简单的 C 程序来更改旋转文件名。 例如:对于A_B_C_1需要旋转到A_B_C_2如果A_B_C需要旋转到A_B_C_1

问题是strncat 没有按预期工作。它给了我这样的输出:

A_B_C_1 (Works fine for single instance)
A_B_C_2
A_B_C_23
A_B_C_2324

使用的逻辑很简单: - 如果存在,则获取字符串中的最后一个数字。 - 如果它不简单地附加_1(这个工作正常) - 如果是 - 提取数字,将其递增并附加到新字符串。

是否有一些标准库可以做到这一点?

在循环/多次调用此方法时出错......

我无法调试原因.....需要帮助,请指导。

   int getRotationFileName(char *sFileName,char *sNewFileName)
   {
   char sTmpFile[256];
    int newRotation;
    memset(sTmpFile,NULL,sizeof(sTmpFile));
    strncpy(sTmpFile, sFileName, strlen(sFileName));
    char *tokenPtr;
    strtok(sFileName,"_"); //a
    strtok(NULL, "_"); //b
    strtok(NULL, "_"); //c
    tokenPtr = strtok(NULL, "_"); //1
        printf("sTempFile [%s], sFileName [%s], token [%s]",
            sTmpFile,sFileName,tokenPtr);


    if(tokenPtr!= NULL)//Last - exists
    {

        newRotation = atoi(tokenPtr);
        int newLen = strlen(sTmpFile);
        int oneLen = strlen(tokenPtr);
        memset(sNewFileName, NULL, sizeof(sNewFileName));
        printf("sNewFileName is prior: %s and len is %d \n", 
        sNewFileName, (newLen-oneLen));
        printf("sTempName is prior: %s", sTmpFile);
    strncpy(sNewFileName,sTmpFile, (newLen-oneLen));

        printf("diff is %d\n", (newLen-oneLen));
        printf("sNewFileName before concat %s \n", sNewFileName);
        newRotation++;
        sprintf(sNewFileName,"%s%d",sNewFileName, newRotation);
        sNewFileName[strlen(sNewFileName)]='\0';
        printf("sNewFileName after concat %s \n", sNewFileName);
    }
    else
    {
        printf("in else TmpFile [%s] , New File [%s], len %d",sTmpFile,
     sNewFileName,strlen(sTmpFile));
        strcat(sTmpFile,"_1");
        strncpy(sNewFileName,sTmpFile, strlen(sTmpFile));
    }
    strcpy(sFileName, sNewFileName);
    printf("\nNew file created is %s\n",sNewFileName);
    return 1;

}

网上好像有问题:strncpy(sNewFileName,sTmpFile, (newLen-oneLen));

反馈:Chrome 浏览器的代码格式化程序在此站点上无法正常工作

【问题讨论】:

  • 源代码的格式很混乱...发布代码,只需确保它缩进四个空格。
  • 我已修复它,但修复已恢复,我认为这就是 Chrome“反馈”行所指的内容。奇怪的。修正版本在编辑历史中,请随时重新应用。 :)
  • 小更新:初始名称中可以有数字,如果需要,我必须先检查两个下划线,然后再在最后一个下划线后面加上递增的数字

标签: c string


【解决方案1】:

您的代码......有点乱。你需要把你的算法分成几个步骤,每个步骤都应该很容易执行:

  • 检查名称是否以数字结尾。如果是,请记录号码的开始位置,然后提取号码。如果不是,就当它以 0 结尾。
  • 增加数字。
  • 通过连接前缀和数字(作为字符串)创建一个新字符串。

请注意,这些算法是活泼的,通常最好让标准库为您生成一个唯一的名称。

这里有一个解决方案:

void rotateName(const char *oname, char *nname)
{
    const char  *ptr;
    int         number, plen;

    for(ptr = oname; *ptr && !isdigit(*ptr); ptr++)
            ;
    if(*ptr == '\0')
            number = 0;
    else
            number = atoi(ptr);
    plen = ptr - oname;
    if(plen <= 0)
            return;
    memcpy(nname, oname, plen);
    sprintf(nname + plen, "%d", number + 1);
}

【讨论】:

    【解决方案2】:

    使用例如

    int get_rotated_name(char *filename,char *rotatedname,size_t len)
    {
        int version = 0;
        int pos = strrchr(filename,'_');
    
        if(pos == -1)
          return 1;
        if(isdigit(filename[pos+1])) {
          version = atoi(&filename[pos+1];
          filename[pos] = 0;
       }
    
       version++;
       snprintf(rotatedname,len,"%s_%d",filename,version);
    
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      对于常量文件名字符串,您不需要所有 strtok 活动。

      • 要么将常量部分与strncmp 进行比较以确认它,要么使用sscanf
      • atoisscanf %d 取出文件编号整数
      • 进行比较并更改整数(使用模运算等)
      • 使用新整数生成带有sprintf 的新名称

      而且,如果您不需要按照函数的建议从先前传递的文件中实际生成下一个文件名,只需保留一个常量字符串和一个旋转整数,与sprintf 一起使用以生成下一个文件名。
      我知道这可能并非在所有情况下都可用。

      【讨论】:

        【解决方案4】:

        你真的要轮换序列号吗?

        我建议不要这样做,并使用序列号不断增加文件名常量,这将有助于了解打开了多少文件。

        Parallaly 您可以维护文件名数组,并在每次打开新文件时旋转起始索引和结束索引并增加起始索引。当数组被填满时,只需删除结束索引处的文件并继续。

        【讨论】:

          【解决方案5】:

          我会查看字符串的末尾,如果它是一个数字,我会继续返回,直到找到一个非数字字符,将这些添加到字符串中,并保持位置 (p)。

          • '文件名' => ''
          • 'filename_9' => '9'
          • '文件名-3786' => '3786'

          然后我会将它转换为数字 n,如果它是空的,我会假设为零。

          我会将原始字符串提升到 p,将 n+1 转换为字符串并将其连接起来。

          • '文件名' => '文件名2'
          • 'filename_9' => 'filename_10'
          • '文件名-3786' => '文件名-3787'

          您还可以在第 p 个字符处查找分隔符,例如 ' '、'_'、'-',然后删除它们,然后始终添加固定分隔符,例如 _。

          【讨论】:

            【解决方案6】:

            是否有一些标准库可以做到这一点?

            我会使用 logrotate (https://linux.die.net/man/8/logrotate) 而不是重新发明轮子。

            您只需要安装一个关闭并重新打开日志文件的 sigusr1 处理程序。 logrotate 将为您旋转/重命名/压缩文件。

            如果您不喜欢使用 sigusr1 处理程序,或者将其用于其他用途,那么您可以在日志例程中实现文件存在性检查。如果日志文件消失了,这意味着 logrotate 已经发生:关闭文件并以相同的名称重新打开它。

            快乐记录。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-09-30
              • 2013-06-06
              • 2020-08-06
              • 2015-01-16
              • 1970-01-01
              • 2011-07-10
              • 1970-01-01
              • 2020-07-17
              相关资源
              最近更新 更多