Reputation: 13
I'm implementing a function for a homework assignment. The function definition is:
int processchar(int fdin, int fdout, char inchar, char *outstr);
The processchar function reads from file descriptor fdin until end-of-file and writes to file descriptor fdout, translating any occurrence of the character inchar into the string outstr. If unsuccessful, processchar returns -1 and sets errno.
My current code is as follows:
#define CHUNK 256
int processchar(int fdin, int fdout, char inchar, char *outstr){
int j = 0, n = CHUNK, np = CHUNK, r;
char *buf, *tmp_buf, *fin_buf, *k, *rbuf, *rrbuf;
if((buf = malloc(sizeof(char) * n )) == NULL)
return 1;
while((r = read(fdin, buf, CHUNK))){
if( r == -1 )
return -1;
n += r;
if(np - n < CHUNK) {
np *= 2;
rbuf = malloc(np * sizeof(char));
memcpy(rbuf, buf, n * sizeof(char));
free(buf);
buf = rbuf;
}
}
fprintf(stderr, "buf is %s\n",
for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
if(*tmp_buf == inchar)
j++;
}
if((fin_buf = malloc((sizeof(char) * n) + (sizeof(char) * j * strlen(outstr) + 1)) == NULL))
return 1;
rrbuf = fin_buf;
for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
if(*tmp_buf == inchar){
fprintf(stderr, "got another j\n");
k = outstr;
while(*fin_buf++ = *k++);
} else {
fprintf(stderr, "swing n a miss\n");
*fin_buf++ = *tmp_buf;
}
}
write(fdout, rrbuf, strlen(rrbuf));
return 0;
}
From the testing that I've done, it seems like the section:
tmp_buf < buf + n
in the for loop definition is not having the intended consequence. The function is called by a ring of processes, each piping their stdout to the stdin of the next (in the use case, fdin
is STDIN_FILENO
and fdout
is STDOUT_FILENO
). Specifically, the fprintf statements in the second for loop do not print as many times I expect them to (my expectation is that they would print once for each character printed by the fprintf
of buf
).
I've been staring at this function for a long time now and would appreciate any direction or opinion that you all would be able to provide. I've utilized a number of threads on this site before, and in fact have pulled directly from this one for the determination of j
in the above code.
(Note: this assignemnt is an aside to learning to implement rings in a book on unix systems programming)
Upvotes: 1
Views: 117
Reputation: 50328
I think you may be overthinking this. A simple implementation that should satisfy the assignment would be:
#define CHUNK 256
int processchar ( int fdin, int fdout, char inchar, char *outstr ) {
char buf[CHUNK];
int r, outlen = strlen( outstr );
while ( (r = read( fdin, buf, CHUNK )) > 0 ) {
int i;
for ( i = 0; i < r; i++ ) {
if ( buf[i] == inchar ) {
if ( write( fdout, outstr, outlen ) < 0 ) return -1;
} else {
if ( write( fdout, &buf[i], 1 ) < 0 ) return -1;
}
}
}
return r;
}
You can slightly optimize that by collecting consecutive non-matching chars and writing them in a single write()
call; I'll leave that as an exercise.
(Also, I'm not checking for partial writes or for EINTR
. In general, this is IMO something best done in wrapper functions around read()
and write()
, not in high-level calling code.)
Upvotes: 2