views:

343

answers:

5

I have an exercise to do where I need to code in C, commands equivalent to cat and nl using only system calls. The system calls given to us are open(), close(), read() and write().

I've already done the "cat" equivalent and it seems to be running fine, now I need to do the "nl" one but I'm having trouble with how am I going to write line by line.

The idea is to use the less system calls possible.

I know I need to find the '\n' on the buffer and I could do a while to loop through the buffer and find the '\n' position (let's call it X) then write X number of bytes to stdout.

But looping through all chars in the buffer searching for the end of the line doesn't feel right to me, but I have no idea how else could I do this...

IMPORTANT EDIT:
I think some of you are missing the point on my question... I don't need explanations on how to do this, that's not my problem. I know how to do it (or have a very good idea, I just haven't tried it yet). The "problem" is that it doesn't feel right to loop through the buffer, file or whatever, char by char, to find the end of the line (no matter how). I'm not saying this is not the answer or that I'm not allowed to do this and that, I'm just talking about what I think. It just seems an odd way to do this, that's all... But if that's the way, than that's the answer to my question.

I apprecite everyone's help though :)

+1  A: 

A very rough outline:

  • You can replace getc(file) with read(file,&c,1): just write a function which accepts the file as an argument and return a character. Read the character into a local ariable and return it.

  • Then implement a getline(file): Make a buffer, starting reading characters into it one at a time, stop when you come to '\n' (what will you do if you run out of room?), and return a pointer to the buffer (How can you allocate the buffer for this to work?).

  • Use you getline to read one line at a time, then write the line number and the line.

  • Loop until you run out of file...


To make fewer system calls:

Read the whole file into a large buffer in one go---that's pretty easy if you have the file size---and walk it one character at a time to find the line starts and ends (use two pointers).

dmckee
Depends on your point of view for homework, is there a rule on stack about this? Where can I read about it?Back to the problem...Doesn't read takes 3 arguments? How will that work and where is the bytes read going to be stored? I'm not sure what I can and cannot do and it just doesn't feel right
Nazgulled
Tagging it homework is good manners. We'll help with homework questions, but not give you answers. I fixed the read() bug. More in a moment.
dmckee
Yes, but like I said, depends on your point of view of homework. I don't consider this homework. Homework, to me, it's an exercise from the teacher to do at home where he'll give me points if I did it or take me points if I didn't do it. This is not the case. But forget about that...
Nazgulled
Just saw your edit but that solution will have too many system calls, the idea is to have as less as possible.
Nazgulled
+1  A: 

If you don't know the lengths of the lines in advance, there is no shortcut for finding the place of the \n. That is, unless you use a readily implemented function for splitting the lines, but that would probably just do the same thing somewhere down the line.

That is, yes, you have to loop through the chars :)

ent
+1  A: 

You don't actually need to know the location of the '\n' to number the lines. You just print out the line number (starting with 1), and read characters until you hit a newline '\n'. Copy each character back to stdout with write(), and if the character is a newline, increment the count of current lines and print that out, too.

Adam Rosenfield
So you're saying to read() char by char until I find a '\n'?
Nazgulled
+3  A: 

The only way to find a '\n' is to search for it. If you can't use strchr(3), you've got to iterate over the buffer to find what you're looking for (read: implement it).

Andy
+4  A: 

You will have to search the buffer for \n, there is no way around it. Don't worry about the performance, the progam will spend most of the time in read and write.

Also, make sure you make the buffer sufficiently large. Don't call read(file,&c,1) as it will be incredibly slow.

avakar
I'm using BUFSIZ from stdio.h (which on my machine is 8192) in the "cat" exercise...
Nazgulled
That should be just fine.
avakar