4

perhaps a lil trivial, but im just learning C and i hate doing with 2 lines, what can be done with one(as long as it does not confuse the code of course).

anyway, im building strings by appending one character at a time. im doing this by keeping track of the char index of the string being built, as well as the input file string's(line) index.

str[strIndex] = inStr[index];
str[strIndex + 1] = '\0';

str is used to temporarily store one of the words from the input line. i need to append the terminator every time i add a char.

i guess what i want to know; is there a way to combine these in one statement, without using strcat()(or clearing str with memset() every time i start a new word) or creating other variables?

8
  • You don't have to append the null character every time. Just append it at the end of the string. How many strings are there? Can you explain further? Commented Oct 15, 2015 at 0:46
  • You can add it at the end of the loop. Means first line outside the loop. Commented Oct 15, 2015 at 0:49
  • I have posted the answer below. Mark it as accepted, if you think so. Commented Oct 15, 2015 at 0:55
  • but if this only had to be done once, outside of a lop for example, it still begs the question, can those two statements be combined into one? i guess what im asking is there a way to append 2(or more) chars at a time without using a library function? Commented Oct 15, 2015 at 0:58
  • if you are talking about assigning multiple values to multiple indices of an array, without library functions, to best of my knowledge, it's not possible. Commented Oct 15, 2015 at 1:01

3 Answers 3

7

Simple solution: Zero out the string before you add anything to it. The NULs will already be at every location ahead of time.

// On the stack:
char str[STRLEN] = {0};

// On the heap
char *str = calloc(STRLEN, sizeof(*str));

In the calloc case, for large allocations, you won't even pay the cost of zeroing the memory explicitly (in bulk allocation mode, it requests memory directly from the OS, which is either lazily zero-ed (Linux) or has been background zero-ed before you ask for it (Windows)).

Obviously, you can avoid even this amount of work by defering the NUL termination of the string until you're done building it, but if you might need to use it as a C-style string at any time, guaranteeing it's always NUL-terminated up front isn't unreasonable.

Sign up to request clarification or add additional context in comments.

Comments

1

I believe the way you are doing it now is the neatest that satisfies your requirement of

1) Not having string all zero to start with

2) At every stage the string is valid (as in always has a termination).

Basically you want to add two bytes each time. And really the most neat way to do that is the way you are doing it now.

If you are wanting to make the code seem neater by having the "one line" but not calling a function then perhaps a macro:

#define SetCharAndNull( String, Index, Character )  \
{                                                   \
    String[Index] = (Character);                    \
    String[Index+1] = 0;                            \
}

And use it like:

SetCharAndNull( str, strIndex, inStr[index]);

Otherwise the only other thing I can think of which would achieve the result is to write a "word" at a time (two bytes, so an unsigned short) in most cases. You could do this with some horrible typecasting and pointer arithmetic. I would strongly recommend against this though as it won't be very readable, also it won't be very portable. It would have to be written for a particular endianness, also it would have problems on systems that require alignment on word access.

[Edit: Added the following] Just for completeness I'm putting that awful solution I mentioned here:

*((unsigned short*)&str[strIndex]) = (unsigned short)(inStr[index]);

This is type casting the pointer of str[strIndex] to an unsigned short which on my system (OSX) is 16 bits (two bytes). It is then setting the value to a 16 bit version of inStr[index] where the top 8 bits are zero. Because my system is little endian, then the first byte will contain the least significant one (which is the character), and the second byte will be the zero from the top of the word. But as I said, don't do this! It won't work on big endian systems (you would have to add in a left shift by 8), also this will cause alignment problems on some processors where you can not access a 16bit value on a non 16-bit aligned address (this will be setting address with 8bit alignment)

2 Comments

Assuming you can use C99 or higher and get proper inline semantics, I'd use an inline function over a preprocessor macro; it gets you type safety and allows debuggers to work more nicely when compiled with symbols. You're not using any feature unique to macros (e.g. checking __LINE__, referencing scoped variables not explicitly passed), so an inline function should be equally effective (sometimes moreso, since the compiler has more knowledge of what is going on for optimization).
Example: static inline void set_char_and_null(char *str, size_t idx, char val) { str[idx] = val; str[idx+1] = '\0'; }
1

Declare a char array:

char str[100];

or,

char * str = (char *)malloc(100 * sizeof(char));

Add all the character one by one in a loop:

for(i = 0; i<length; i++){
    str[i] = inStr[index];
}

Finish it with a null character (outside the loop):

str[i] = '\0';

1 Comment

but if this only had to be done once, outside of a loop for example, it still begs the question, can those two statements be combined into one? i guess what im asking is there a way to append 2(or more) chars at a time without using a library function?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.