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.
Related
I am trying to reverse this C-string and I thought I did it correct but the string remains the same when it passes through the function.
#include <stdio.h>
char* reverse(char* string);
int main(int arc, char* argv[]) {
char word[] = "Hello World!";
printf("%s\n", word);
printf("%s\n", reverse(word));
return 0;
}
char* reverse(char* string) {
int i, j, n = 0;int len = 0;char temp;
//Gets string length
for (i = 0; *(string + i) != '0'; i++) {
len++;
}
//Reverses string
for (j = len - 1; j >= 0; j--) {
temp = string[n];
string[n] = string[j];
string[j] = temp;
n++;
}
return &string[0];
}
Expected output:
Hello World!
!dlroW olleH
For starters there is a typo
for (i = 0; *(string + i) != '0'; i++) {
You have to write
for (i = 0; *(string + i) != '\0'; i++) {
That is instead of the character '0' you have to use '\0' or 0.
In this for loop
for (j = len - 1; j >= 0; j--) {
temp = string[n];
string[n] = string[j];
string[j] = temp;
n++;
}
the string is reversed twice.:) As a result you get the same string.
The function can look for example the following way
char * reverse(char *string)
{
//Gets string length
size_t n = 0;
while ( string[n] != '\0' ) ++n;
//Reverses string
for ( size_t i = 0, m = n / 2; i < m; i++ )
{
char temp = string[i];
string[i] = string[n - i - 1];
string[n - i - 1] = temp;
}
return string;
}
Or the function can be defined the following way using pointers
char * reverse(char *string)
{
//Gets string length
char *right = string;
while ( *right ) ++right;
//Reverses string
if ( right != string )
{
for ( char *left = string; left < --right; ++left )
{
char temp = *left;
*left = *right;
*right = temp;
}
}
return string;
}
The same approach of the function implementation without using pointers can look the following way
char * reverse(char *string)
{
//Gets string length
size_t n = 0;
while ( string[n] != '\0' ) ++n;
//Reverses string
if ( n != 0 )
{
for ( size_t i = 0; i < --n; ++i )
{
char temp = string[i];
string[i] = string[n];
string[n] = temp;
}
}
return string;
}
Here is one more solution. I like it most of all. Tough it is inefficient but it is not trivial as the early presented solutions. It is based on an attempt of one beginner to write a function that reverses a string.:)
#include <stdio.h>
#include <string.h>
char *reverse( char *string )
{
size_t n = 0;
while (string[n]) ++n;
while (!( n < 2 ))
{
char c = string[0];
memmove( string, string + 1, --n );
string[n] = c;
}
return string;
}
int main( void )
{
char string[] = "Hello World!";
puts( string );
puts( reverse( string ) );
}
The program output is
Hello World!
!dlroW olleH
Of course instead of manually calculating the length of a string in all the presented solutions there could be used standard string function strlen declared in the header <string.h>.
The problem is that the input word[] is an array, which decays to a pointer when passed to the reverse function.
In the for loop, instead of using n to keep track of the position, I suggest you to use i and j to keep track of the start and end of the string, and increment and decrement them respectively and use strlen to get the length of string.
Also, as it is mentionned above by #Vlad from Moscow, in your for loop you are checking for 0 but it should be \0 which is the null character.
Please find down below an update of your posted code that is generating the expected result :
#include <stdio.h>
char* reverse(char* string);
int main(int arc, char* argv[]) {
char word[] = "Hello World!";
printf("%s ", word);
printf("%s\n", reverse(word));
return 0;
}
char* reverse(char* string) {
int i, j;
char temp;
int len = strlen(string);
//Reverses string
for (i = 0, j = len - 1; i < j; i++, j--) {
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
return &string[0];
}
The output is as expected: Hello World! !dlroW olleH
Aditionnally, you can include the header <string.h> or explicitly
provide a declaration for 'strlen' to avoid the warning that indicate to implicitly declaring library function 'strlen' with type 'unsigned long (const char *)' [-Wimplicit-function-declaration]
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 am trying to remove even occurences of a substsring, for example if i have A11B11C11 and i want to remove 11, it will remove the ones on position 0 and 2, so it should look like AB11C.
This is the function i have thus far, it removes all the occurences.
void removeSubstr(char* s, char* c)
{
int poz = -1;
int i = 0;
int string_length = strlen(s);
int number_length = strlen(c);
while (i < string_length) {
if (strstr(&s[i], c) == &s[i]) {
poz++;
if (poz % 2 == 0) {
string_length -= number_length;
for (int j = i; j < string_length; j++) {
s[j] = s[j + number_length];
}
}
}
else {
i++;
}
}
printf("'%d'", poz);
s[i] = '\0';
}
My approach was that whenever i find one occurence i should add it to a counter, and whenever the counter is divisible with 2, i remove the substring, but it always removes all the substrings.
edit:
if (strstr(&s[i], c) == &s[i]) {
poz++;
if (poz % 2 == 0) {
string_length -= number_length;
for (int j = i; j < string_length; j++) {
s[j] = s[j + number_length];
}
}
else {
i++; //added this
}
}
As was told in comment, i had to increment the i as well when there was an odd occurence, and now it works.
For starters the function should return the modified source string. Also as the substring is not changed within the function then the corresponding function parameter should be declared with the qualifier const
char * removeSubstr( char *s1, const char *s2 );
Calling the function strstr starting from each character of the source string as you are doing
while (i < string_length) {
if (strstr(&s[i], c) == &s[i]) {
is not efficient. The substring initially can be absent in the source string.
Also if you have the source string like this "A11111" then it seems the result string should look like "A111" because after the first substring "11" is removed when in this string "A111" the substring "11" is odd and must not be removed.
However using your approach you will get the result string "A1". That is in the else statement you should write
else {
i += number_length;
}
I would write the function the following way as it is shown in the demonstration program below.
#include <stdio.h>
#include <string.h>
char * removeSubstr( char *s1, const char *s2 )
{
size_t pos = 0;
size_t n1 = strlen( s1 ), n2 = strlen( s2 );
for ( char *prev = s1, *next = s1 ; ( next = strstr( prev, s2 ) ) != NULL; prev = next )
{
n1 -= next - prev - n2;
if ( pos++ % 2 == 0 )
{
memmove( next, next + n2, n1 + 1 );
}
else
{
next = prev + n2;
}
}
return s1;
}
int main( void )
{
char s1[] = "A11B11C11";
const char *s2 = "11";
printf( "\"%s\"\n", s1 );
printf( "\"%s\"\n", removeSubstr( s1, s2 ) );
}
The program output is
"A11B11C11"
"AB11C"
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"
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