I am having issues with outputting a string correctly that is coming from a 4K read buffer. Here is the code I have currently:

read_4K.c (cannot be modified)

int read_4K(char *b)
{
  return read(0, b, 4096);
}

reader.c

static char Buffer[4096];
static int Bend = 0;
static int Bptr = 0;

int read_string(char *s,int size){
	
	if(Bptr >= Bend){
		Bend = read_4K(Buffer);
		if(!Bend){
			return 0;
		}
		Bptr = 0;
	}
	
	strncpy(s, &Buffer[Bptr], size);
	Bptr += size;
	
}

bcat.c

main(int argc, char **argv)
{
  int i;
  char *str;
  int bsize;

  if (argc != 2 || sscanf(argv[1], "%d", &bsize) == 0 || bsize <= 0) {
    fprintf(stderr, "usage: bcat strsize\n");
  }
  
  str = (char *) malloc(sizeof(char)*bsize);
  if (str == NULL) { perror("malloc str"); exit(1); }
  
  while (1) {
    i = read_string(str, bsize);
    if (i == 0) exit(0);
    fwrite(str, 1, i, stdout);
  }
}

When I execute this I get the following output

> ./bcat2 10 < input1.txt
Up and down the puppñies' hair ñ
Fleas andñ ticks jumñp everywheñre
'Causeñ of originñal sin

input1.txt:
Up and down the puppies' hair
Fleas and ticks jump everywhere
'Cause of original sin


I can't figure out why I am getting these garbage characters after the first read from the buffer... Can anyone help?

Recommended Answers

All 11 Replies

Try to use fflush(stdin) before reading. It will flush the standard input(keyboard)

I am having issues with outputting a string correctly that is coming from a 4K read buffer. Here is the code I have currently:

read_4K.c (cannot be modified)

int read_4K(char *b)
{
  return read(0, b, 4096);
}

reader.c

static char Buffer[4096];
static int Bend = 0;
static int Bptr = 0;

int read_string(char *s,int size){
	
	if(Bptr >= Bend){
		Bend = read_4K(Buffer);
		if(!Bend){
			return 0;
		}
		Bptr = 0;
	}
	
	strncpy(s, &Buffer[Bptr], size);
	Bptr += size;
	
}

bcat.c

main(int argc, char **argv)
{
  int i;
  char *str;
  int bsize;

  if (argc != 2 || sscanf(argv[1], "%d", &bsize) == 0 || bsize <= 0) {
    fprintf(stderr, "usage: bcat strsize\n");
  }
  
  str = (char *) malloc(sizeof(char)*bsize);
  if (str == NULL) { perror("malloc str"); exit(1); }
  
  while (1) {
    i = read_string(str, bsize);
    if (i == 0) exit(0);
    fwrite(str, 1, i, stdout);
  }
}

When I execute this I get the following output

> ./bcat2 10 < input1.txt
Up and down the puppñies' hair ñ
Fleas andñ ticks jumñp everywheñre
'Causeñ of originñal sin

input1.txt:
Up and down the puppies' hair
Fleas and ticks jump everywhere
'Cause of original sin


I can't figure out why I am getting these garbage characters after the first read from the buffer... Can anyone help?

commented: It's a really bad idea to go round recommending fflush(stdin) - search the board for why -4

It looks like you need to null-terminate your strings.

commented: It sure does :) +19

Try to use fflush(stdin) before reading. It will flush the standard input(keyboard)

Never, NEVER, NEVER use fflush(stdin) . Here's why.

Are you guys on autopilot again? Beg to explain how null termination is related to the OP problem.

The real problem is that read_string doesn't return anything when it should.

Are you guys on autopilot again? Beg to explain how null termination is related to the OP problem.

I would guess that it had very much to do with the OP's description of the issue:

When I execute this I get the following output

> ./bcat2 10 < input1.txt
Up and down the puppñies' hair ñ
Fleas andñ ticks jumñp everywheñre
'Causeñ of originñal sin

input1.txt:
Up and down the puppies' hair
Fleas and ticks jump everywhere
'Cause of original sin


I can't figure out why I am getting these garbage characters after the first read from the buffer...

See that garbage character every 10? Which coincides with the size limit with the call to strncpy? Which doesn't automatically null terminate?

