cif-statementwhile-loopc-stringsgetchar

get string in input and print it folded in C


I'm trying to write a program which gets one or more input lines, and if one line is too long, it gets folded at a maximum number of chars. My approach would be to write the input chars in a first array, of a given length. If Maximum length is reached or '\n' as input, i copy the content in a bigger array which will be the final string to print and get the second line in input. Problem is: it doesn't work and I can't figure out why. Thanks for the help

#include <stdio.h>
#define MAXCOL 10
#define FINAL_LENGTH 300
char line[MAXCOL];
char final_string[FINAL_LENGTH];
extern int fnlstr_pos = 0;
int main() 
{
    int pos, c;
    pos = 0;
    while(c=getchar() != EOF)
    {
        line[pos] = c;

        if (pos + 1 >= MAXCOL || c == '\n'){
            to_printandi(pos);
            pos = 0;
        }
        ++pos;

    }
    printf("%s", final_string);


}


to_printandi(pos)
int pos;
{
    int i;
    for(i = 0; i <= pos; ++i){
        final_string[fnlstr_pos] = line[i]; 
        ++fnlstr_pos;
    }
    if (final_string[fnlstr_pos] != '\n'){
        final_string[++fnlstr_pos] = '\n';
    }
    ++fnlstr_pos;
}


Solution

  • There are several problems in the code. Others have already pointed out the bug in the getchar() line.

    More variables and more functions and more code only twist one around in knots. If you take some time to think about what you want to achieve, go slowly, you can get your results with much less effort. Less code full of helpful comments, make for better programs.

    EDIT
    Looking at code with fresh eyes, I realised that the two lines explicitly setting the 'trailing' byte to '\0' were write 0 overtop of bytes already initialised to 0. Have commented out those two lines as they are superfluous.

    #include <stdio.h>
    
    int main () {
        char buf[ 1024 ] = { 0 }; // buffer initialised
        int ch, cnt = 0, ccnt = 0; // input char and counters
    
        while( ( ch = getchar() ) != EOF ) { // get a character
            ccnt++; // count this character
            buf[ cnt++ ] = (char)ch; // assign this character
            // buf[ cnt ] = '\0'; // string always terminated
            if( buf[ cnt-1 ] == '\n' ) // user supplied LF?
                ccnt = 0; // reset the counter (for width)
            else
            if( ccnt == 10 ) { // reached max output width?
                buf[ cnt++ ] = '\n'; // inject a LF
                // buf[ cnt ] = '\0'; // string always terminated
                ccnt = 0; // reset the counter (for width)
            }
        }
        puts( buf ); // output the whole shebang
    
        return 0;
    }
    
    0123456789abcdefghijklmnop
    qrs
    tuv
    wxyz
    ^D // end of input
    0123456789
    abcdefghij
    klmnop
    qrs
    tuv
    wxyz
    

    Like the OP code, this does not test for overrunning the buffer. An easy addition left as an exercise for the reader.


    EDIT2:
    Then again, why have a buffer to overrun?

    #include <stdio.h>
    
    void main( void ) {
        for( int ch, n = 0; ( ch = getchar() ) !=  EOF; /**/ )
            if( (n = putchar( ch ) == '\n' ? 0 : n + 1) == 10 )
                putchar( '\n' ), n = 0;
    }