日志文件轮换名称

时间:2009-07-16 09:37:33

标签: c string

我编写了这个简单的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(这个工作正常) - 如果是 - 提取数字,递增它并附加到新字符串。

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

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

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

   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浏览器

6 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

使用例如

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

答案 2 :(得分:0)

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

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

并且,如果您不需要实际生成以前传递的下一个文件名,就像您的函数建议的那样,只需保留一个常量字符串和一个与sprintf一起使用的旋转整数来生成下一个文件名。
我知道在所有情况下都可能无法使用。

答案 3 :(得分:0)

你真的想要旋转序列号吗?。

我建议不要这样做并继续使用序列号增加文件名,这将有助于了解已打开的文件数量。

Parallaly你可以维护文件名数组,并在每次打开新文件时旋转start-index和end-index并增加start-index。当数组被填充时,只需删除end-index处的文件并继续。

答案 4 :(得分:0)

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

  • 'filename'=&gt; ''
  • 'filename_9'=&gt; '9'
  • 'filename-3786'=&gt; '3786'

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

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

  • 'filename'=&gt; '文件名2'
  • 'filename_9'=&gt; 'filename_10'
  • 'filename-3786'=&gt; '文件名-3787'

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

答案 5 :(得分:0)

  

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

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

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

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

快乐的伐木。