Number of times one string occurs within another in C - c

I have written a function that uses the strstr() function to determine if string2 has any matches in string1. This works fine (I also convert both strings to lower case so that I can do a case-insensitive match.). However, strstr() only finds the first time the match occurs. Is there a way to use it to find each time a match occurs? For example:
string1[] = "ABCDEFABC";
string2[] = "ABC";
Would return 0 as a match is found in position 0, and 6 as it's found again in position 6?
Here's the original function as written (including call to function in main):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strstrnc(const char *str1, const char *str2);
int main()
{
char buf1[80],buf2[80];
printf("Enter the first string to be compared: ");
gets(buf1);
printf("Enter the second string to be compared: ");
gets(buf2);
strstrnc(buf1,buf2);
return 0;
}
char *strstrnc(const char *buf1, const char *buf2)
{
char *p1, *ptr1, *p2, *ptr2, *loc;
int ctr;
ptr1 = malloc(80 * sizeof(char));
ptr2 = malloc(80 * sizeof(char));
p1 = ptr1;
p2 = ptr2;
for (ctr = 0; ctr < strlen(buf1);ctr++)
{
*p1++ = tolower(buf1[ctr]);
}
*p1 = '\0';
for (ctr = 0; ctr < strlen(buf2);ctr++)
{
*p2++ = tolower(buf2[ctr]);
}
*p2 = '\0';
printf("The new first string is %s.\n", ptr1);
printf("The new first string is %s.\n", ptr2);
loc = strstr(ptr1,ptr2);
if (loc == NULL)
{
printf("No match was found!\n");
}
else
{
printf("%s was found at position %ld.\n", ptr2, loc-ptr1);
}
return loc;
}

Given
char string1[] = "ABCDEFABC";
char string2[] = "ABC";
strstr(string1, string2) will return a pointer to the first element of string1.
Would return 0 as a match is found in position 0, and 6 as it's found again in position 6?
In order to check for multiple occurrences of string2 in string1, you'll have to call strstr multiple times with an offset from string1. E.g.
char* found = strstr(string1, string2);
while ( found != NULL )
{
// Search for string2 after applying an offset.
int offset = 1;
found = strstr(found+offset, string2);
}

I think this is what you need:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void){
char string1[] = "ABCDABCEFABC";
char string2[] = "ABC";
char *s1, *s2, *s3;
size_t lenstring1 = strlen(string1);
size_t lenstring2 = strlen(string2);
if (lenstring2 < 1){
printf("There is no substring found"); /* or what ever */
exit(1);
}
size_t i=0,j=0;
int found=0;
s1 = string1;
s2 = string2;
for(i = 0; i < lenstring1; i++){
if(*s1 == *s2){
s3 = s1;
for(j = 0;j < lenstring2;j++){
if(*s3 == *s2){
s3++;s2++;
}else{
break;
}
}
s2 = string2;
if(j == strlen(string2)){
found = 1;
printf("%s found at index : %zu\n",string2,i+1);
}
}
s1++;
}
if(found == 0){
printf("No match Found");
}
return 0;
}
Output:
ABC found at index : 1
ABC found at index : 5
ABC found at index : 10
If the string2 is empty you will get:
There is no substring found

Related

Replace words in sentence

I am trying to make a function in C where the function has to replace given word with another given word in sentence. This is my code but it does not work:
#include <stdio.h>
#include <string.h>
void repl(char* sentence, char* thiss, char* change_to_this) {
int i = 0;
int j = 0;
int length_thiss = strlen(thiss);
int length_change_to_this = strlen(change_to_this);
while (sentence[i] != 0) {
if (sentence[i] == this[j]) {
int init = i;
while (sentence[init] == thiss[j] && thiss[j] != 0)
{
j++;
init++;
}
if (thiss[j] == 0) {
j -= length_thiss;
for (int m = 0; m < length_thiss; m++) {
sentence[i] = change_to_this[m];
}
j = 0;
}
i++;
}
}
}
This should be result:
char sent[] = "My name is John and I am thirty years old.";
char name1[] = "John";
char name2[] = "Rick";
char age1[] = "thirty";
char age2[] = "fifty";
replace(sent, name1, name2);
replace(sent, age1, age2);
printf("result: %s\n", a); // My name is Rick and I am fifty years old.
Length of thiss is at least the same as the length of change_to_this. I cannot include any other libraries except those 2 I already included. Any ideas how to correct the code, please?
if you use string functions it can be archived much easier
char *repl(char *haystack, const char *needle, const char *repl)
{
size_t hLen = strlen(haystack), nLen = strlen(needle), rLen = strlen(repl);
char *pos, *nhs = haystack;
while((pos = strstr(nhs, needle)))
{
memmove(pos + rLen, pos + nLen, hLen - (pos - haystack) - nLen + 1);
memcpy(pos, repl, rLen);
nhs = pos + rLen;
}
return haystack;
}
int main()
{
char sent[] = "My name is Johnatan and I am thirty years old.";
char name1[] = "Johnatan";
char name2[] = "Rich";
char age1[] = "thirty";
char age2[] = "fifty five";
repl(sent, name1, name2);
printf("result: %s\n", sent); // My name is Rick and I am fifty years old.
repl(sent, age1, age2);
printf("result: %s\n", sent); // My name is Rick and I am fifty years old.
}
https://godbolt.org/z/2fK3XY
In my another answers you will find all the functions used written by hand
EDIT
As in the deleted comment - amended to replace all occurrences.
the caller is responsible for the size of the haystack.

