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.
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.
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;
}
}
}