473,387 Members | 1,597 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

insert a char in the middle of a string

Hello,
I have to insert a char in the middle of a string, I have written two functions
but I don't know what is the better? The problem is: if I use malloc() I copy
all the string with the new char in the middle every time, with realloc() the
part of the string before the position where the char has to be inserted is not
changed if realloc returns the same pointer is passed, but if not the
string is copied at all the first time, and then the part after the char has to
be shifted to right.. Perhaps it could be possible to make another function
using the system call of the os (brk, sbrk)?
Can anybody give me suggestions or clarify my ideas?
Thanks,
tano

/* Code: the len is in memory, incremented after every insertion, so it
doesn't need to compute it using strlen() */

#include <stdio.h>
#include <stdlib.h>

char* insert_char_malloc (char *str, int len, char c, int pos)
{
char *p;
int i;

p = malloc(len + 2);
for (i = 0 ; i < pos ; ++i)
p[i] = str[i];
p[i++] = c;
for ( ; i < len + 2 ; ++i)
p[i] = str[i - 1];
free(str);
return p;
}

char* insert_char_realloc (char *str, int len, char c, int pos)
{
int i;

str = realloc(str, len + 2);
for (i = len + 1 ; i > pos ; --i)
str[i] = str[i - 1];
str[i] = c;
return str;
}
Nov 14 '05 #1
7 14716
On 2004-08-09, tano <ta*****@yahoo.it> wrote:

I have to insert a char in the middle of a string, I have written
two functions but I don't know what is the better?


Both have their pros and cons, as you said yourself. I would
personally choose the "malloc" version, because it has a more
"constant" behavior. In any case it all depends on how often you have
to perform the operation: If not very often then you functions are
ok. If, though, you have to do it every once in a while (e.g. you 're
writing an editor), then you should probably choose a whole different
*representation* for your strings: Instead of having them be arrays of
chars you could implement them as lists of characters, or as lists of
arrays (substrings) that are broken and re-combined, and so on. The
possibilities are endless.

/npat

P.S. The system calls you mentioned cannot help you with this (they
are irrelevant).

Nov 14 '05 #2
tano <ta*****@yahoo.it> spoke thus:
char* insert_char_malloc (char *str, int len, char c, int pos)
{
char *p;
int i; p = malloc(len + 2);
You should check whether malloc() succeeded, if you were not aware of
that.
for (i = 0 ; i < pos ; ++i)
p[i] = str[i];
p[i++] = c;
for ( ; i < len + 2 ; ++i)
p[i] = str[i - 1];
free(str);
The caller has to be aware that str was freed, which IMHO is an
unnecessary burden.
return p;
}


I suggest (untested):

char *insert_char_realloc( char **str, int len, char c, int pos )
{
char *tmp=realloc( *str, len+2 );
if( !tmp ) { /* failed */
return NULL;
}
sprintf( tmp, "%.*s%c%s", pos, *str, c, *str+pos );
*str=tmp;
return *str;
}

I don't remember whether realloc( ptr, n ) == ptr; the double pointer
may be unnecessary. Of course, pos must be less than len or things
will break.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #3

"tano" <ta*****@yahoo.it> wrote

I have to insert a char in the middle of a string, I have written two functions but I don't know what is the better?

/* Code: the len is in memory, incremented after every insertion, so it
doesn't need to compute it using strlen() */

#include <stdio.h>
#include <stdlib.h>

char* insert_char_malloc (char *str, int len, char c, int pos)
{
char *p;
int i;

p = malloc(len + 2);
You need to check p is non-null.
for (i = 0 ; i < pos ; ++i)
p[i] = str[i];
p[i++] = c;
for ( ; i < len + 2 ; ++i)
p[i] = str[i - 1];
free(str);
return p;
}
Consider carefully whether you want to free str, and whether you want to
insist that the length is passed in. Both these things may give you a speed
advantage, but make the function less generally useful.

char* insert_char_realloc (char *str, int len, char c, int pos)
{
int i;

str = realloc(str, len + 2);
You need to assign to a temporary and test str for null.
for (i = len + 1 ; i > pos ; --i)
str[i] = str[i - 1];
str[i] = c;
return str;
}

The realloc() version may well be faster, since realloc() doesn't always
perform a copy. Howver it suffers from the same problem that the interface
isn't clean - you must pass a pointer allocated with malloc and then
remember that it is invalidated by the call.
Nov 14 '05 #4
# all the string with the new char in the middle every time, with realloc() the
# part of the string before the position where the char has to be inserted is not
# changed if realloc returns the same pointer is passed, but if not the
# string is copied at all the first time, and then the part after the char has to

realloc has a potential performance problem that you may not be aware of.
realloc can copy the string everytime; if the string is length n, that
is O(n) time. If you insert every character starting from an empty
string, that is n inserts or a total time of O(n^2).

If instead of copying each time 1, 2, 3, 4, 5, 6, 7, 8, ... , n = n(n+1)/2,
or O(n^2), you double the length only when necessary, 1, 2, 4, 4, 8, 8, 8,
8, ... , 2n, the number of copies is 1 + 2 + 4 + 8 +...
approx= 2^(log n) - 1, or O(n).

Bad news is that with C strings, you cannot deduce the allocated block
size from string length, and it is not portably available from the block
address, so you need to pass the allocated block size in and out.

If you do n mallocs of size 1, 2, 3, ..., n, you get this same quadratic
worst case performance.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
I think that's kinda of personal; I don't think I should answer that.
Nov 14 '05 #5


