Имя ротации файла журнала - PullRequest
0 голосов
/ 16 июля 2009

Я написал эту простую программу на 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

Ответы [ 6 ]

1 голос
/ 16 июля 2009

Ваш код ... немного грязный. Вам нужно разбить ваш алгоритм на этапы, каждый из которых должен быть прост в выполнении:

  • Проверьте, заканчивается ли имя цифрой. Если это так, запишите, где начался номер, и извлеките номер. Если это не так, действуйте так, как будто это закончилось 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);
}
0 голосов
/ 29 марта 2018

Есть ли библиотека std, которая делает это?

я бы использовал logrotate (https://linux.die.net/man/8/logrotate) вместо того, чтобы заново изобретать колесо.

вам просто нужно установить обработчик sigusr1, который закроет и снова откроет файл журнала. logrotate будет вращать / переименовывать / сжимать файл для вас.

Если вы не любите использовать обработчик sigusr1 или использовали его для чего-то другого, тогда вы можете реализовать проверку существования файла внутри процедуры log. Если файл журнала исчез, что означает, что произошло logrotate: закройте файл и снова откройте его с тем же именем.

счастливого входа.

0 голосов
/ 13 августа 2009

Я бы посмотрел на конец строки, и если это число, я бы продолжал возвращаться, пока не достигну нечислового символа, добавив их в строку и сохранив позицию (p).

  • 'filename' => ''
  • 'filename_9' => '9'
  • 'filename-3786' => '3786'

Затем я бы преобразовал его в число n, если оно пустое, я бы принял ноль.

Я бы взял исходную строку до p, преобразовал n + 1 в строку и конкатенировал ее.

  • 'filename' => 'filename2'
  • 'filename_9' => 'filename_10'
  • 'filename-3786' => 'filename-3787'

Вы также можете искать разделители для p-го символа, например '', '_', '-', и удалять их, а затем всегда добавлять фиксированный разделитель, такой как _.

0 голосов
/ 16 июля 2009

Вы действительно хотите также повернуть порядковый номер?.

Я бы посоветовал не делать этого и продолжать увеличивать постоянное имя файла с порядковым номером, это поможет узнать, сколько файлов было открыто.

Параллельно вы можете поддерживать массив имен файлов, вращать начальный и конечный индексы и увеличивать начальный индекс каждый раз, когда вы открываете новый файл. когда массив заполнится, просто удалите файл в конце индекса и продолжайте.

0 голосов
/ 16 июля 2009

Вам не нужна вся эта активность strtok для постоянной строки имени файла.

  • Либо сравните постоянную часть с strncmp для подтверждения, либо используйте sscanf
  • Вытащите номер файла целое число с atoi или sscanf %d
  • Выполните сравнение и измените целое число (с операциями модуля и т. Д.)
  • Создать новое имя с помощью sprintf, используя новое целое число

И, если вам не нужно фактически генерировать следующее имя файла из ранее переданного, как предлагает ваша функция, просто сохраните постоянную строку и вращающееся целое число, которое используется с sprintf для генерации следующего имени файла.
Я понимаю, что это может использоваться не во всех случаях.

0 голосов
/ 16 июля 2009

используйте, например,

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...