adding chars to a string

R

Rick

Hi,

This is probably simple byt when you never did pointers and being used to
luxery strings like in Delphi or Visual Basic, C can get though. What I'm
trying to do is to add chars to a string. I looked in the string.h file but
I didn't find that kind of function (that string library is more than 7
years old) so I decided to write that function on myself. It seems to work
although when I'm trying to do printf's between those actions I get strange
messages. Anyway, now I'm trying to add chars to 2 strings. The first string
is ok but the second one seems to get overwrited. Here's my code :

/* the function to add 1 char to a string */

char *strAddChar(char *s1, char c){
char *s;
s = s1;
s = s + strlen(s1); // the position to write
*s = c; // this should be on the place where the null char
first
// was.
s++;
*s = 0; // add a new null string
return(s1);
} // strAddChar

/* this is how I use the function */
main(){
char *res1 = ""; // empty string 1
char *res2 = ""; // empty string 2
strAddChar( res1, 'a' );
strAddChar( res1, 'b' );
strAddChar( res1, 'c' );
strAddChar( res2, '1' );
strAddChar( res2, '2' );
strAddChar( res2, '3' );
printf( "%s\n",res1 ); // test
printf( "%s\n",res2 );

Ok, the output should be res1="abc" and res2="123" but this is my result :
res1="abc" res2="bc123"
How does "bc" come in res2?? How to fix the function?

Greetings,
Rick
 
A

Andreas Kahari

Hi,

This is probably simple byt when you never did pointers and being used to
luxery strings like in Delphi or Visual Basic, C can get though. What I'm
trying to do is to add chars to a string.


Did you investigate strcat() and strncat()?
 
R

Rick

To add, I think result2 get's overwritten by result1 somehow. When those 2
got initialized they get a memory adress automatically and it seems that
when I'm adding chars to result1, result2 won't move further. Result1
probably only get 1 byte of memory so when adding the second char it's "out
of bounds" and contineus on result2.

If this is true, that would be quiete dangerous because I could overwrite a
big part of the program. Normally you can use arrays and malloc them but in
my case, I really don't know how big the result becomes. While building the
result string, I need at least 1 sub string for other stuff, that string has
the same problem, I can't calculate how big it becomes, it has to grow
dynamically. How to handle this?

Greetings,
Rick
 
R

Rick

You answered faster than the light! I just tried it but the same problem
(see that other post where I explained the problem a little bit more). Or
maybe I am using the code wrong, this is what I did with strncat:

char *res1 = "";
char *res2 = "";
strncat( res1, "a",1 );
strncat( res1, "b",1 );
strncat( res1, "c",1 );
strncat( res2, "1",1 );
strncat( res2, "2",1 );
strncat( res2, "3",1 );
printf( "result1 %s\n",res1 );
printf( "result2 %s\n",res2 );

result : res1 = "abc" res2="bc123". When using strcat the same.

Greetings,
Rick
 
M

Mark A. Odell

You answered faster than the light! I just tried it but the same problem
(see that other post where I explained the problem a little bit more).
Or maybe I am using the code wrong, this is what I did with strncat:

char *res1 = "";
char *res2 = "";

HEY! You have to allocate writable memory for these pointers.
strncat( res1, "a",1 );

NO! You cannot write to res1 or res2. Look up malloc() and use it, then
come back. The res1 pointer is pointing to non-writable memory at this
point. Some implemtations will allow this, others will crash. What if the
compiler put the null string that res1 points to in FLASH or PROM? How
could you write to that?
 
A

Andreas Kahari

You answered faster than the light! I just tried it but the same problem
(see that other post where I explained the problem a little bit more). Or
maybe I am using the code wrong, this is what I did with strncat:

char *res1 = "";
char *res2 = "";
strncat( res1, "a",1 );

You're not allowed to modify the contents of the string pointed
to by res1 or res2, the way you defined them. Both pointers
must point to a sufficiently large portion of allocated memory.

See here:

#include <stdio.h>
#include <string.h>

int
main(void)
{
char res1[10] = ""; /* Must be long enough */
char res2[10] = ""; /* Must be long enough */

/* strncat(res1, "abc", 3), but more verbose: */
strncat(res1, "a", 1);
strncat(res1, "b", 1);
strncat(res1, "c", 1);

/* strncat(res2, "123", 3), but more verbose: */
strncat(res2, "1", 1);
strncat(res2, "2", 1);
strncat(res2, "3", 1);

printf("res1 = '%s'\nres2 = '%s'\n", res1, res2);

return 0;
}

Result:
res1 = 'abc'
res2 = '123'
 
B

Bjoern Pedersen

Rick said:
Hi,
char *strAddChar(char *s1, char c){
char *s;
s = s1;
s = s + strlen(s1); // the position to write
*s = c; // this should be on the place where the null char
first
// was.
s++;
*s = 0; // add a new null string
return(s1);
} // strAddChar

/* this is how I use the function */
main(){
char *res1 = ""; // empty string 1
^^^ ^^^^ res1 points to an (possibly)
non-writable array of 2 chars,
char *res2 = ""; // empty string 2

the same here...
strAddChar( res1, 'a' );

and here you invoke undefinde behaviour by writting to res1 ( and
writing past the end.

C-strings do not grow automagically, you would have to do this by
mallocing enough memory somewhere.

Björn
 
L

L.J. Buitinck

Rick said:
If this is true, that would be quiete dangerous because I could overwrite a
big part of the program. Normally you can use arrays and malloc them but in
my case, I really don't know how big the result becomes. While building the
result string, I need at least 1 sub string for other stuff, that string has
the same problem, I can't calculate how big it becomes, it has to grow
dynamically. How to handle this?

use realloc(), which resizes malloc()'d buffers. e.g.,


char *s;

s = malloc(4);
if (s == NULL) {
/* ... */
}
strcpy(s, "foo");
s = realloc(s, 4+3);
if (s == NULL) {
free(s);
/* ... */
}
strcat(s, "bar");


if your system has them, consider using strlcpy()/strlcat().
http://www.openbsd.org/papers/strlcpy-paper.ps
 
M

Mark A. Odell

Andreas, let's be sure Rick sees the important change...
int
main(void)
{
char res1[10] = ""; /* Must be long enough */
char res2[10] = ""; /* Must be long enough */
^^^^

Rick, note that these are arrays of chars, not pointers to chars. That's
the key.
 
R

Rick

Everybody thanks for helping I understand the problem. It's now working with
fixed sized arrays.

Greetings,
Rick
 
A

Andreas Kahari

L.J. Buitinck wrote: said:
char *s;

s = malloc(4);
if (s == NULL) {
/* ... */
}
strcpy(s, "foo");
s = realloc(s, 4+3);
if (s == NULL) {
free(s);

If s is NULL, what use is the free() call?

Hint: Assign the returned value from realloc() to to a temporary pointer.
/* ... */
}
strcat(s, "bar");

/* ... */

free(s);
 
D

David Rubin

Rick said:
Hi,

This is probably simple byt when you never did pointers and being used to
luxery strings like in Delphi or Visual Basic, C can get though.

Was this generated by a Markov chain program?

[snip]
/* this is how I use the function */
main(){
char *res1 = ""; // empty string 1
char *res2 = ""; // empty string 2
strAddChar( res1, 'a' );

This produces UB unless strAddChar (re)allocates memory (which it
doesn't). Also, starting a function with 'str' violates the
implementation namespace.

Man strcat, but always make sure you're (allocated) string memory is big
enough to accomodate the new character.

/david
 
D

Dan Pop

In said:
NO! You cannot write to res1 or res2. Look up malloc() and use it, then
come back.

Static allocation is perfectly OK for the OP's needs. And dynamic
allocation seems to be above his current C skills.

Dan
 
I

Irrwahn Grausewitz

David Rubin said:
[...] Also, starting a function with 'str' violates the
implementation namespace.

But only if followed by a lowercase letter, thus the OP is safe
declaring a function named strAddChar.

Regards
 
K

Kevin Goodsell

Rick said:
/* the function to add 1 char to a string */

char *strAddChar(char *s1, char c){
char *s;
s = s1;
s = s + strlen(s1); // the position to write

Unless you are using a C99 compiler (extremely unlikely), the above
"comment" is a syntax error. Use /* */ comments instead.
*s = c; // this should be on the place where the null char
first
// was.
s++;
*s = 0; // add a new null string
return(s1);
} // strAddChar

/* this is how I use the function */
main(){

Make this

int main(void)

'Implicit int' has been removed from the C language. Granted, you are
not using the current version of C, but you might as well get in the
habit if supplying a return type now.
char *res1 = ""; // empty string 1
char *res2 = ""; // empty string 2

Never assign a string literal to a non-const char *. This is only
allowed for historical reasons, and it's never a good idea. You cannot
modify a string literal, so you might as well make it obvious that you
do not intend to modify it by declaring the pointers const:

const char *res1 = "";
const char *res2 = "";

If you make this change, you will find that your program no longer
compiles. This is because it contains an error. The error (attempting to
modify a string literal) was there before, the compiler just wasn't able
to detect it. Once you use the correct type for res1 and res2, it can
detect it.

-Kevin
 
C

Christopher Benson-Manica

Kevin Goodsell said:
Unless you are using a C99 compiler (extremely unlikely), the above
"comment" is a syntax error. Use /* */ comments instead.

Well, it isn't conforming, but he could easily have a compiler that supports
this extension...
 
M

Mark McIntyre

David Rubin said:
[...] Also, starting a function with 'str' violates the
implementation namespace.

But only if followed by a lowercase letter, thus the OP is safe
declaring a function named strAddChar.

Safe but dangerous. /He/ might realise the above rule, but the next
maintainer might not. T'is safer just to steer clear entirely of RYO
str.. functions.
 
D

Dan Pop

In said:
Well, it isn't conforming, but he could easily have a compiler that supports
this extension...

Which requires a diagnostic, once he's using his compiler as a conforming
C89 compiler, because, with one exception (//*) // is a syntax error in
C89.

Dan
 
S

Simon Biber

Irrwahn Grausewitz said:
David Rubin said:
[...] Also, starting a function with 'str' violates the
implementation namespace.

But only if followed by a lowercase letter, thus the OP is safe
declaring a function named strAddChar.

Only safe if that function is declared static. Otherwise the
external name of the function may conflict with any identifier
starting with 'stradd', since external identifiers need not
be case-sensitive.

C89 3.1.2 Identifiers:
"The implementation may further restrict the significance of
an external name (an identifier that has external linkage)
to six characters and may ignore distinctions of alphabetical
case for such names."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top