Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

71%
+3 −0
Q&A How can I manage multiple consecutive strings in a buffer (and add more later)?

The fundamental problem here is that it is already ambiguous where the "end" of the data in the buffer is. Strings can be empty (have zero length as reported by strlen); as such, buffer could equal...

posted 9mo ago by Karl Knechtel‭

Answer
#1: Initial revision by user avatar Karl Knechtel‭ · 2024-03-21T19:36:49Z (9 months ago)
The fundamental problem here is that **it is already ambiguous** where the "end" of the data in the buffer is. Strings can be empty (have zero length as reported by `strlen`); as such, `buffer` could equally well be interpreted as containing *three* strings, where the last is empty. Or more than that - up to what the buffer can hold.

**The situation is even worse if we start with uninitialized memory**; then there's no way to tell whether the byte after the last intentionally-written null is just uninitialized garbage, or the start of another actual string.

If we don't need to be able to store empty strings, one way around the problem is to mimic how null-termination works, but at a string level rather than a byte level. That is to say, we can establish a convention that the sequence of strings is "empty-string-terminated", and use `strlen` repeatedly to search for this string. That will tell us where to copy the new string.

However, it will be both simpler and more flexible to just ***remember* where the end of the string sequence is**, and update it whenever another string is added. For example, we could do this using an integer index:

```
/* the lengths of the two initial strings and their null terminators */
int used = 8;
int usable = sizeof(buffer);
strncpy(buffer + used, another_string, usable - used);
buffer[usable - 1] = '\0';
used += strlen(another_string) + 1;
if (used > usable) used = usable;
```
This code takes care of a few important issues. Note the pointer arithmetic: `buffer` decays to a pointer to the start of the array, so `buffer + used` is the desired destination pointer. We need to restrict `strncpy` to the amount of space that *remains in* the buffer - between `buffer + used` and the end of the buffer - to avoid writing beyond the end of the array. Note that `strncpy` avoids writing more than the declared amount of room, but *does not* null-terminate if it reaches that limit. To avoid ending up with non-null-terminated data at the end of the array, we can just unconditionally add a null to the last spot in the buffer each time, as shown. (A more sophisticated approach might detect this situation and report an error somehow.) After writing, we need to update the record of how much space is used. (When the buffer is full, `used` will be limited to the array length; future attempts at `strncpy` will see that zero bytes are available.)

Also keep in mind that a representation like this is not convenient for *modifying* the strings later. In particular, anything that tries to change the length of a string that isn't at the end of the sequence, will cause a major headache - because every other string after it will need to be shifted around to make room or close a gap. (This is the same reason that you can't easily modify a single line of a text file "in place".)