// Convert an array of char* strings into a single string, separated by spaces, with a passed maximum length // RJM Programming 15/11/2013 ... as per http://au.answers.yahoo.com/question/index?qid=20131112144151AA92GN0 #include #include #include char* concatenate_into_buffer(char** buffer, char* inarr[], int maxlen, int *elen, char* prevc) { // buffer is Pointer to pointer to buffer // inarr[] is String array of char*'s // maxlen is Maximum allowable buffer length (allowing for zero byte at end) // *elen is Pointer to length of buffer // prevc is Parent's memory of the last buffer returned, for reruns char* endptr = NULL, *inp = NULL, fmt[20]; int i=0, ilen=0, setaside=0; bool firstgo = true; if (inp == NULL && strlen(inarr[0])) { // if there is input data ... inp = inarr[0]; while (strlen(inp) && ilen != maxlen) { // while there is input data for this String array element ... if (!*buffer) { // inside here is first go for unassigned memory scenarios the first time ... firstgo = false; ilen = strlen(inp) + 1; if (ilen > maxlen) { // overshooting length inside here ... ilen = maxlen; *buffer = (char*) malloc(ilen); sprintf(fmt, "%s%d%s", "%.", (maxlen - 1), "s"); sprintf((char*)*buffer, fmt, inp); } else { // else first time malloc to allocate memory for buffer //printf("Len=%d Inp=%s Ilen=%d\n", strlen(inarr[i]), inp, ilen); *buffer = (char*) malloc(ilen); sprintf((char*)*buffer, "%s", inp); // write to buffer ... } } else { // else here for situations where malloc has already been called ... if (ilen == 0) { ilen = strlen((char*)*buffer) + 1; } ilen += strlen(inp) + 1; if (ilen > maxlen) { // overshooting buffer length inside here ... ilen = maxlen; if (ilen > setaside) realloc((char*)*buffer, ilen); sprintf(fmt, "%s%d%s", "%s %.", (maxlen - strlen((char*)*buffer) - 2), "s"); sprintf((char*)*buffer, fmt, (char*)*buffer, inp); // append to buffer ... } else { // no overshooting inside here ... //printf("len=%d inp=%s ilen=%d buffer=%s\n", strlen(inarr[i]), inp, ilen, (char*)*buffer); if (firstgo && strlen(prevc) > 0) { // inside here is a rerun of this function recalled by parent ... //printf("Len=%d inp=%s ilen=%d buffer=%s\n", strlen(inarr[i]), inp, ilen, (char*)*buffer); *buffer = (char*) malloc(maxlen); setaside = maxlen; sprintf((char*)*buffer, "%s\0", prevc); } else { // first pass realloc call to get more memory ... if (ilen > setaside) realloc((char*)buffer, ilen); } firstgo = false; sprintf((char*)*buffer, "%s %s", (char*)*buffer, inp); // append to buffer ... } } i++; // increment current input array counter, of interest ... endptr = *buffer + strlen((char*)*buffer) + 1; // determine and return the pointer to end of buffer ... inp = inarr[i]; // update pointer to next string of input array ... //printf("buffer=%s %ld\n", *buffer, endptr); } } *elen = strlen((char*)*buffer) + 1; // fill in value for length of buffer (available for parent) *endptr = 0; // end of buffer should be zero byte return endptr; // return end of buffer pointer } int main(int argc, char** argv) { char* strs[] = {"firststring\0", "secondstring\0", "thirdstring\0" "fourthstring\0", "\0"}; //char *strs[] = {"f\0", "s\0", "t\0" "f\0", "\0"}; char *buff=NULL, *ebuff="\0"; char **mybuff = &buff; int jlen = 0; ebuff = concatenate_into_buffer(mybuff, strs, 10, &jlen, (ebuff - jlen)); printf("Buffer=%s\n", buff); ebuff = concatenate_into_buffer(mybuff, strs, 1000, &jlen, (ebuff - jlen)); printf("Buffer=%s\n", buff); ebuff = concatenate_into_buffer(mybuff, strs, 1000, &jlen, (ebuff - jlen)); printf("Buffer=%s\n", buff); }