Skip to main content
Code Review

Return to Answer

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

5gon12eder 5gon12eder is right about the missing header for system and many implementations claiming the symbol getline missing header for system and many implementations claiming the symbol getline.
Just want to add that if the implementation defining getline interferes with you defining it however you want, it's non-conforming, for whatever that's worth.

5gon12eder is right about the missing header for system and many implementations claiming the symbol getline.
Just want to add that if the implementation defining getline interferes with you defining it however you want, it's non-conforming, for whatever that's worth.

5gon12eder is right about the missing header for system and many implementations claiming the symbol getline.
Just want to add that if the implementation defining getline interferes with you defining it however you want, it's non-conforming, for whatever that's worth.

added 20 characters in body
Source Link
Deduplicator
  • 19.6k
  • 1
  • 32
  • 65

One could go byte-at-a-time byte-at-a-time(just drop getline and use getchar / putchar directly), even though that's incredibly inefficient.
There are also disadvantages to going line-at-a-time line-at-a-time(using fgets, gets is always an error): Lines can be too long for your buffer (and simply growing the buffer is no good), or too short for efficiency (degenerates to byte-at-a-time) and you don't need the whole line anyway.
The optimal unit of work is block-at-a-timeblock-at-a-time (using fread, fwrite, and reasonably-sized buffers (powers of two)). Beside being more efficient (single-pass, aside from newline-transformation if neccessary on the implementation), it also handles embedded 0-bytes gracefully.

One could go byte-at-a-time (just drop getline and use getchar / putchar directly), that's incredibly inefficient. There are also disadvantages to going line-at-a-time (using fgets, gets is always an error): Lines can be too long for your buffer (and simply growing the buffer is no good), or too short for efficiency (degenerates to byte-at-a-time) and you don't need the whole line anyway.
The optimal unit of work is block-at-a-time (using fread, fwrite, and reasonably-sized buffers (powers of two)). Beside being more efficient (single-pass, aside from newline-transformation if neccessary on the implementation), it also handles embedded 0-bytes gracefully.

One could go byte-at-a-time(just drop getline and use getchar / putchar directly), even though that's incredibly inefficient.
There are also disadvantages to going line-at-a-time(using fgets, gets is always an error): Lines can be too long for your buffer (and simply growing the buffer is no good), or too short for efficiency (degenerates to byte-at-a-time) and you don't need the whole line anyway.
The optimal unit of work is block-at-a-time (using fread, fwrite, and reasonably-sized buffers (powers of two)). Beside being more efficient (single-pass, aside from newline-transformation if neccessary on the implementation), it also handles embedded 0-bytes gracefully.

Source Link
Deduplicator
  • 19.6k
  • 1
  • 32
  • 65

includes and symbol-names

5gon12eder is right about the missing header for system and many implementations claiming the symbol getline.
Just want to add that if the implementation defining getline interferes with you defining it however you want, it's non-conforming, for whatever that's worth.

Forward-declarations

Don't repeat yourself.
If there are no circular dependencies, omit any forward-declarations and instead define before use.

The above should not be as a vote against using multiple source-files and declarations in included header-files where the projects size merits that.
Though even (or especially) in that case, just like there is only one definition, there should only be a single declaration.

system("pause");

As 5gon12eder said, prune this. If your terminal quits before you see the output, fix how you call your program.

getline

Let's for the moment pretend reading each separate line into a buffer and then transforming that was a good idea, and there was no standard-library function for that.

Well, you should avoid pushing so much into a for-loop's condition, even though it technically works.
Also, slightly changing the loop allows merging the deferred storing of the newline.
I also added a debug-mode precondition-check (#include <assert.h>):

int getline(char line[], int len) {
 assert(line && len > 0);
 int c = 0, i = 0;
 while(c != '\n' && i < len - 1 && (c = getchar()) != EOF)
 line[i++] = c;
 line[i] = 0;
 return i;
}

How big is a tabstop?

People use tabstops of different lengths, the classic 8 being most common, 4 following quite a long step behind, 2 also being seen, and that was nearly everything observed.
So allow the user to override the default.

I/O and Algorithm

Here we get to the heart of it.

One could go byte-at-a-time (just drop getline and use getchar / putchar directly), that's incredibly inefficient. There are also disadvantages to going line-at-a-time (using fgets, gets is always an error): Lines can be too long for your buffer (and simply growing the buffer is no good), or too short for efficiency (degenerates to byte-at-a-time) and you don't need the whole line anyway.
The optimal unit of work is block-at-a-time (using fread, fwrite, and reasonably-sized buffers (powers of two)). Beside being more efficient (single-pass, aside from newline-transformation if neccessary on the implementation), it also handles embedded 0-bytes gracefully.

#include <stdio.h>
#include <stdlib.h>
#define BUFFSIZE (1<<11)
#define MAXTABSTOP 64
int main(int c, char* argv[]) {
 char input[BUFFSIZE];
 char output[BUFFSIZE+MAXTABSTOP];
 int n = 0, i = -1, o = 0, t = 0, tabstop = 8;
 if(c > 1) {
 tabstop = strtol(argv[1], argv, 10);
 if(**argv || tabstop < 1 || tabstop > MAXTABSTOP)
 tabstop = 8;
 }
 for(;;) {
 if(n == ++i && (i = 0) == (n = fread(input, 1, BUFFSIZE, stdin))) {
 fwrite(output, 1, o, stdout);
 return 0;
 }
 switch(input[i]) {
 case '\t':
 if(!t)
 t = tabstop;
 while(t--)
 output[o++] = ' ';
 break;
 case '\n':
 t = -1;
 // FALLTHRU
 default:
 t = (t+1) % tabstop;
 output[o++] = input[i];
 }
 if(o >= BUFFSIZE) {
 fwrite(output, 1, o, stdout);
 o = 0;
 }
 }
}
lang-c

AltStyle によって変換されたページ (->オリジナル) /