Print with junk values,c

I'm having a problem and I can not figure out why.
In main I create 2 arrays of strings.
The function accepts 2 strings and creates a new array of the appropriate size according to the following requirement:
For example:
Array 1: aviv ,
Array 2: 12 ,
The new array: a12v12i12v
The new array must be exactly the size!
And then send the new array to main and main to print it.
I also print junk values.
I checked the size of the new array and it is the right size.
My code:
char* CreateString(char* str1, char* str2)
{
int length1, length2, length3 = 0;
int i,j, index_help = 0;
char *str3 = NULL;
length1 = strlen(str1);
length2 = strlen(str2);
for (i = 0; i < length1; i++) // Check the size of the new array
{
length3++;
if (i == (length1 - 1))
{
break;
}
for (j = 0; j < length2; j++)
{
length3++;
}
}
str3 = (char*)malloc(length3+1 * sizeof(char));
if (str3 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
for (i = 0; i < length1; i++) //Copying data
{
str3[index_help] = str1[i];
if (i == (length1 - 1))
{
break;
}
for (j = 0; j < length2; j++)
{
index_help++;
str3[index_help] = str2[j];
}
index_help++;
}
return str3;
}
int main()
{
char *str1 = NULL, *str2 = NULL,*str4=NULL;
int size1, size2,i;
printf("enter the size of string number 1:\n");
scanf("%d", &size1);
printf("enter the size of string number2 :\n");
scanf("%d", &size2);
str1 = (char*)malloc((size1 + 1) * sizeof(char));
if (str1 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
str2 = (char*)malloc((size2 + 1) * sizeof(char));
if (str2 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
printf("Enter a value for the first string (the size is:%d):\n", size1);
scanf("%s", str1);
printf("Enter a value for the second string (the size is:%d):\n", size2);
scanf("%s", str2);
str4 = CreateString(str1, str2);
printf("%s",str4);
printf("\n");
return 0;
}
The function should be declared like
char* CreateString( const char* str1, const char* str2);
because neither string str1 nor string str2 are changed in the function.
You have to append the result string with a terminating zero.
The length of the resulted string can be calculated simpler without using loops.
As the function strlen has the return type size_t then variables that accept the result of a function call should be also declared as having the type size_t instead of the type int.
The function can be implemented the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <string.h>
char * CreateString(const char *s1, const char *s2)
{
size_t n1 = strlen(s1);
size_t n2 = strlen(s2);
size_t n3 = n1 == 0 ? 0 : n1 + (n1 - 1) * n2;
char *s3 = ( char * )malloc(n3 + 1);
if (s3)
{
if (n2 == 0)
{
strcpy(s3, s1);
}
else
{
char *p = s3;
while (*s1)
{
*p++ = *s1++;
if (*s1)
{
strcpy(p, s2);
p += n2;
}
}
*p = '\0';
}
}
return s3;
}
int main( void )
{
char *p = CreateString("aviv", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("a", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("av", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("av", "");
printf("\"%s\"\n", p);
free(p);
return 0;
}
The program output is
"a12v12i12v"
""
"a"
"a12v"
"av"

hi i am writing a c program to get the position of a character in a given string

I am developing a code to return a position of a character in string.
I have removed all the error but when I run the program my compiler
crashes.
find a position in a given string
// int str_find_char(char *str, char *ch) -
// returns the position where ch is in str and if not present returns -1
#include <stdio.h>
char arr[5] = {'a','b','c','d','e'};
char d;
int str_find_char(char (*ptr),char *chr)
{
int i;
for(i=0; i<5; i++)
{
printf("h");
}
}
int main(void)
{
char (*ptr)[5];
char arr[5] = {'a','b','c','d','e'};
ptr = &arr;
int i,k=0;
char *chr;
char ch;
chr = &ch;
printf("enter the value to search = ");
scanf("%c",&ch);
str_find_char( (*ptr), chr);
if(*(ptr[i]) = ch)
{
printf("element found at = %d",i);
k = 1;
}
else if(k == 1)
{
printf("element found at = %d",i);
return 0;
}
else {
return -1;
}
}
First of all you said you search in a string that means it must be null terminated.
You can change
char arr[5] = {'a','b','c','d','e'};
to
char arr[] = "abcde";
and use the code below
int GetCharPos(char* str, char ch)
{
int i = 0;
int ret = -1;
while(*str){
if(*str++ == ch){
ret = i;
break;
}
i++;
}
return ret ;
}
Note that this code will work only if you pass a null terminated string.
Annti Haapala is right. Your compiler should be generating truckloads of warnings, among which should also be a few errors.
You should repeatedly check if you've found a matching character
int str_find_char(const char* str, char ch){
const char* p = str;
for(;*p;p++)
if(*p== ch)
return (p - str);
return -1;
}
...and as a good practice, use a const pointer if the function does not change the string.
Also notice UBs:
int i,k=0; // i is uninitialized
char *chr;
char ch;
chr = &ch;
printf("enter the value to search = ");
scanf("%c",&ch);
str_find_char( (*ptr), chr);
if(*(ptr[i]) = ch) // Use an uninitialized variable?
{ // Now exit with Segmentation fault!

Reversing String in C for loop error

I have an array of strings and am trying to reverse each string in the array to see if that string is a palindrome. I am using a for loop to increment an int i (the index). However after the I call the reverse function, the value of i becomes some really large number and I cant figure out why this is happening.
#include <stdio.h>
#include <string.h>
void revString(char *dest, const char *source);
int main() {
const char *strs[] = {
"racecar",
"radar",
"hello",
"world"
};
int i;
char res[] = "";
for (i = 0; i < strlen(*strs); i++) {
printf("i is %d\n", i);
revString(&res[0], strs[i]); //reversing string
printf("i is now %d\n", i);
//comparing string and reversed string
if (strcmp(res, strs[i]) == 0) {
printf("Is a palindrome");
} else {
printf("Not a palindrome");
}
}
return 0;
}
void revString(char *dest, const char *source) {
printf("%s\n", source);
int len = strlen(source);
printf("%d\n", len);
const char *p;
char s;
for (p = (source + (len - 1)); p >= source; p--) {
s = *p;
*(dest) = s;
dest += 1;
}
*dest = '\0';
}
This is the output showing the value of i before and after the revString function is called.
i is 0
i is now 1667588961
Illegal instruction: 4
There are multiple problems in your code:
You pass a destination array char res[] = ""; that is much too small for the strings you want to reverse. It's size is 1. This causes buffer overflow, resulting in undefined behavior.
Use char res[20]; instead.
You enumerate the array of string with an incorrect upper bound. Use this instead:
for (i = 0; i < sizeof(strs) / sizeof(*strs); i++)
The termination test for the loop in revString() is incorrect too: decrementing p when is equal to source has undefined behavior, although it is unlikely to have an consequences. You can simplify this function this way:
void revString(char *dest, const char *source) {
size_t len = strlen(source);
for (size_t i = 0; i < len; i++) {
dest[i] = source[len - i - 1];
}
dest[len] = '\0';
}
Here is the resulting code:
#include <stdio.h>
#include <string.h>
void revString(char *dest, const char *source) {
size_t len = strlen(source);
for (size_t i = 0; i < len; i++) {
dest[i] = source[len - i - 1];
}
dest[len] = '\0';
}
int main(void) {
const char *strs[] = { "racecar", "radar", "hello", "world" };
char res[20];
for (size_t i = 0; i < sizeof(strs) / sizeof(*strs); i++) {
revString(res, strs[i]);
//comparing string and reversed string
if (strcmp(res, strs[i]) == 0) {
printf("Is a palindrome\n");
} else {
printf("Not a palindrome\n");
}
}
return 0;
}
Here is Final Code with some change
#include <stdio.h>
#include <string.h>
void revString(char* dest, const char* source);
int main(){
const char* strs[] = {
"racecar",
"radar",
"hello",
"world"
};
static int i;
char res[] = "";
int length = (int) sizeof(strs)/sizeof(char*);
for(i = 0; i < length; i++)
{
printf("i is %d\n", i);
revString(&res[0], strs[i]); //reversing string
printf("i is now %d\n", i);
//comparing string and reversed string
if(strcmp(res, strs[i]) == 0){
printf("Is a palindrome");
}else{
printf("Not a palindrome");
}
}
return 0;
}
void revString(char* dest, const char* source){
printf("%s\n", source);
int len = (int) strlen(source);
printf("%d\n", len);
const char* p;
char s;
for(p = (source + (len - 1)); p >= source; p--){
s = *p;
*(dest) = s;
dest += 1;
}
*dest = '\0';
}
Change 1 :-
int i; to static int i; (Reason:- i is local variable you are calling
function so when function call the value of i will remove and after
that it will assign garbage value.)
change 2 :-
strlen(*strs) to length of array (because strlen(*strs) will give the
length of first string)

find the count of substring in string

I have to find the count of a substring in a string using the C language.
I'm using the function strstr but it only finds the first occurrence.
My idea of the algorithm is something like searching in the string while strstr does not return null and
to substring the main string on each loop.
My question is how to do that?
You could do something like
int countString(const char *haystack, const char *needle){
int count = 0;
const char *tmp = haystack;
while(tmp = strstr(tmp, needle))
{
count++;
tmp++;
}
return count;
}
That is, when you get a result, start searching again at the next position of the string.
strstr() doesn't only work starting from the beginning of a string but from any position.
Should already processed parts of the string should be consumed or not?
For example, what's the expect answer for case of searching oo in foooo, 2 or 3?
If the latter (we allow substring overlapping, and the answer is three), then Joachim Isaksson suggested the right code.
If we search for distinct substrings (the answer should be two), then see the code below (and online example here):
char *str = "This is a simple string";
char *what = "is";
int what_len = strlen(what);
int count = 0;
char *where = str;
if (what_len)
while ((where = strstr(where, what))) {
where += what_len;
count++;
}
USE KMP and you can do it in O(n)
int fail[LEN+1];
char s[LEN];
void getfail()
{
//f[i+1]= max({j|s[i-j+1,i]=s[0,j-1],j!=i+1})
//the correctness can be proved by induction
for(int i=0,j=fail[0]=-1;s[i];i++)
{
while(j>=0&&s[j]!=s[i]) j=fail[j];
fail[i+1]=++j;
if (s[i+1]==s[fail[i+1]]) fail[i+1]=fail[fail[i+1]];//optimizing fail[]
}
}
int kmp(char *t)// String s is pattern and String t is text!
{
int cnt=0;
for(int i=0,j=0;t.s[i];i++)
{
while(j>=0&&t.s[i]!=s[j]) j=fail[j];
if (!s[++j])
{
j=fail[j];
cnt++;
}
}
return cnt;// how many times s appeared in t.
}
The results can be different depending whether you allow an overlap or not:
// gcc -std=c99
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
static int
count_substr(const char *str, const char* substr, bool overlap) {
if (strlen(substr) == 0) return -1; // forbid empty substr
int count = 0;
int increment = overlap ? 1 : strlen(substr);
for (char* s = (char*)str; (s = strstr(s, substr)); s += increment)
++count;
return count;
}
int main() {
char *substrs[] = {"a", "aa", "aaa", "b", "", NULL };
for (char** s = substrs; *s != NULL; ++s)
printf("'%s' -> %d, no overlap: %d\n", *s, count_substr("aaaaa", *s, true),
count_substr("aaaaa", *s, false));
}
Output
'a' -> 5, no overlap: 5
'aa' -> 4, no overlap: 2
'aaa' -> 3, no overlap: 1
'b' -> 0, no overlap: 0
'' -> -1, no overlap: -1
Assuming s and substr are non-null and non-empty:
/* #times substr appears in s, no overlaps */
int nappear(const char *s, const char *substr)
{
int n = 0;
const char *p = s;
size_t lenSubstr = strlen(substr);
while (*p) {
if (memcmp(p, substr, lenSubstr) == 0) {
++n;
p += lenSubstr;
} else
++p;
}
return n;
}
/*
* C Program To Count the Occurence of a Substring in String
*/
#include <stdio.h>
#include <string.h>
char str[100], sub[100];
int count = 0, count1 = 0;
void main()
{
int i, j, l, l1, l2;
printf("\nEnter a string : ");
scanf("%[^\n]s", str);
l1 = strlen(str);
printf("\nEnter a substring : ");
scanf(" %[^\n]s", sub);
l2 = strlen(sub);
for (i = 0; i < l1;)
{
j = 0;
count = 0;
while ((str[i] == sub[j]))
{
count++;
i++;
j++;
}
if (count == l2)
{
count1++;
count = 0;
}
else
i++;
}
printf("%s occurs %d times in %s", sub, count1, str);
}

Resources