0

I'm required to do as the question title states. The restriction is that the consumer and producer have only 12 slots to put up to 20 chars into. I've got it working except that the last producer puts in only 13 chars (this is correct), and the last consumer does not recognize this. It writes 20 chars, which appends some extra chars to the end of my copied file. I have given it some thought and cannot find a suitable and efficient solution to have the consumer recognize that there are only 13 chars in the slot. I'm using the follow 2 lines to produce and consume (both use semaphores correctly and are running on separate threads simultaneously).

given by the problem at hand:

#define SLOTSIZE 20
#define SLOTCNT 12
char buffer[SLOTCNT][SLOTSIZE];

Producer:

count = fread(buffer[pIndex], sizeof(char), sizeof(buffer[pIndex]), myFile);

Consumer:

count = fwrite(buffer[cIndex], sizeof(char), sizeof(buffer[cIndex]), myFile);

This is a popular homework assignment so I'd prefer not to post much code. Any ideas? I believe I need an EOF marker at the end of those last 13 chars because I think that it is getting thrown out.

p.s. again for the producer, the result of the last read makes count = 13; and for the consumer, the last write makes count=20 and the extra chars ARE in the output file.

codenaugh
  • 857
  • 2
  • 12
  • 27
  • 1
    I think [mfro](http://stackoverflow.com/users/3423234/mfro) has [identified](http://stackoverflow.com/a/22890335/) the problem. You need to use the count from `fread()` when you call `fwrite()` (or vice versa; you shouldn't try to process data that isn't there to be processed). Most of the time, that'll be the same as the fixed `sizeof()` value, except at the end…which is when it matters. – Jonathan Leffler Apr 06 '14 at 06:32
  • the use of semaphores will prevent accessing data that has not been put in the buffer. – codenaugh Apr 06 '14 at 11:15
  • 1
    The use of semaphores will only prevent you from accessing slots that have not been partially or fully loaded; nothing will prevent you from writing 20 bytes of data from a slot when only 13 bytes were read into it if you don't record and use the number of bytes of data that were read into the slot. The return value from `fread()` is not for decoration; it is a critical value. Likewise, the return value from `fwrite()` is important for checking that you wrote what you intended to write. You've not accessing out of bounds, but if 13 bytes were filled, writing 20 bytes uses 7 bytes of garbage. – Jonathan Leffler Apr 06 '14 at 12:30
  • correct, I thought you were saying something else... I was a walking zombie last night. keeping track of the count in a global array did fix the problem, so thank you very much. – codenaugh Apr 06 '14 at 17:28

1 Answers1

1

with only that amount of sample code, it's difficult to give a correct answer without some guesswork.

Your problem seems to be that you do not know the amount of valid bytes in your buffers in the writer. buffer seems to be an array of char arrays? If yes, you could make it an array of structs instead, for example:

struct buf
{
    int used_length;
    char b[20];
};
struct buf buffer[20];

Then do as follows:

producer:

buffer[pIndex].used_length = count = fread(buffer[pIndex].b, sizeof(char), sizeof(buffer[pIndex].b), myFile);

consumer:

count = fwrite(buffer[cIndex].b, sizeof(char), buffer[cIndex].used_length, myFile);

This way you will only write as much bytes as you read.

mfro
  • 3,286
  • 1
  • 19
  • 28
  • I updated my code to show how the buffer is to be initialized, per the instructions. – codenaugh Apr 06 '14 at 11:15
  • 1
    if you are instructed to use buffers as shown, you will need some other way of to memorize how many bytes are valid within your arrays. You weren't clear if your copy should also copy binary files. If not, you could (ab)use a special character ('\0') as EOS (end of string) marker. If binary copy should be possible, you could use a separate array of `int`s instead where you store the valid length of each buffer. As long as you don't show more of your program, we can't tell you any other way to propagate buffer lengths to your writer threads. – mfro Apr 06 '14 at 11:42
  • Thank you. I was thinking the right stuff and was trying to make it work with a 2d array, but only a 1d was necessary for this. I initialized it as `bytes[SLOTCNT];`. During the producer's critical section, I used 'bytes[pIndex]=count;` to set the number of chars in the slot that was just filled; then during consumption, my fwrite becomes `count = fwrite(buffer[cIndex], sizeof(char), bytes[cIndex], myFile);` If you want to edit your response to match the solution, I'll mark it as the answer. – codenaugh Apr 06 '14 at 17:23
  • I'm not here to fish for reputation ;), thanks. I'm still of the mind that my original solution with structures is cleaner and easier to understand and maintain in "real code" than a separate array, so I will not change my answer. No offense, never mind. – mfro Apr 06 '14 at 17:30
  • No offense taken. Your solution is nice, but a slight mutation of the assignment. I'll mark as the answer and hopefully, if anyone runs into the same problem, they can read the comments as well, if necessary. – codenaugh Apr 06 '14 at 19:54