views:

176

answers:

5
I have written this simple C program that changes the rotation file name.
Eg: 
For A_B_C_1
Need to rotate it to 
A_B_C_2
and 
if A_B_C 
need to rotate it to A_B_C_1

Problem is the strncat is not working as expectedly. It is giving me output like:

A_B_C_1 (Works fine for single instance)
A_B_C_2
A_B_C_23
A_B_C_2324

Logic used is simple:get the last digit in the string if it exists.
If it does not simply append _1 (This one is working fine)
If it does - extract the number, increment it and append to the new string.

Is there some std library that does this?

Gives error on calling this method in a loop / multiple times....

I am not able to debug the cause..... Need help on this,Please guide.

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

Seems to be a problem on line: strncpy(sNewFileName,sTmpFile, (newLen-oneLen));

Feedback: The code formatter is not working correctly on this site for Chrome browser

A: 

Your code is ... A bit messy. You need to split your algorithm into steps, each of which should be easy to perforM:

  • Check if the name ends in a number. If it does, record where the number started, and extract the number. If it didn't, act as if it ended with 0.
  • Increment the number.
  • Create a new string by concatenating the prefix and the number (as a string).

Please note that these algorithms are racy, generally it's a better idea to let the standard library generate a unique name for you.

Here's one solution:

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);
}
unwind
A: 

use e.g.

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;
}
nos
A: 

You do not need all that strtok activity for a constant filename string.

  • Either compare the constant part with a strncmp to confirm it, or use a sscanf
  • Pull out the file number integer with an atoi or a sscanf %d
  • Do your comparisons and change the integer (with modulus operations, etc)
  • Generate the new name with sprintf using the new integer


And, if you do not need to actually generate the next file name from the previously passed as your function suggests, simply keep a constant string and an rotating integer which is used with the sprintf to generate the next file name.
I understand that may not be usable in all cases.

nik
A: 

Do you really want to rotate the sequence number also?.

I would suggest not to do that and keep incrementing your file name constant with sequence number it will help to know how many files have been opened.

Parallaly you can maintain array of files-names, and rotate the start-index and end-index and increment the start-index every time you open new file. when array gets filled just remove the file at end-index and go on.

harishvk27
A: 

I would look at the end of the string, and if it's a number, I'd keep going back until I reach a non-numeric character, adding these to a string, and keeping the position (p).

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

I'd then convert it to a number n, if it's empty, I'd assume a zero.

I would take the original string up to p, convert n+1 to a string and concatenate it.

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

You could also look for separators at the p-th character like ' ', '_', '-', and remove them, then always add a fixed separator like _.

Osama ALASSIRY