Someonewhohaveacat
Someonewhohaveacat

Reputation: 83

Replace CR LF with LF in C

I have to write a C program that somewhat function like dos2unix. Which replace all CR LF with only LF (DOS-Format to Unix-Format). So this is my way of approach. Everytime I read a line, I search for the end of the data by lookng for \0and then check if the following are \r\n. If yes replace with \nonly. But it seems do not work and the line CRLF here never been printed out once.

char data[255]; // save the data from in.txt
char *checker;
pf = fopen("in.txt", "r");
pf2 = fopen("out.txt", "w");
while (feof(pf) == 0)
{
    fgets(data, 255, pf);       // Read input data
    checker = data;
    while (checker != "\0") // Search for a new line
    {
        if (checker == "\r\n") // Check if this is CR LF
        {
            printf("CRLF here");
            checker = "\n";   // replace with LF
        }
        checker++;
    }
    fputs(data, pf2);       // Write to output data
}

Upvotes: 1

Views: 4993

Answers (1)

zwol
zwol

Reputation: 140649

You have a whole bunch of bugs:

  • You may need to open in.txt in "rb" mode, instead of "r" mode, to see the CRLF line endings in the first place.
  • You may need to open out.txt in "wb" mode, instead of "w" mode, to prevent the C library from undoing your work.
  • You cannot compare string literals with ==. You can compare one character of a string to a character literal with ==, but that's not what you're doing, and it only works for single characters; a CRLF sequence is two characters.
  • You cannot replace a two-character sequence with a one-character sequence within a mutable C string by simple assignment. You would need to use memmove to shift all the characters after the replacement down one.
  • You do not properly handle very long lines.
  • You do not check whether fopen succeeded, or for any other I/O errors.
  • while (!feof (fp)) is always wrong.

A better way to write this program is with a main loop that goes character by character, something like

  int c;
  while ((c = getc(ifp)) != EOF) {
    if (c == '\r') {
      putc('\n', ofp);
      c = getc(ifp);
      if (c == EOF) break;
      if (c == '\n') continue;
    }
    putc(c, ofp);
  }

This converts both \r\n and bare \r to \n, because bare \r is very rare nowadays, but was used as the line terminator on some historical OSes (notably classic MacOS), and there isn't anything else sensible to do with it.

It's important that c be an int, not a char, so that it can hold EOF as well as all possible characters.

Upvotes: 5

Related Questions