Just a guess.

The real problem is that read_string doesn't return anything when it should.

I don't think the OP posted enough of the code to reproduce the problem. Or at least not reliably on different systems. But it would appear that on the OP's system that input is being obtained.

See that garbage character every 10? Which coincides with the size limit with the call to strncpy? Which doesn't automatically null terminate?

I sure do. I also see that the output is produced with fwrite(str, 1, i, stdout) , which cares not of null termination. I am absolutely sure that the counter i is plain wrong.

I sure do. I also see that the output is produced with fwrite(str, 1, i, stdout) , which cares not of null termination. I am absolutely sure that the counter i is plain wrong.

Well, I'll defer to that since my I/O looks like this:

D:\projects\misc\c>debug\capp 10 < file.txt

D:\projects\misc\c>

[edit]But indeed read_string should return a value.
[edit=2]Let me instead say that read_string probably really needs a fair rewrite. Handling a rollover of say 4090 to 4100, so adjusting the size. Plus returning how many bytes are really copied. And maybe using memcpy instead of strncpy. Maybe.

Anytime strncpy is used, it is up to you to make sure the string is terminated properly.

Dave- I can very much relate to your tagline "Long time no C"!

Nezachem - I don't mean to imply, by my terse answers, that I have all the answers to the problem. I was merely pointing out one potentential problem that caught my eye. You might have a valid point, however; whenever I see output such as what the OP supplied, and see a call to strncpy without explicit termination of the destination string (which is the input for fwrite: Garbage In Garbage Out) I see a red flag.
I would feel much more comfortable if I saw something like
destination[strlen(source)] = 0, after the call to strncpy
It's been a while cause like Dave says... "long time no C".
I do miss C, though.

Nezachem - I don't mean to imply, by my terse answers, that I have all the answers to the problem. I was merely pointing out one potentential problem that caught my eye.

If I sounded harsh, I owe an apology too.
You see, your original message by no means offered any help to the OP. His problem stemmed from the totally different mistake.
Yes I agree that strncpy raises a red flag. Seeing such construct everybody urges to jump out and say "hey where is the terminator?!". It is very important to suppress this urge and reread a problem. Otherwise the reply would only contribute to the entropy of the universe and a global warming.

You might have a valid point, however; whenever I see output such as what the OP supplied, and see a call to strncpy without explicit termination of the destination string (which is the input for fwrite: Garbage In Garbage Out) I see a red flag.

Surprisingly, strncpy was designed as it is (that is without placing a terminator) for a reason. In most situations calling for strncpy that extra '\0' would just stand in a way.

destination[strlen(source)] = 0, after the call to strncpy

Hmm... do I smell a buffer overflow here?

If I sounded harsh, I owe an apology too.

I was not seeking an apology. Since, you offered one, and quickly followed it with condescending statements, I take it your “apology” was disingenuous.

You see, your original message by no means offered any help to the OP. His problem stemmed from the totally different mistake.

That may be the case, however; my intent was merely to shed light on, what appears to me, as a potential problem. In my experience, when using strncpy(char* destination, char* source, n), you need to be certain that the “nth” character is a null terminator, or place one there yourself, before printing it to output. My intent on this forum is to help others where I think I can, and learn from those that are more knowledgeable than myself on a given subject. And from the majority of what I have seen so far from this forum, there’s a lot of opportunity for me to learn!

It is very important to suppress this urge and reread a problem. Otherwise the reply would only contribute to the entropy of the universe and a global warming.

C’mon, get a grip on reality. You sound like you’re the one that invented the internet… very imaginative, and condescending.

Surprisingly, strncpy was designed as it is (that is without placing a terminator) for a reason.

This is not surprising at all. I have found this function very useful many times in the past.

In most situations calling for strncpy that extra '\0' would just stand in a way.

Yes, the “extra”, if not an extra ‘\0’, would stand in the way of having a non-terminated string with who knows what garbage might at the end, until a ‘\0’ is found.

Hmm... do I smell a buffer overflow here?

Not if you have allocated enough memory to store (strlen(source) + 1) bytes. However, I do smell a b.s. overflow from your posts.

My intent here is not to turn this thread into a pissing contest. If that’s your intent, I’ll let you have the last word

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.