Thread: Char array and functions

  1. #1
    Registered User acolussi's Avatar
    Join Date
    Jun 2012
    Location
    Udine - UD - Italy
    Posts
    6

    Char array and functions

    Hi there,
    I have an issue on a simple program I'm trying to complete. The problem I have is on the "reverse" function, which probably has some error in its body. I'm quite beginner and so I probably missed something in char arrays. If you could help me with this program, I would really appreciate. Thanks in advance and please find here following the C code:

    Code:
    /* Write a function reverse(s) that reverses the character string s. Use it to
    write a program that reverses its input a line at a time. */
    
    #include <stdio.h>
    
    #define MAXLENGTH 101 /* maximum input line length */
    
    int getline(char line[], int limit);
    void reverse(char d[], char s[], int len);
    
    
    int main(void)
    {
        int len;
        char rev[MAXLENGTH];
        char line[MAXLENGTH];
    
        while ((len = getline(line, MAXLENGTH)) > 0)
        {
            reverse(rev,line,len);
            printf("\nLenght of this line is: %d\n",len);
            printf("Original line = %s\nReverse line = %s",line, rev);
            printf("\n\n");
        }
        return 0;
    }
    
    void reverse(char d[], char s[], int len)
    {
        int i,j;
        j = len;
        for (j=0; j<len; j++)
        {
            d[j]=0;
        }
    
        for (i=0; i<len; i++)
        {
            d[j] = s[i];
            --j;
            printf("s[%d]=%c\td[%d]=%c\n",i,s[i],j,d[j]);
        }
        return 0;
    }
    
    int getline(char line[], int limit)
    {
        int c,i;
        for (i=0; i<=limit-1 && (c=getchar())!=EOF && c!='\n'; i++)
            line[i]=c;
        line[i]='\0';
        return i;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You have an off by one error concerning j. Use your debugger to observe it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You will probably get more help if you explain what exactly is wrong with your program. Just saying you have a problem, doesn't tell us what to look for.

    Having said that you have at least two problems with your reverse function. First why are you decrementing j before your printf() statement? Second, before the second loop starts, what is the value of j? This value seems to be 1 off. After you fix the first problem look closely at your output:
    This is a test.
    s[0]=T d[15]=T
    s[1]=h d[14]=h
    s[2]=i d[13]=i
    s[3]=s d[12]=s
    s[4]= d[11]=
    s[5]=i d[10]=i
    s[6]=s d[9]=s
    s[7]= d[8]=
    s[8]=a d[7]=a
    s[9]= d[6]=
    s[10]=t d[5]=t
    s[11]=e d[4]=e
    s[12]=s d[3]=s
    s[13]=t d[2]=t
    s[14]=. d[1]=.

    Lenght of this line is: 15
    Original line = This is a test.
    Reverse line =
    Look closely at your indexes.

    Jim

  4. #4
    Registered User acolussi's Avatar
    Join Date
    Jun 2012
    Location
    Udine - UD - Italy
    Posts
    6
    laserlight, thanks sio much for the quick reply. I'm using CodeBlocks for testing this exercises and unfortunately I can't use the debugger, but I'm used to start the build and check warnings and errors on it to find out what to correct on the program. My problem is that I cannot have back the correct reverse-destination string (or better char array[]) d[], which it's the purpose of the function. I just can't understand why the s[i] cannot be copied in d[j]... maybe I'm missing some initialization of d[j], for this I've added a for loop to put at 0 each value of the d[j] array... but probably this is not the solution.
    What do you mean with "you have an off by one error"? I'm sorry but I'm missing some English technical words.

  5. #5
    Registered User acolussi's Avatar
    Join Date
    Jun 2012
    Location
    Udine - UD - Italy
    Posts
    6
    Jim, hi. Thanks also to your kind reply. Maybe I understand what laserlight meant with "an off by one" on j, since j it's not aligned correctly with i and so I probably have to define (j = len - 1) to match the correct array. To reply to your first question, I've used the (printf("s[%d]=%c\td[%d]=%c\n",i,s[i],j,d[j]) just as a debug trick, so I could understand what the output of reverse() is inside reverse() itself. I'm decrementing j-- since I want an opposite char array d[j] with the same length of s[i] but reversed. So I want to copy each char saved in s[i] from head-to-tail to d[j] from tail-to-head.

    Your output is really different from the one I got with CodeBlocks IDE... instead I receive the same empty "Reverse line =" result, as the main() couldn't get the d[] from the reverse() function... I'll try to do some test tonight.

    Many thanks for your help

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by acolussi
    What do you mean with "you have an off by one error"?
    This means that your error is due to doing something that is very close to correct, but wrong because, for example, you started copying to a position that is adjacent to where you actually should have started.

    Consider this code snippet:
    Code:
    j = len;
    for (j=0; j<len; j++)
    {
        d[j]=0;
    }
    Your idea is to set as many character in d as there are characters in s to be null characters. (Note that '\0' would be more descriptive than plain 0 here.) This is unnecessary, but okay. The problem though, is that you don't set d[len] to be a null character, but this is the most important reason for setting characters in d to be null characters: you want to make sure that the string represented by d is the same length as the string represented by s.

    Next, after the loop, j has the value of len. Then we examine this statement:
    Code:
    d[j] = s[i];
    So, what you are doing is setting d[len] to s[0]. But d[len] is supposed to be a null character! Rather, you should have decremented j first, and thus set d[len-1] to s[0].
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    But since you are using that printf() for debugging wouldn't it make sense to actually print the current value of j not the decremented value? By decrementing the value of j before you do the printf() you are printing a value that you have not copied from the original string. The printout I supplied is with the decrement after the printf() it still has the off by one error.

    Also I am also using Code::Blocks with gcc version 4.7.0.

    Jim

  8. #8
    Registered User acolussi's Avatar
    Join Date
    Jun 2012
    Location
    Udine - UD - Italy
    Posts
    6
    laserlight and jim, thank you very much for your suggestions.
    Infact I forgot to close the d[j] string using the '\0' char, now I know that it's essential to close it with that special char, like I did in getline of s[i]. Then the error jim said was true, I was decreasing j before the printf and so I get the wrong output. Inserting the '\0' let me have the correct variable from reverse() function.
    Following last revision of the code which works fine.

    Just 1 last question about functions, since I'm really confused on the use of local variables (automatic variables) which are defined inside the round brackets... A function returns a value, or maybe void and so do not return anything and only executing its body. But, in case of reverse() I passed it, in the main body, 2 values defined inside main(), while I've only define rev variable to get the d[] from the reverse() function. I thought that you could only pass values to the function() in main and expect for a returned value, but in case of void functions I can see that it's possible to define multiple variable, some for passing values from main() and some variables to be used in main() after the function has been executed... It's quite difficult to explain by words, but I hope you could have understood what I mean.
    Thanks in advance for all your help and I hope to speak with you again later.

    This is the program code modified and which works really fine, thanks to your suggestions:

    Code:
    /* Write a function reverse(s) that reverses the character string s. Use it to
    write a program that reverses its input a line at a time. */
    
    #include <stdio.h>
    
    #define MAXLENGTH 101 /* maximum input line length */
    
    int getline(char line[], int limit);
    void reverse(char d[], char s[], int len);
    
    
    int main(void)
    {
        int len;
        char rev[MAXLENGTH];
        char line[MAXLENGTH];
    
        while ((len = getline(line, MAXLENGTH)) > 0)
        {
            reverse(rev,line,len);
            printf("\nLenght of this line is: %d\n",len);
            printf("Original line = %s\nReverse line = %s",line, rev);
            printf("\n\n");
        }
        return 0;
    }
    
    void reverse(char d[], char s[], int len)
    {
        int i,j;
        j = len-1;
        for (i=0; i<len; i++)
        {
            d[j] = s[i];
            printf("s[%d]=%c\td[%d]=%c\n",i,s[i],j,d[j]);
            --j;
        }
        j = len;
        d[j]='\0';
        return 0;
    }
    
    int getline(char line[], int limit)
    {
        int c,i;
        for (i=0; i<=limit-1 && (c=getchar())!=EOF && c!='\n'; i++)
            line[i]=c;
        line[i]='\0';
        return i;
    }

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You may want to review how functions work. Here are two links: Functions I and Functions II.

    Since you are passing the address of these arrays any changes made to these variables will be reflected in the variables in the calling function. However your length variable is being passed by value so if you make changes to that variable in the function the changes will be lost when you return to the calling function.


    Jim
    Last edited by jimblumberg; 07-17-2012 at 05:52 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. uincode char array to array<unsigned char,1>^
    By ripspinner in forum Windows Programming
    Replies: 5
    Last Post: 12-14-2009, 05:41 PM
  2. Replies: 3
    Last Post: 11-17-2008, 12:36 PM
  3. signed char array to unsign char array.
    By beon in forum C Programming
    Replies: 5
    Last Post: 12-14-2006, 07:19 PM
  4. functions gets into char array
    By bobthesled in forum C Programming
    Replies: 8
    Last Post: 04-27-2005, 09:16 AM
  5. Read File To Char Array with Null char init
    By MicroFiend in forum Windows Programming
    Replies: 1
    Last Post: 10-28-2003, 06:18 PM