tano wrote:
Hello,
I have to insert a char in the middle of a string, I have written two functions
but I don't know what is the better? The problem is: if I use malloc() I copy
all the string with the new char in the middle every time, with realloc() the
part of the string before the position where the char has to be inserted is not
changed if realloc returns the same pointer is passed, but if not the
string is copied at all the first time, and then the part after the char has to
be shifted to right.. Perhaps it could be possible to make another function
using the system call of the os (brk, sbrk)?
Can anybody give me suggestions or clarify my ideas?
Thanks,


This is some code I have saved away. It inserts one string of
characters into another, so I can be used to insert a single character too.

/**FILE******************************************** ********************/
/* File Id: STRINS.C. */
/* Author: William Smith. */
/* Date Written: 23 Dec. 92. */
/* */
/* This function inserts a string (ins) into a target string */
/* (str) at a specified position (pos) in the target string. */
/* The position for the insert must fall within the boundries */
/* of the target string. */
/* */
/* The inspiration of this code came from an article that ap- */
/* peared in the Jan. 93 issue of "The C Users Journal" called */
/* an "Essential String Library". I wrote this code without the */
/* benefit of the code listing in the magazine. */
/* */
/* Arguments: */
/* char *str - The address of the string to insert into. */
/* char *pos - Position in the string where the insert will */
/* be done. */
/* char *ins - The address of a string to insert into the */
/* target string. */
/* */
/* Returns: The address of the target string after the */
/* insert. */
/* */
/* NOTE: It is the programmer's responsiblity to ensure there */
/* is enough space in the target string to insert. */
/* */
/************************************************** **************FILE**/

#include <stddef.h>
#include <string.h>

char *str_insert(char *str, char *pos, char *ins) {

size_t inslen, poslen, lenstr;

lenstr = strlen(str); /* Get lengths */
inslen = strlen(ins);
if (inslen && pos >= str && pos <= &str[lenstr]) { /* Minimum edits */
poslen = strlen(pos); /* Adjusted
length */
memmove(pos + inslen, pos, poslen); /* Make room in
str */
memmove(pos, ins, inslen); /* Now copy in
ins */
}
return str; /* Return entire
str */
}

--
Regards,
Stan Milam.
-------------------------------------------------------
Spiritual people inspire me. Religeous people scare me.
-------------------------------------------------------
Nov 14 '05 #6
Since no one else has pointed this out yet, I will:

In article <news:cf**********@chessie.cirr.com>
Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote:
char *insert_char_realloc( char **str, int len, char c, int pos )
{
char *tmp=realloc( *str, len+2 );
if( !tmp ) { /* failed */
return NULL;
}
sprintf( tmp, "%.*s%c%s", pos, *str, c, *str+pos );
*str=tmp;
return *str;
}

I don't remember whether realloc( ptr, n ) == ptr; the double pointer
may be unnecessary. Of course, pos must be less than len or things
will break.


There are two problems here: (A) realloc() may move the data, and
in the process invalidate the old data, so that the call to sprintf()
passes the wrong values. This can be fixed, and in some cases
realloc() does not actually move the data, but then: (B) The
behavior of sprintf() is undefined if the output region (tmp)
overlaps the input (*str, or after fixing the bug, tmp again).

The memmove()-and-insert solution is probably the best to the
problem as stated, but in general, inserting one character at a
time into a potentially-long string is not a great strategy.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #7
Chris Torek <no****@torek.net> spoke thus:
There are two problems here: (A) realloc() may move the data, and
in the process invalidate the old data, so that the call to sprintf()
passes the wrong values. This can be fixed, and in some cases
realloc() does not actually move the data, but then: (B) The
behavior of sprintf() is undefined if the output region (tmp)
overlaps the input (*str, or after fixing the bug, tmp again).


I wasn't sure I remembered A, but it figures. B, however, is an
embarassing gaffe on my part, and I'm grateful that you didn't let me
get away with it :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: Marcio Kleemann | last post by:
I need to force the first letter of each word in a line of text to uppercase. The text comes from a TextBox control in a Web Form. I'm new to ..NET and am having a problem. Since I can't modify...
11
by: Zeng | last post by:
Hello, Is it true that in C# we can't modify directly a character in a string? I can't find the method anywhere. I would expect something like this should work,but it doesn't string myStr =...
8
by: electrixnow | last post by:
I am reading in a comma delimited text file, with a document #,revision letter on each line. example: 123,A 456,B There are 19000 lines to this master document file. I will also be reading...
2
by: claire | last post by:
I have a char that i convert to a string as follows m_tHeader.m_sshortname is defined as char; string result = new string(m_tHeader.m_sshortname); The problem is that any '\0' chars in the...
2
by: Joah Senegal | last post by:
Hello I need to convert a chat to a string... but I don't know how to do this. i;ve searched the internet but I've only find some code to convert char * to string or char to string.... but I...
2
by: key9 | last post by:
Hi all on reading code I found these function int foo(int char); char foo(char ch_); string foo(string ch);
3
by: Kevin Frey | last post by:
I am porting Managed C++ code from VS2003 to VS2005. Therefore adopting the new C++/CLI syntax rather than /clr:oldSyntax. Much of our managed code is concerned with interfacing to native C++...
5
by: Zytan | last post by:
I am surprised that a single character string is not auto-created from a single char. It is hard to find information on converting a char into a string, since most people ask how to convert char...
7
by: Zhang Liming | last post by:
unsigned char rcd; rcd contains 10 chars, such as '1', '2'.... etc. string str; the problem is how to pass the contents in rcd to str with minimal cost?
14
by: Javier | last post by:
Hello, in which cases is it better the use of "const char*" to "string" (or even const string &). I mean, in STL (http://www.sgi.com/tech/stl/hash_map.html) I see: hash_map<const char*, int,...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.