Home > Net >  How can I merge 2 empty lines into one? Like cat -s
How can I merge 2 empty lines into one? Like cat -s

Time:07-03

how can I merge 2 empty lines into one? Like cat -s

#include <stdio.h>
#include <stdlib.h>

int main() {
    int c;
  
    FILE *file = fopen("2.txt", "r");
    while ((c = getc(file)) != EOF) {
        putc(c, stdout);             
    }
    fclose(file);
    return 0;
} 

CodePudding user response:

Here is a modified version that implements cat -s:

#include <stdio.h>

int main() {
    int c, last_c = '\n', has_empty = 0;

    FILE *file = fopen("2.txt", "r");
    if (file != NULL) {
        while ((c = getc(file)) != EOF) {
            if (last_c == '\n' && c == '\n') {
                if (has_empty) {
                    //has_empty = 0;
                    continue;
                }
                has_empty = 1;
            } else {
                has_empty = 0;
            }
            putchar(c);
            last_c = c;
        }
        fclose(file);
    }
    return 0;
}

If you want to only collapse 2 empty lines into one, uncomment the //has_empty = 0; statement.

CodePudding user response:

Consider using fgets() instead, keep a copy of the last line and discard any empty line if the stored line is also empty.

But if you need to use getc(), we run in a bit of trouble because of the way the different OSs handle new lines. Windows uses \r\n but Linux and MacOS use \n.


Linux or MacOS

For Linux or MacOS, you simply need to keep a copy of the last character and discard any newline if the last character is also a newline :

#include <stdio.h>
#include <stdlib.h>

int main() {
    int c;
    int last_c = '\0';

    FILE *file = fopen("2.txt","r");
    while ((c = getc(file)) != EOF)
    {
        if(last_c == '\n' && c == '\n')
            continue;
        putc(c, stdout);
        last_c = c;        
    }
    fclose(file);
    return 0;
}

Windows

For Windows it can be a bit trickier. First you can have invalid new lines with single \r or \n. But most importantly we need to check two characters to make sure it is a new line. We can check for a newline and set a flag, then discard any newline sequence. We need to look ahead if we encountered a newline, and determinate if it is a single \r or if it is followed by a \n. Then if it is not a newline sequence we need to print the \r we skipped.

A simple implementation would look like this :

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main() {
    int c;
    int last_c = '\0';
    bool is_newline = 0;

    FILE *file = fopen("2.txt","r");
    while ((c = getc(file)) != EOF)
    {
        if(is_newline)
        {
            if(c == '\n' && last_c == '\r' || c == '\r')
            {
                last_c = c;
                continue;
            }
            else
            {
                if(last_c == '\r')
                    putc(c, stdout); //Print the '\r' we skipped
                is_newline = false;
            }
        }
            
        putc(c, stdout);
        if(c == '\n' && last_c == '\r')
            is_newline = true;
        last_c = c;        
    }
    fclose(file);
    return 0;
}

This code will let the \n or \r that are alone pass through without touching them, but will delete newlines that repeat

  •  Tags:  
  • c
  • Related