I have written this exercise which should remove any chars in the first argument string which appear in the second string. But the result is a segmentation fault for the arguments below. Can any one explain to me what am I missing?
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int i, j, k, match;
while (s1[i] != '\0') {
match = 0;
for (k = 0; s2[k] != '\0'; ++k) {
if (s1[i] == s2[k]) {
match = 1;
break;
}
}
if (match) {
i++;
} else {
s1[j++] = s1[i++];
}
}
s1[j] = '\0';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}
For starters the function should be declared the following way
char * squeez( char s1[], const char s2[] );
That is the second parameter should have the qualifier const because the string specified by this parameter is not changed in the function.
The function should follow the general convention of C standard string functions and return pointer to the result string.
Within the function variables i and j are not initialized and have indeterminate values. So even the first while loop
int i, j, k, match;
while (s1[i] != '\0') {
// ...
invokes undefined behavior.
Instead of the type int of these variables you should use the type size_t because the type int can be not large enough to store lengths of strings.
You should declare variables in minimum scopes where they are used.
Keeping your approach to the function definition it can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
char * squeez( char s1[], const char s2[] )
{
size_t i = 0, j = 0;
while ( s1[i] != '\0' )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != '\0'; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
i++;
}
s1[j] = '\0';
return s1;
}
int main(void)
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
puts( squeez( s, x ) );
return 0;
}
The program output is
adk
Also as the variable i is not used outside the while loop then the while loop could be substituted for a for loop where the variable i will be declared. For example
char * squeez( char s1[], const char s2[] )
{
size_t j = 0;
for ( size_t i = 0; s1[i] != '\0'; i++ )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != '\0'; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
}
s1[j] = '\0';
return s1;
}
I noticed that the i and j are not initialized. In fact, your code is workable without the problem that I put forward. This is the code I tried.
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int index1 = 0, position = index1, index2 = 0;
int match = 0;
while (s1[index1] != '\0')
{
match = 0;
for (index2 = 0; s2[index2] != '\0'; index2++)
{
if (s1[index1] == s2[index2])
{
match = 1;
break;
}
}
if (match)
index1++;
else
s1[position++] = s1[index1++];
}
s1[position] = '\0';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}
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 need to delete all letters from s1 which are in s2.
I can't understand what is wrong with my code:
#include <stdio.h>
#include <stdlib.h>
void squeeze(char s1[], char s2[])
{
int i,j;
i=j=0;
for(i; s2[i]!='\0'; i++) {
for (j; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
s1[j] = s1[j + 1];
--j;
}
}
}
}
int main()
{
char w1[] = "abcde";
char w2[] = "fghaj";
squeeze(w1,w2);
puts(w1);
return 0;
}
but the output is:
abcde
What should I repair?
For starters the variable j is not reset to 0 in the inner loop for each iteration of the outer loop.
Secondly if a character has to be removed then all characters after it are not being moved to the left one position. You are simply replacing the removed character with the next character in the string.
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
char * squeeze( char s1[], const char s2[] )
{
for ( char *p = s1, *q = s1; *q; ++p )
{
if ( !*p || !strchr( s2, *p ) )
{
if ( q != p )
{
*q = *p;
}
if ( *p ) ++q;
}
}
return s1;
}
int main( void )
{
char w1[] = "abcde";
char w2[] = "fghaj";
puts( squeeze( w1, w2 ) );
return 0;
}
The program output is
bcde
If you are not allowed to use standard string functions and pointers then the program can look the following way.
#include <stdio.h>
char * squeeze( char s1[], const char s2[] )
{
for ( size_t i = 0, j = 0; s1[j] != '\0'; ++i )
{
size_t k = 0;
while ( s2[k] != '\0' && s2[k] != s1[i] ) ++k;
if ( s2[k] == '\0' )
{
if ( j != i )
{
s1[j] = s1[i];
}
if ( s1[i] != '\0' ) ++j;
}
}
return s1;
}
int main( void )
{
char w1[] = "abcde";
char w2[] = "fghaj";
puts( squeeze( w1, w2 ) );
return 0;
}
The program output is the same as shown for the previous demonstrative program
bcde
Two problems in squeeze:
You need to reinitialize j to zero on every pass through the loop.
You need to copy the entire remained of the string one character to the left, not just the character following the one you want to remove.
I suggest you rewrite squeeze as:
void squeeze(char s1[], char s2[])
{
int i,j;
i=j=0;
for( ; s2[i]!='\0'; i++) {
for (j = 0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
strcpy(s1+j, s1+j+1);
--j;
}
}
}
}
I see an issue here , your code is not entering this statement for some reason :
if (s1[j] == s2[i]) {
s1[j] = s1[j + 1];
--j;
}
your question might be why ? cause i and j are not set to 0 , try printing them and you will see that j will move to 4 but i is staying forever as 0
so as a start you can fix it by doing this
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
then you didn't copy the whole string and moved it back one step to rewrite over the found caracter , you only moved one caracter and left it blank
Exemple
input : abcde
output :b_cde
to fix this you have two methods :
use strcpy in order to move back one step the code
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]){
strcpy(s1+j, s1+j+1);
--j;
}
}
or you can simply create the same function using a boucle for
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]){
for (k=j;s1[k] != '\0';k++)
s1[k] = s1[k + 1];
--j;
}
}
#include <stdio.h>
#include <string.h>
int rem_str(char * porgstr, char * pdel) {
if (!porgstr || !pdel) {
return 0;
}
int i = 0;
int j = 0;
char tmp[256] = {0};
int len = strlen(pdel);
for (i = 0; i < len; i++) {
tmp[pdel[i]]++;
}
len = strlen(porgstr);
for (i = 0, j=0; i < len; i++) {
if(tmp[porgstr[i]] == 0) {
porgstr[j] = porgstr[i];
j++;
}
}
porgstr[j] = 0;
return 0;
}
int main () {
char * input1 = strdup("origional string passed to program");
char * input2 = strdup("sdel");
printf("Input before del : %s\n", input1);
rem_str(input1, input2);
printf("String after del : %s\n", input1);
return 0;
}
Output:
./a.out
Input before del : origional string passed to program
string after del : origiona tring pa to program
exercise in C:
write a function 'any' wchich returns information about position of first occurrence in s1 any lsign from s2. Return -1 when s1 doesnt includes signs from s2.
And my code is:
#include <stdio.h>
#include <stdlib.h>
int any(char s1[], char s2[]) {
int i, j;
int koniec;
for (i = 0; s2[i] != '\0'; i++) {
for (j = 0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
koniec = j;
}
else
{
koniec = -1;
}
}
}
return koniec;
}
int main()
{
char w1[] = "Dominik";
char w2[] = "zcki";
int wynik;
wynik = any(w1, w2);
printf("%d", wynik);
return 0;
}
but it returns: -1
but should 3
what is wrong?
Just return the position when you find it and do not keep looping:
int any(char s1[], char s2[]) {
int i, j;
for (i = 0; s1[i] != '\0'; i++) {
for (j = 0; s2[j] != '\0'; j++) {
if (s1[i] == s2[j]) {
return j;
}
}
}
return -1;
}
The if statement within the inner loop
if (s1[j] == s2[i]) {
koniec = j;
}
else
{
koniec = -1;
}
Does not make a sense because the value of the variable koniec will be overwritten in the last iterations of the both loops.
Moreover due to the order of the loops you are searching in fact a character from the string s2 in the string s1 while you need to find the first character in s1 that is present in s2.
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stddef.h>
ptrdiff_t any( const char *s1, const char *s2 )
{
ptrdiff_t pos = -1;
for ( const char *p1 = s1; pos == -1 && *p1; ++p1 )
{
const char *p2 = s2;
while ( *p2 && *p2 != *p1 ) ++ p2;
if ( *p2 ) pos = p1 - s1;
}
return pos;
}
int main(void)
{
char w1[] = "Dominik";
char w2[] = "zcki";
printf( "%td\n", any( w1, w2 ) );
return 0;
}
The program output is
3
Indeed the first character from w1 that is present in w2 is the character 'i'. Pay attention to that positions start from 0.
#include <stdio.h>
#include <stdlib.h>
int any(char *s1, char *s2)
{
int koniec=0;
int j=0;
for (int i = 0; s1[i]!='\0'; i++)
{j=0;
while(s1[i]!=s2[j]&&s2[j]!='\0')
{
j++;
}
if(s2[j]!='\0')
{
return j;
}
}
return -1;
}
int main()
{
char w1[] = "Dominik";
char w2[] = "zcki";
printf("%d\n", any(w1, w2));
return 0;
}
I tried to write a function that deletes each character in string s1 that matches any character in the string s2.
Here is the testing code for the squeeze method.
#include <stdio.h>
void squeeze(char s1[], char s2[]);
int main()
{
char s1[20] = "HelloWorld", s2[20] = "ol";
squeeze(s1, s2);
printf("%s\n", s1);
return 0;
}
void squeeze(char s1[], char s2[])
{
int i, j, k;
k = 0;
for (i = 0; s1[i] != '\0'; ++i) {
for (j = 0; s2[j] != '\0'; ++j) {
if (s1[i] != s2[j])
s1[k++] = s1[i];
}
}
s1[k] = '\0';
}
When I run this code, terminal always gives Segmentation fault: 11.
Could anyone please give me any hints why this happens?
Example:
#include <stdio.h>
static int found(char *str, char c) { // return 1 if c is found in str
for (size_t i = 0; str[i] != '\0'; i++) {
if (str[i] == c) {
return 1;
}
}
return 0;
}
static void squeeze(char *a, char *b) {
size_t k = 0;
for (size_t i = 0; a[i] != '\0'; i++) { // use size_t to iterate on a c-string
if (found(b, a[i]) != 1) {
a[k++] = a[i]; // copy only if a[i] is not in b
}
}
a[k] = '\0';
}
int main(void) {
char a[] = "HelloWorld"; // you should let auto size
char b[] = "ol"; // and separate declaration
squeeze(a, b);
printf("%s\n", a);
}
Problem with your code is s1[k++] = s1[i];
Try to use new array
See Following Code
#include<stdio.h>
char *squeeze(char s1[], char s2[]);
int main()
{
char s1[20] = "HelloWorld", s2[20] = "olH";
squeeze(s1, s2);
return 0;
}
char *squeeze(char s1[], char s2[])
{
int i, j, k;
k = 0;
char arr[100]; // new array
int flag = 0;
for (i = 0; s1[i] != '\0'; i++) {
flag = 0;
for (j = 0; s2[j] != '\0'; ++j) {
if (s1[i] == s2[j])
{
flag = 1;
break;
}
}
if (flag == 0)
{
arr[k++] = s1[i];
}
}
arr[k] = '\0';
printf("%s",arr);
}
I am currently learning C with the book "Programming in C 3rd edition" by Stephen G. Kochan.
The exercise require that I make a function that replaces a character string inside a character string with another character string. So the function call
replaceString(text, "1", "one");
Will replace, if exist, "1" in the character string text with "one".
To fullfill this exercise, you need the functions findString(), insertString() and removeString().
This is the findString() function
int findString (const char source[], const char s[])
{
int i, j;
bool foundit = false;
for ( i = 0; source[i] != '\0' && !foundit; ++i )
{
foundit = true;
for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;
if (foundit)
return i;
}
return -1;
}
If s[] is inside the string source[], it returns an integer equal to the starting point for s[] inside the string. If it do not find s[] it will return -1.
The insertString() function is as follows
void insertString (char source[], char s[], int index)
{
int stringLength (char string[]);
int j, lenS, lenSource;
lenSource = stringLength (source);
lenS = stringLength (s);
if ( index > lenSource )
return;
for ( j = lenSource; j >= index; --j )
source[lenS + j] = source[j];
for ( j = 0; j < lenS; ++j )
source[j + index] = s[j];
}
This function take three arguments i.e. source[], s[] and index[]. s[] is the string that I would like to put into source[] and index[] is where it should start (e.g. insertString("The son", "per", 4) makes the source string to "The person").
The function includes another function called stringLength(), which purpose is the same at its name. This is stringLength()
int stringLength (char string[])
{
int count = 0;
while ( string[count] != '\0' )
++count;
return count;
}
The removeString() takes three arguments i.e. word, i and count. The function removes a number of characters inside another character string. This function I have not yet been able to make.
Just to sum it up, my question is:
How do i make the function replaceString(), which looks for a word in a character string, and if it is there, then it replaces it with another?
This has really bugged me for some time, and I would really appreciate your help on this.
UPDATE
This is the code I have made so far
// replaceString() program
#include <stdio.h>
#include <stdbool.h>
int findString (char source[], char s[])
{
int i, j;
bool foundit = false;
for ( i = 0; source[i] != '\0' && !foundit; ++i )
{
foundit = true;
for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;
if (foundit)
return i;
}
return -1;
}
int stringLength (char string[])
{
int count = 0;
while ( string[count] != '\0' )
++count;
return count;
}
void replaceString(char source[], char str1[], char str2[])
{
int findString(char source[], char s[]);
int stringLength(char string[]);
int start;
if ( findString(source, str1) == -1 )
return;
else
{
start = findString(source, str1);
int lenSource = stringLength(source);
int lenStr2 = stringLength(str2);
int counter = lenStr2;
for ( lenSource; lenSource > start + lenStr2; --lenSource )
{
source[lenSource + lenStr2] = source[lenSource];
}
int i = 0;
while ( i != counter )
{
source[start + i] = str2[i];
++i;
}
}
}
int main (void)
{
void replaceString(char source[], char str1[], char str2[]);
char string[] = "This is not a string";
char s1[] = "not";
char s2[] = "absolutely";
printf ("Before: \n %s \n\n", string);
replaceString(string, s1, s2);
printf ("After: \n %s \n\n", string);
return 0;
}
This code gives the following output:
Before:
This is not a string
After:
This is absolutelyng
As you can see, I have not included the removeString function(), as I could not get that function working properly. Where is the error in my program?
for starters, your string's length is fixed. so if the "destination" is longer than "source", then it won't work. insert string needs to pass in a pointer, then you can allocate a string on the heap that is long enough to contain length(source)-length(remove) +length(add), and return that pointer
Say your replaceString() args are (char source[], char s1[], char replacement[])
You need to use findString() to find s1 in source. If it finds it, given the position of s1, use removeString() to remove that string and then insertString() to insert replacement into that position.
I am also a newbie in programming. I came across this same exercise some days ago and just solved it today.
This is my code.
/* Programme to replace a string by using find, remove and insert
functions ex9.8.c */
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX 501
// Function prototypes
void read_Line (char buffer[]);
int string_Length (char string[]);
int find_String (char string1[], char string2[]);
void remove_String (char source[], int start, int number);
void insert_String (char source[], int start, char input[]);
void replace_String (char origString[], char targetString[], char substString[]);
bool foundFirstCharacter = false;
int main(void)
{
printf("This is a programme to replace part of a string.\n");
printf("It can only handle up to 500 characters in total!\n");
char text[MAX];
bool end_Of_Text = false;
int textCount = 0;
printf("\nType in your source text.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(text);
if (text[0] == '\0')
{
end_Of_Text = true;
}
else
{
textCount += string_Length(text);
}
break;
}
// Declare variables to store seek string parameters
int seekCount = 0;
char seekString[MAX];
printf("\nType in the string you seek.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(seekString);
if (seekString[0] == '\0')
{
end_Of_Text = true;
}
else
{
seekCount += string_Length(seekString);
}
break;
}
// Declare variables to store replacement string parameters
int replCount = 0;
char replString[MAX];
printf("\nType in the replacement string.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(replString);
if (replString[0] == '\0')
{
end_Of_Text = true;
}
else
{
replCount += string_Length(replString);
}
break;
}
// Call the function
replace_String (text, seekString, replString);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to find index of sub-string
int find_String (char string1[], char string2[])
{
int i, j, l;
int start;
int string_Length (char string[]);
l = string_Length(string2);
for (i = 0, j = 0; string1[i] != '\0' && string2[j] != '\0'; ++i)
{
if (string1[i] == string2[j])
{
foundFirstCharacter = true;
++j;
}
else
{
j = 0;
}
}
if (j == l)
{
start = i - j + 1;
return start;
}
else
{
return j - 1;
}
}
// Function to remove characters in string
void remove_String (char source[], int start, int number)
{
int string_Length (char string[]);
int i, j, l;
char ch = 127;
l = string_Length(source);
j = start + number;
for (i = start; i < j; ++i)
{
if (i >= l)
{
break;
}
source[i] = ch;
}
//printf("\nOutput: %s\n", source);
}
// Function to insert characters in string
void insert_String (char source[], int start, char input[])
{
int string_Length (char string[]);
int i, j, k, l, m;
int srcLen;
int inpLen;
int totalLen;
int endInsert;
srcLen = string_Length(source);
inpLen = string_Length(input);
// Declare buffer array to hold combined strings
totalLen = srcLen + inpLen + 3;
char buffer[totalLen];
// Copy from source to buffer up to insert position
for (i = 0; i < start; ++i)
buffer[i] = source[i];
// Copy from input to buffer from insert position to end of input
for (j = start, k = 0; k < inpLen; ++j, ++k)
buffer[j] = input[k];
endInsert = start + inpLen;
for (m = start, l = endInsert; m <= srcLen, l < totalLen; ++m, ++l)
buffer[l] = source[m];
buffer[l] = '\0';
printf("\nOutput: %s\n", buffer);
}
// Function to replace string
void replace_String (char origString[], char targetString[], char substString[])
{
// Function prototypes to call
void read_Line (char buffer[]);
int string_Length (char string[]);
int find_String (char string1[], char string2[]);
void remove_String (char source[], int start, int number);
void insert_String (char source[], int start, char input[]);
// Search for target string in source text first
int index;
index = find_String (origString, targetString);
if (index == -1)
{
printf("\nTarget string not in text. Replacement not possible!\n");
exit(999);
}
// Remove found target string
int lengthTarget;
lengthTarget = string_Length(targetString);
remove_String(origString, index - 1, lengthTarget);
// Insert replacement string
insert_String(origString, index, substString);
}