Reputation: 3775
I want to make a very simple console application that replaces the Unix command wc -c
. For this, I need simply to count the bytes into the file and output them in the console.
If my application is not provided with arguments, it reads them from the standard input (this part I've already made working). However, if I decide to supply more arguments (valid and existing file names), I should count each one of them their bytes.
So far so good. Here is the code
const int __OPEN_ERROR = 48;
int main(int argc, char* argv[]) {
if(argc == 1) {
char buf[3];
int count = 0, lines = 0;
while(read(0, buf, 1) != 0) {
count++;
if(buf[0] == '\n')
lines++;
}
printf("Count:%d\n", count);
printf("Lines:%d\n", lines);
}
else {
int fd, bytes = 0;
char buf[3];
for (int arg = 1; arg <= argc; arg++) {
if ((fd = open(argv[arg], O_RDONLY) < 0)) {
exit(__OPEN_ERROR);
}
while (read(fd, buf, 1) != 0) { // <-- this here leads to infinite loop.
printf("%s", buf);
bytes++;
}
printf("%d %s", bytes, argv[arg]);
}
}
exit(0);
}
Please don't mind how badly this code is written, this is my first day exploring C, for now everything I want is working solution.
Notice how both reads are same but latter one falls into infinite loop, for a reason I cannot understand. And yes, opening the file succeeds.
Upvotes: 0
Views: 1369
Reputation: 36391
Your loops are wrong, should be:
char buf;
...
while (read(fd, buf, 1) == 1) {
printf("%c", buf);
bytes++;
}
read
lets you read bytes from file descriptor. The given number say n
is a request, this means that read
reads at most n
bytes, and the returned value is exactly the number of bytes effectively read. As you want to read 1 byte, then test if it read 1 byte. Second, as you read bytes (or char) one by one, then the result is one char and should be print as. %c
tells printf to print the value as a char (%s
is to print C-strings).
The other error is the control of arg loop, should be:
for (int arg = 1; arg < argc; arg++) // strict test...arg from 0 to argc-1 (included) or argc (excluded)
You must also reset the byte count to 0 on each arg looping, and close each unused file, thus:
for (int arg = 1; arg < argc; arg++) {
char buf;
int bytes = 0;
int fd;
if ((fd = open(argv[arg], O_RDONLY) < 0)) {
exit(__OPEN_ERROR);
}
while (read(fd, buf, 1) == 1) {
printf("%c", buf); // optionnal, counting may not print...
bytes++;
}
close(fd);
printf("%d %s", bytes, argv[arg]);
}
Upvotes: 1