Inserting string (character by character) into a larger string - c

I am trying to insert a string by replacing a substring in the (original) string with a new string (toInsert). The start parameter is the starting position of the substring I want to replace. Note: This is part of a larger program but I am just trying to get this function to work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROW 5
#define COLUMN 81
void insertString(char original[], int start, int length, char toInsert[]){
char buffer[COLUMN];
int i = 0;
for (i=0; i<strlen(original); ++i){
if (i>=start){
buffer[i] = toInsert[i];
}
else{
buffer[i] = original[i];
}
}
buffer[strlen(buffer)-1] = '\0';
printf("%s\n", buffer);
return;
}
int main()
{
char rep[COLUMN] = "very";
char sub[COLUMN] = "are";
char buf[ROW][COLUMN] = {
{"How are you doing"}
};
int len = strlen(sub);
int start = 4;
insertString(buf[0], start, len, rep);
return 0;
}
The problem is it only prints "How".
I want it to print "How very you doing"
Also, I have tried using strcpy but that just gives errors/warnings (something to do with pointers and I don't want to deal with pointers because I have not learned about them yet.)

Your function does not make great sense because it neither enlarge or shrink the original string though it has to do this.
And moreover it has undefined behavior due to this if statement because when i is equal to or greater than start you can access the memory beyond the string toInsert using the index i.
if (i>=start){
buffer[i] = toInsert[i];
}
It is simpler to write the function using standard C functions.
Here you are
#include <stdio.h>
#include <string.h>
char * replaceString( char *s1, size_t pos, size_t n, const char *s2 )
{
size_t n1 = strlen( s1 );
if ( pos < n1 )
{
size_t n2 = strlen( s2 );
if ( n != n2 )
{
memmove( s1 + pos + n2, s1 + pos + n, n1 - pos - n + 1 );
}
memcpy( s1 + pos, s2, n2 );
}
return s1;
}
int main(void)
{
{
char s1[100] = "ab1111cd";
const char *s2 = "22";
puts( replaceString( s1, 2, 4 , s2 ) );
}
{
char s1[100] = "ab11cd";
const char *s2 = "2222";
puts( replaceString( s1, 2, 2 , s2 ) );
}
{
char s1[100] = "ab11cd";
const char *s2 = "22";
puts( replaceString( s1, 2, 2 , s2 ) );
}
return 0;
}
The program output is
ab22cd
ab2222cd
ab22cd
If to insert this code block
{
char s1[100] = "How are you doing";
const char *s2 = "very";
puts( replaceString( s1, 4, 3 , s2 ) );
}
in the demonstrative program you will get the output
How very you doing

Related

Inserting chars between each other with using arrays in C

I've been tried to place each character in the source string between characters in the destination string. It worked with equal length words but it didn't work other situations
For example:
It worked between apple and fruit, result is afprpuliet.
But it didn't work between plane and yes, the result should have been pyleasne.
or fly and train, the result should have been ftlryain.
Here is my code:
#include <stdio.h>
#include <string.h>
#define DESTSIZE 100
#define SOURCESIZE 20
int main(void)
{
char destination [DESTSIZE], source [SOURCESIZE];
printf("enter destinantion string for strinsert: ");
scanf("%s", destination);
printf("enter source string for strinsert: ");
scanf("%s", source);
strinsert(destination, source);
printf("after strinsert, destination string is %s\n", destination);
return 0;
}
void strinsert(char destination[], char source [])
{
int dest_len = strlen(destination);
for (int i = dest_len - 1; i >= 0; i--) {
destination[2 * i] = destination[i];
}
for (int i = 0; i < dest_len; i++) {
destination[2 * i + 1]= source[i];
}
}
To do this "in place" (using an adequately sized destination array) is not hard. The key is to determine the index of the destination element, then start copying, one by one, from the longest of the two strings, right to left.
Subtle is that when the two lengths yet to be copied are the same value, the second array is used as the source, not the first.
#include <stdio.h>
#include <string.h>
char *merge( char s1[], char s2[] ) {
int l1 = strlen( s1 );
int l2 = strlen( s2 );
s1[ l1 + l2 ] = '\0'; // ensure string will be terminated
while( l1 || l2 )
if( l1 > l2 )
l1--, s1[ l1 + l2 ] = s1[ l1 ];
else
l2--, s1[ l1 + l2 ] = s2[ l2 ];
return s1;
}
int main( void ) {
char dest[100];
char *test[] = { "apple", "fruit", "plane", "yes", "fly", "train", };
const int nTest = sizeof test/sizeof test[0];
for( int i = 0; i < nTest; i += 2 ) {
printf( "%s << %s = ", test[i], test[i+1] );
strcpy( dest, test[i] );
puts( merge( dest, test[i+1] ) );
}
return 0;
}
apple << fruit = afprpuliet
plane << yes = pyleasne
fly << train = ftlryain
A more compact version of main() so that it doesn't draw so much attention:
int main( void ) {
char d[100], *t[] = { "apple", "fruit", "plane", "yes", "fly", "train", };
for( int i = 0; i < sizeof t/sizeof t[0]; i += 2 )
printf("%s << %s = %s\n", t[i], t[i+1], merge(strcpy(d, t[i]), t[i+1]));
return 0;
}
EDIT
Although this is more difficult for a human to read, merge() could, likewise, be made more compact. It's up to the reader to decide if this appeals to their taste.
char *merge( char s1[], char s2[] ) {
int l1 = strlen( s1 ), l2 = strlen( s2 );
char *p = s1 + l1 + l2;
*p = '\0';
while( l1 || l2 )
*--p = ( l1 > l2 ) ? s1[ --l1 ] : s2[ --l2 ];
return p;
}
The problem is here
for (int i = 0; i < dest_len; i++) {
destination[2 * i + 1]= source[i];
}
Your source length is only 20 characters but your destination length is 100. So you are reading past the bounds of the source array. You should change the second loop to something like
int src_len = strlen(source);
for (int i = 0; i < src_len; i++) {
destination[2 * i + 1]= source[i];
}
I think you are messing yourself up by trying to do it in-place. Sure, it can be done in-place, but that just adds complexity.
Try doing it with a destination that is not either of the sources.
void interleave_strings( char * dest, const char * src1, const char * src2 )
{
// Interleaves src1 and src2 and stores the result in dest.
// dest must have space for strlen(src1) + strlen(src2) + 1 characters.
}
Usage:
int main(void)
{
char destination[SOURCE_SIZE*2+1] = {0};
char source1[SOURCE_SIZE] = {0};
char source2[SOURCE_SIZE] = {0};
...
interleave_strings( destination, source1, source2 );
printf( "interleaved = \"%s\"\n", destination );
return 0;
}
Once you make sense of doing it that way, then you can totally go back and do it the harder in-place way.
Oh, BTW, functions beginning with “str” are reserved. Hence you should not create them. So I renamed it.
You overwrite existing data in the destination. The easiest way is to use temporary array:
char *merge(char *dest, const char *src)
{
char temp[strlen(dest) + strlen(src) + 1];
char *wrk = dest;
size_t index = 0;
while(*src | *dest)
{
if(*dest) temp[index++] = *dest++;
if(*src) temp[index++] = *src++;
}
memcpy(dest, temp, index);
dest[index] = 0;
return dest;
}
int main(void)
{
char dest[256] = "1234567890";
char *src = "abcdefghijklmno";
puts(merge(dest, src));
}
https://godbolt.org/z/sqznjMf6r
or with your examples:
int main(void)
{
puts(merge((char[128]){"apple"}, "fruit"));
puts(merge((char[128]){"pen"}, "paper"));
puts(merge((char[128]){"plane"}, "yes"));
puts(merge((char[128]){"fly"}, "train"));
}
https://godbolt.org/z/6dc9Kv3dP

I'm not making the comparison I am intending to

I am trying to write a program that compares strings by their length and sorts them with qsort. I have been able to make them sort alphabetically, now I'm trying to sort them by length. What am I doing wrong with my comparison method? I'm unsure about pointers and feel that issue lies there. Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int stringCmp(const void *str1, const void *str2); //Function prototype.
int main (int argc, char *argv[])
{
int i;
char **arr = malloc(argc * sizeof(char *));
printf("Original Args:\n");
for (i = 0; i < argc-1; i++){
arr[i] = argv[i+1];
printf("%s\n",arr[i]);
}
qsort(arr, argc-1, sizeof *arr, stringCmp);
printf("\nSorted Args:\n");
for (i = 0; i < argc-1; i++){
printf("%s\n", arr[i]);
}
free (arr);
return 0;
}
int stringCmp(const void *str1, const void *str2)
{
return strlen(str1) - strlen(str2);
// return strcmp(*(char **)str1,*(char**) str2);
}
As with the commented out call to strcmp, the pointers received by the function actually have type char ** so you need to cast to that type.
return strlen(*(char **)str1) - strlen(*(char **)str2);
It seems you need to allocate argc - 1 pointers instead of argc pointers
char **arr = malloc( ( argc - 1 ) * sizeof(char *));
As for the comparison function then it can be defined the following way
int cmp( const void *s1, const void *s2 )
{
size_t n1 = strlen( *( const char ** )s1 );
size_t n2 = strlen( *( const char ** )s2 );
return ( n2 < n1 ) - ( n1 < n2 );
}
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cmp( const void *s1, const void *s2 )
{
size_t n1 = strlen( *( const char ** )s1 );
size_t n2 = strlen( *( const char ** )s2 );
return ( n2 < n1 ) - ( n1 < n2 );
}
int main(void)
{
char * s[] = { "12345", "1234", "123", "12", "1" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
qsort( s, N, sizeof( *s ), cmp );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
}
The program output is
12345 1234 123 12 1
1 12 123 1234 12345
Pay attention to that to implements the comparison function like
return strlen(*(char **)str1) - strlen(*(char **)str2);
will be incorrect because values of an expression of the unsigned integer type size_t can not be negative. And conversion such a value to the type int results in undefined behavior.

Is there any way to return a string starting at a certain index without using the library functions

char* string = "Hello, what's up?";
and I want to just return
"at's up?"
You can write a function. If the function shall not use standard C string functions then it can look for example the following way
char * substr( char *s, size_t pos )
{
size_t i = 0;
while ( i < pos && s[i] ) ++i;
return s + i;
}
As C does not support function overloading then the function above can be also written like
char * substr( const char *s, size_t pos )
{
size_t i = 0;
while ( i < pos && s[i] ) ++i;
return ( char * )( s + i );
}
Here is a demonstrative program.
#include <stdio.h>
char * substr( const char *s, size_t pos )
{
size_t i = 0;
while ( i < pos && s[i] ) ++i;
return ( char * )( s + i );
}
int main(void)
{
char * s = "Hello, what's up?";
puts( substr( s, 9 ) );
return 0;
}
The program output is
at's up?
If you already know the length of the string (and therefore know that going n characters ahead you will not go past the end), you can use string + n or &string[n], which are equivalent ways of "skipping" the first n characters of the string.
#include <stdio.h>
int main(void) {
char *str = "Hello!";
printf("%s\n", str + 1); // ello!
printf("%s\n", str + 3); // lo!
char *str2 = str + 3;
printf("%s\n", str2); // lo!
}
On the other hand, if you do not know the length of the string, you will have to make sure you don't go past the end by using a loop first. You can write a function for this:
#include <stdio.h>
char *skip(char *s, size_t n) {
while (*s && n--)
s++;
return s;
}
int main(void) {
char *str = "Hello!";
printf("%s\n", skip(str, 1)); // ello!
printf("%s\n", skip(str, 3)); // lo!
printf("%s\n", skip(str, 100)); // empty line
char *str2 = skip(str, 3);
printf("%s\n", str2); // lo!
}

How to Reverse a sentence word by word?

I was trying to reverse a sentence word by word. (how are you -> you are how) First of all I create a char sentence and reverse and temp. Sentence given by user to reverse. Temp catches the word to change the location in the sentence.Then I use strcat to concatenate each word. Here is the problem. I can find the word which is end of the sent(takes input) but when I'm trying to concatenate to reverse, it add this word to sentence and an error occurs. What's the problem?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* subs(char* temp, char* src, int start, int end);
int main() {
char sent[15]; //input sentence
char rev[15]; // output sentence
char *temp=(char*)calloc(1,sizeof(char)); //for the word
scanf(" %[^\n]%*c", &sent); // takin' input
int i, end, start;
i = strlen(sent);
//find the beggining and ending of the indexes of the word in sentence
while (i > 0) {
while (sent[i] == ' ') {
i--;
}
end = i-1;
while (sent[i] != ' ') {
i--;
}
start = i + 1;
//add the word to temp and concatenate to reverse
temp=subs(temp, sent, start, end);
strncat(rev, temp,end-start+3);
}
rev[strlen(sent)] = '\0';
printf("%s", rev);
return 0;
}
char* subs(char* temp, char* src, int start, int end) {
int i = 0, control;
// resize the temp for the wırd
temp = (char*)realloc(temp,end-start+3);
for (; i < (end - start) + 1; i++) {
control = (start + i);
temp[i] = src[control];
}
//adding blank and null character to end of the word.
temp[i] = ' ';
temp[++i] = '\0';
return temp;
}
I will just copy my good answer from this question that was not yet closed Reverse a string without strtok in C
. So I can not use this reference to close your question as a duplicate.
A standard approach is to reverse each word within a string and then to reverse the whole string.
The standard C function strtok is not appropriate in this case. Instead use the standard C functions strspn and strcspn.
Here you are.
#include <stdio.h>
#include <string.h>
static char * reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[ i ];
s[ i ] = s[ n - i - 1 ];
s[ n - i - 1 ] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *p = s;
while ( *p )
{
p += strspn( p, delim );
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
reverse( q, p - q );
}
}
return reverse( s, p - s );
}
int main(void)
{
char s[] = "5 60 +";
puts( s );
puts( reverse_by_words( s ) );
return 0;
}
The program output is
5 60 +
+ 60 5
If you want to keep leading and trailing spaces as they were in the original string then the functions can look the following way
#include <stdio.h>
#include <string.h>
static char *reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i -1 ];
s[n - i - 1] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *first = s, *last = s;
for ( char *p = s; *p; )
{
p += strspn( p, delim );
if ( last == s ) first = last = p;
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
last = p;
reverse( q, p - q );
}
}
reverse( first, last - first );
return s;
}
int main(void)
{
char s[] = "\t\t\t5 60 +";
printf( "\"%s\"\n", s );
printf( "\"%s\"\n", reverse_by_words( s ) );
return 0;
}
The program output is
" 5 60 +"
" + 60 5"

