9 Replies - 690 Views - Last Post: 01 July 2011 - 11:04 AM Rate Topic: -----

#1 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 07:43 PM

Wow, maybe I am over thinking this but I have been beating my brains on the keyboard trying to figure this out. I need to reverse lines of text I have in a buffer that are terminated with a LF or LF CR. Example:
abcde
12345


Should read:
edcba
54321



Here is some code attempts of what I am working on:
char* revLine(char *str){

   int c, i, j;
   char revStr[strlen(str)];
   
   j = strlen(str);
   
   for(i = 0;i < j;i++){
       c = str[i];
       revStr[j-1] = c;
       if(i==0) str[j]='\n';
       j--;
   }
   strcpy(str,revStr);
   return str;
}



Nth attempt:
char* revLine(char *str){
   for( i = 0, j = strlen(str) - 1; i < j; i++, j-- ){
       c = str[i];
       str[i] = str[j];
       str[j] = c;
       
       // concatenate str to revStr if a new line is found
       if(c == 13 || c == 10){
           // Windows text files fix
           if(str[i+1] == '\r') str++;
           strcat(revStr,str);
       }


   }
   return str;



I believe I am thoroughly fried at looking at this. I have spent 4 hours today and 5 hours last night trying to get this to work.

This post has been edited by roachmmflhyr: 30 June 2011 - 07:43 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Reversing individual lines terminated with \n in text file

#2 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1852
  • View blog
  • Posts: 6,664
  • Joined: 19-February 09

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 08:04 PM

The new array will need to be the length of the string + 1 for the null terminator ('\0').

04	   char revStr[strlen(str)];




To find the your string terminators you could use strcspn.

Then you can use a for loop. After that you need to add a null ('\0')
Was This Post Helpful? 0
  • +
  • -

#3 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 08:23 PM

Well here is another attempt I thought for sure would work but unfortunately an empty string is returned:
char* revLine(char *str){ 

    int i, j;
    j = strlen(str);
    char revStr[j+1];
    
    revStr[j+1];
    
    for(i = 0;i < j+1;i++){
        if(i == 0){
            revStr[j+1] = '\0';
        }
        revStr[j]=j;
        j--;
    }
    strcpy(str,revStr);
    return str;
}


Was This Post Helpful? 0
  • +
  • -

#4 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1852
  • View blog
  • Posts: 6,664
  • Joined: 19-February 09

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 08:47 PM

The null character is used to terminate C strings, so putting the null '\0' at the beginning will always return an empty string. You should put it at the end of the string.

10	        if(i == 0){
11	            revStr[j+1] = '\0';
12	        }



If a string contains "hello" the string length is 5, the last position is 4 ([0][1][2][3][4]).
So have one variable in the for loop that initially points to this last character and decrements on each iteration, and another variable which starts at zero and increments on each iteration.

This post has been edited by #define: 30 June 2011 - 08:48 PM

Was This Post Helpful? 1
  • +
  • -

#5 jimblumberg  Icon User is online

  • member icon

Reputation: 5358
  • View blog
  • Posts: 16,731
  • Joined: 25-December 09

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 08:53 PM

Is this a C or C++ program?

Does the above code compile without errors or warnings?

This: char revStr[j+1]; as it is only valid in C-99.

In your for loop you should not be changing the value of your sentinel value. The variable j in this case. When you try to reverse the string you need to place the first character into the last character in your revStr. Where are you doing this?

Also line 7 in the above code is not doing anything and should be deleted.

Jim
Was This Post Helpful? 0
  • +
  • -

#6 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 08:58 PM

View Post#define, on 30 June 2011 - 08:47 PM, said:

The null character is used to terminate C strings, so putting the null '\0' at the beginning will always return an empty string. You should put it at the end of the string.

10	        if(i == 0){
11	            revStr[j+1] = '\0';
12	        }



If a string contains "hello" the string length is 5, the last position is 4 ([0][1][2][3][4]).
So have one variable in the for loop that initially points to this last character and decrements on each iteration, and another variable which starts at zero and increments on each iteration.


That is essentially what I thought I was doing with this code:
char* revLine(char *str){ 

    int i, j;
    j = strlen(str);
    char revStr[j+1];
    
    revStr[j+1];
    
    for(i = 0;i < j+1;i++){
        if(i == 0){
            revStr[j+1] = '\0';
        }
        revStr[j]=j;
        j--;
    }
    strcpy(str,revStr);
    return str;
}



I retrieved the length of my str and stored this in j. Then I stored '\0' on the first iteration(e.g. if (i == 0){...}) into revStr[j+1]. Which revStr[j+1] would be the very last element where the '\0' char should go.
Was This Post Helpful? 0
  • +
  • -

#7 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 09:46 PM

I finally got it! Wow that took awhile but I decided to take break for a little while and actually think about what is going on and I finally came up with this solution: (Fully commented for anyone else that may need this and wants to know how it works)

void reverse(char str[]){
   int c, i, j;

   // Loop and reverse entire string
   for( i = 0, j = strlen(str) - 1; i < j; i++, j-- ){
   c = str[i];
   str[i] = str[j];
   str[j] = c;
   }
}

char* revLine(char *str){
    // Delimiter to tokenize string
    char delims[] = "\n";
    // Create new char array +1 for null terminator
    char revStr[strlen(str)+1];
    char *result = NULL;
    // Search string for \n
    result = strtok( str, delims );
    while(result != NULL){
        // Reverse string up to first \n
        reverse(result);
        // Concatenate reversed string to empty string revStr
        strcat(revStr,result);
        // Concatenate \n to specify a new line
        strcat(revStr,"\n");
        // Find next token in string
        result = strtok( NULL, delims );
    }
    // Copy results into str and return
    strcpy(str,revStr);
    return str;
}



BTW this will only work with lines terminated with '\n'. These are usually text files created on *nix systems. If you are parsing a text file from a Windows machine change your delimiter and string concatenate to
char delims[] = "\n\r";
strcat(revStr,"\n\r");
to include the carriage return in your line.
Was This Post Helpful? 0
  • +
  • -

#8 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Re: Reversing individual lines terminated with \n in text file

Posted 30 June 2011 - 11:29 PM

Hmm.... with a 20000 line text file it reverses the first time fine but when I try to reverse the second time it fails. Why is this?
Was This Post Helpful? 0
  • +
  • -

#9 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6246
  • View blog
  • Posts: 24,014
  • Joined: 23-August 08

Re: Reversing individual lines terminated with \n in text file

Posted 01 July 2011 - 05:45 AM

Here's a working example:

char *rev(char *str)
{
    size_t len = strlen(str);

    // Pointer to the last actual character, leaving the                        
    // \n and \0 where they need to be, at the end.                             
    char *pEnd = &str[len - 2];

    // Pointer to the start of the string.                                      
    char *pStart = &str[0];

    // While the location of the pointer to the end of the string               
    // exceeds the location of the pointer to the start, we walk the            
    // string copying the start character into a temp variable,                 
    // setting the start character to the end character, and                    
    // then setting the end character to the saved temp variable.               
    while (pEnd > pStart)
    {
        // Get character currently at the start                                 
        char temp = *pStart;

        // Set character at start to character at end                           
        // and move start to the next character                                 
        *pStart++ = *pEnd;

        // Set character at end to temporary char from start                    
        // and move backward a character                                        
        *pEnd-- = temp;
    }
    return str;
}

int main()
{
    FILE *fp = fopen("revtest.txt", "r");
    if (fp)
    {
        char buf[BUFSIZ] = {0};
        while(fgets(buf, sizeof(buf), fp) != NULL)
        {
            printf("Before: %s", buf);
            printf("After: %s", rev(buf));
        }
        fclose(fp);
    }
    return 0;
}


Was This Post Helpful? 1
  • +
  • -

#10 roachmmflhyr  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 31
  • Joined: 29-January 11

Re: Reversing individual lines terminated with \n in text file

Posted 01 July 2011 - 11:04 AM

View PostJackOfAllTrades, on 01 July 2011 - 05:45 AM, said:

Here's a working example:

char *rev(char *str)
{
    size_t len = strlen(str);

    // Pointer to the last actual character, leaving the                        
    // \n and \0 where they need to be, at the end.                             
    char *pEnd = &str[len - 2];

    // Pointer to the start of the string.                                      
    char *pStart = &str[0];

    // While the location of the pointer to the end of the string               
    // exceeds the location of the pointer to the start, we walk the            
    // string copying the start character into a temp variable,                 
    // setting the start character to the end character, and                    
    // then setting the end character to the saved temp variable.               
    while (pEnd > pStart)
    {
        // Get character currently at the start                                 
        char temp = *pStart;

        // Set character at start to character at end                           
        // and move start to the next character                                 
        *pStart++ = *pEnd;

        // Set character at end to temporary char from start                    
        // and move backward a character                                        
        *pEnd-- = temp;
    }
    return str;
}

int main()
{
    FILE *fp = fopen("revtest.txt", "r");
    if (fp)
    {
        char buf[BUFSIZ] = {0};
        while(fgets(buf, sizeof(buf), fp) != NULL)
        {
            printf("Before: %s", buf);
            printf("After: %s", rev(buf));
        }
        fclose(fp);
    }
    return 0;
}



Very nice solution. Thanks.

I still wonder why mine runs fine once and the second pass fails....
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1