Insert a string to another string in C

I need to insert a character string to another character string.
I'd write my own code and it's work very well until I put SPACE character in insert character string.
I need to find out what is the problem of my code and How I can fix it.
//Insert string in another string
#include <stdio.h>
//Function to count number of characters in a string
int numOfChars(const char string[]);
//Function to insert string to another string
void insertString(char string[], char insert[], int position);
int main()
{
char str[20]= "145";
insertString(str, "23", 1);
printf("%s\n", str);
return 0;
}
int numOfChars(const char string[])
{
int counter = 0;
while(string[counter] != '\0')
counter++;
return counter;
}
void insertString(char string[], char insert[], int position)
{
int i, j;
int lenght1 = numOfChars(string);
int lenght2 = numOfChars(insert);
int finalLenght = lenght1 + lenght2;
for(i=lenght1, j=0; i<finalLenght; i++, position++, j++)
{
string[i] = string[position];
string[position] = insert[j];
}
string[finalLenght] = '\0';
}
Example 1 :
Main string : 145
Insert string : 23
Position : 2
Result : 12345
Example 2 with blank space :
Main string : 145
Insert string : 23[SPACE]
Position : 2
Result : 123 54
This loop
for(i=lenght1, j=0; i<finalLenght; i++, position++, j++)
{
string[i] = string[position];
string[position] = insert[j];
}
is incorrect because independent on the given position all characters from the source string stating at position position are written after the end of the source string.
Also the function insertString should be declared like
char * insertString(char string[], const char insert[], size_t position);
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
size_t numOfChars( const char s[] )
{
size_t n = 0;
while ( s[n] != '\0' ) ++n;
return n;
}
char * insertString( char s1[], const char s2[], size_t pos )
{
size_t n1 = numOfChars( s1 );
size_t n2 = numOfChars( s2 );
if ( n1 < pos ) pos = n1;
for ( size_t i = 0; i < n1 - pos; i++ )
{
s1[n1 + n2 - i - 1] = s1[n1 - i - 1];
}
for ( size_t i = 0; i < n2; i++)
{
s1[pos+i] = s2[i];
}
s1[n1 + n2] = '\0';
return s1;
}
int main(void)
{
enum { N = 20 };
char s1[N] = "123";
puts( insertString( s1, "AB", 0 ) );
char s2[N] = "123";
puts( insertString( s2, "AB", 1 ) );
char s3[N] = "123";
puts( insertString( s3, "AB", 2 ) );
char s4[N] = "123";
puts( insertString( s4, "AB", 3 ) );
return 0;
}
The program output is
AB123
1AB23
12AB3
123AB
Changing string[i] = string[position]; to string[position+lenght2] = string[position]; should solve the problem.
While copying over the elements of string[i] to their proper places, the length of the string to insert should be considered in addition to the position variable. In other words, you should shift the characters in string by the number of elements that need to be inserted in the middle.

Resources