Strings of characters using pointers - c

I'm trying to write a function which changes letters into two asterisks (*) using pointers.
For example:
Input: hello12345good++//--ok
Output: **********123456********++//--****
I've writen one that changes letters into two of the same letters, but couldn't write the same for *.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int points_converter(char str[])
{
char *s, *s1;
int f = 0;
for (s = str; *s; s++)
{
if(isalpha(*s))
{
f = 1;
s1 = s;
s = s + strlen(s);
while(s != s1 - 1)
*(s+1) = *(s--);
s = s + 2;
}
}
return f;
}
int main()
{
char str[81];
int f;
puts("Input string:");
while (strlen(gets(str)) >= 81);
f = points_converter(str);
if (f == 0)
{
puts("No latin letters in string.");
}
else
{
puts("New string: ");
puts(str);
}
return 0;
}

like this
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
bool points_converter(char str[]){
bool f = false;
char *temp = malloc(strlen(str)*2+1);
char *s = str, *d = temp;
if(!temp){
perror("malloc:");
return f;//no change
}
for (; *s; s++){
if(isalpha((unsigned char)*s)){
f = true;
*d++ = '*';
*d++ = '*';
} else {
*d++ = *s;
}
}
*d = 0;
strcpy(str, temp);//`str` must have enough spaces.
free(temp);
return f;
}
#define MAX_LENGTH 40
int main(void){
char str[MAX_LENGTH * 2 + 1];
while(true){
puts("Input string:");
fgets(str, MAX_LENGTH+1+1, stdin);//+1:newline, +1:NUL. Use fgets instead of gets
char *p = strchr(str, '\n');
if(p){
*p = '\0';//chomp newline
break;
} else {
while (getchar() != '\n');//Input too long, clear input
}
}
if (points_converter(str)) {
puts("New string: ");
puts(str);
} else {
puts("No latin letters in string.");
}
return 0;
}

how about:
static const int MAXINPUTLEN=81;
int points_converter(const char* input, char *output)
{
int count = 0; // initialize counter to zero
while (*input) { // while input is not pointing to zero
if (isalpha(*input)) { // if input is pointing to alpha
output[0] = '*'; // replace first byte pointed to by output with '*'
output[1] = '*'; // replace 2nd byte pointed to by output with '*'
output += 2; // increment output by 2
count++; // increment counter
} else {
*output = *input; // copy non-alpha to output
output++; // increment output by one
}
input++; // increment input pointer by one
}
*output = 0; // terminate output with zero byte
return count; // return count
}
int main()
{
char input[MAXINPUTLEN + 1];
char output[2 * MAXINPUTLEN + 1];
gets(input); // not checking for input overflow!
points_converter(input, output);
}

Related

Why is my solution for Super Reduced String(HackerRank) question working fine on my computer but giving wrong answers in HackerRank?

When I run my code in Hackerrank it fails 6/16 test cases but when I try the same test cases on my computer it works fine.
This is the code that I run on my computer:(I use Clion as ide and the latest MinGW as compiler.)
I initialize the string with one of the test cases that fail on HackerRank.
#include <string.h>
#include <stdio.h>
//#include <stdlib.h>
char* superReducedString(char* s);
int contain(char *S,char find);
void copyWithout(char *S,char *T,char trash);
int countWithout(char *S,char trash);
int findSize(char *S);
void fillString(char *S,char filler);
int main(){
char s[] = {"ppffccmmssnnhhbbmmggxxaaooeeqqeennffzzaaeeyyaaggggeessvvssggbbccnnrrjjxxuuzzbbjjrruuaaccaaoommkkkkxx"};
char *result = superReducedString(s);
printf("%s",result);
}
int findSize(char *S){
int i = 0;
while(*(S+i) != '\0'){
i++;
}
return i;
}
void fillString(char *S,char filler){
int i = 0;
while(*(S+i) != '\0'){
*(S+i) = filler;
i++;
}
}
void copyWithout(char *S,char *T,char trash){
fillString(T,'0');
int i = 0;
int count = 0;
while(*(S+i) != '\0'){
if(*(S+i) != trash){
*(T+count) = *(S+i);
count++;
}
i++;
}
}
int countWithout(char *S,char trash){
int i = 0;
int count = 0;
while(*(S+i) != '\0'){
if(*(S+i) != trash){
count++;
}
i++;
}
return count;
}
int contain(char *S,char find){
int i = 0;
int flag = 0;
while(*(S+i) != '\0'){
if(*(S+i) == find){
flag = 1;
}
i++;
}
return flag;
}
char* superReducedString(char* s){
static char empty[] = "Empty String";
static char result[1024];
int flag = 1;
char temp[findSize(s)];
fillString(temp,'0');
int i,j;//Loop variable.
i = 0;
while(*(s + i) != '\0'){
j = 0;
//Checking if adjacent numbers is same. If it is changing them to '0'.
while(s[j] != '\0') {
if (s[j] == s[j + 1]) {
*(s + j) = '0';
*(s + j + 1) = '0';
}
j++;
}
if(contain(s,'0') == 0){ //If there is no zero in original string that means nothing changed.
return s;
}else{
copyWithout(s,temp,'0');//If there are zeros in it, copy it to a temp char array without zeros.
}
strcpy(s,temp);//Copy temp to s again for swapping.
i++;
}
int count = countWithout(s,'0'); //Calculate the size of original string without zeros.
char finalString[count];//Initialize a new string with the calculated size.
copyWithout(s,finalString,'0'); //Copy original string to finalString without zeros to obtain a clear zeroless string.
strcpy(result,finalString);//copy finalstring to static result string to return it.
i = 0;
while(*(result+i) != '\0'){ //Check if result string consists of zeroes. If it is code will return empty string.
if(*(result+i) != '0'){
flag = 0;
}
i++;
}
if(flag == 0){
return result;
}else{
return empty;
}
}
and this is the code that I run on HackerRank:
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* superReducedString(char* s);
int contain(char *S,char find);
void copyWithout(char *S,char *T,char trash);
int countWithout(char *S,char trash);
int findSize(char *S);
void fillString(char *S,char filler);
char* readline();
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
char* s = readline();
char* result = superReducedString(s);
fprintf(fptr, "%s\n", result);
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) {
break;
}
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') {
break;
}
alloc_length <<= 1;
data = realloc(data, alloc_length);
if (!data) {
data = '\0';
break;
}
}
if (data[data_length - 1] == '\n') {
data[data_length - 1] = '\0';
data = realloc(data, data_length);
if (!data) {
data = '\0';
}
} else {
data = realloc(data, data_length + 1);
if (!data) {
data = '\0';
} else {
data[data_length] = '\0';
}
}
return data;
}
int findSize(char *S){
int i = 0;
while(*(S+i) != '\0'){
i++;
}
return i;
}
void fillString(char *S,char filler){
int i = 0;
while(*(S+i) != '\0'){
*(S+i) = filler;
i++;
}
}
void copyWithout(char *S,char *T,char trash){
fillString(T,'0');
int i = 0;
int count = 0;
while(*(S+i) != '\0'){
if(*(S+i) != trash){
*(T+count) = *(S+i);
count++;
}
i++;
}
}
int countWithout(char *S,char trash){
int i = 0;
int count = 0;
while(*(S+i) != '\0'){
if(*(S+i) != trash){
count++;
}
i++;
}
return count;
}
int contain(char *S,char find){
int i = 0;
int flag = 0;
while(*(S+i) != '\0'){
if(*(S+i) == find){
flag = 1;
}
i++;
}
return flag;
}
char* superReducedString(char* s){
static char empty[] = "Empty String";
static char result[1024];
int flag = 1;
char temp[findSize(s)];
fillString(temp,'0');
int i,j,k;//Loop variable.
i = 0;
while(*(s + i) != '\0'){
j = 0;
while(s[j] != '\0') {
if (s[j] == s[j + 1]) {
*(s + j) = '0';
*(s + j + 1) = '0';
}
j++;
}
if(contain(s,'0') == 0){
return s;
}else{
// printf("temp0 = %s s0 = %s\n",temp,s);
copyWithout(s,temp,'0');
// printf("temp1 = %s s1 = %s\n",temp,s);
}
//printf("%s\n",temp);
strcpy(s,temp);
i++;
}
int count = countWithout(s,'0');
char finalString[count];
copyWithout(s,finalString,'0');
strcpy(result,finalString);
i = 0;
while(*(result+i) != '\0'){
if(*(result+i) != '0'){
flag = 0;
}
i++;
}
if(flag == 0){
return result;
}else{
return empty;
}
}
The only difference is main function and the functions that HackerRank uses for getting input.
I don't know if this helps but sometimes my code can give wrong answers for same input.
What I mean is:
input = "acdqglrfkqyuqfjkxyqvnrtysfrzrmzlygfveulqfpdbhlqdqrrqdqlhbdpfqluevfgylzmrzrfsytrnvqyxkjfquyqkfrlacdqj"
While it should give "acdqgacdqj" as answer, it gives "acdqgacdqjÑ"
The last char randomly changes.
But for other inputs no matter how many times I run it it gives the correct answer on my computer.
char temp[findSize(s)]; fillString(temp,'0'); is invalid. In fillString you iteratate until the element is equal to '\0'. temp is uninitialized - you can't expect it to have any certain value (and even reading an uninitialized value is undefined behavior).
In char finalString[count]; count is too small - it doesn't account for zero terminating character. copyWithout(s,finalString,'0'); is not copying zero terminating character. Which results in strcpy(result,finalString); accessing array out-of-bounds when searching for.... zero terminating character.
When working with C string you usually see a magical + 1 everywhere in the code.
Advices:
Prefer not use variable length arrays (arrays where the size expression is not a constant expression). Prefer using dynamic allocation.
findSize is just strlen...
fillString is just memset(string, value, strlen(string));
When using a compiler, always enable all options. When using gcc, you could use gcc -g -Wall -Wextra -fsanitize=address sourcefile.c - sanitize will allow to really fast find all out-of-bounds accesses on stack variables. Use valgrind to find dynamic allocation leaks.
I advise to change order of argument in copyWithout to (destination, source, fill) so it's the same as strcpy(destination, source) - ie. destination is first.
Seems like fixing parts of code to:
char* superReducedString(char* s){
...
// char temp[findSize(s)];
char temp[findSize(s) + 1];
// fillString(temp,'0');
memset(temp, '0', findSize(s));
temp[findSize(s)] = '\0';
...
char finalString[count + 1];//Initialize a new string with the calculated size.
memset(finalString, '0', count);
finalString[count] = '\0';
}
is enough for me to -fsanitize to stop erroring.
I have no idea where exactly your bug is, but it is quite clear from the output that you are using uninitialised memory. And on your computer, that uninitialised memory contains a zero by pure coincidence, and on the computer used for the test it doesn't.
Generally if you have a problem "it works on computer A but not on computer B" then very often undefined behaviour in your code is the answer, and here it is most like uninitialised memory.

Code can't get an n-digit numbers from a string in C

I wanna ask how it can not get integer from a string
for example, here are my code:
int main() {
char str[] = "ababbababa-1998";
int nr = atoi(str);
printf("%d\n", nr);
return (EXIT_SUCCESS);
}
when running, it print out 0 but not 1998, how can I fix it ?
In your case you can use strtok.
int main() {
char str[] = "ababbababa-1998";
char * const first_part = strtok(str, "-");
if (first_part == NULL) {
return 1;
}
char * const second_part = strtok(NULL, "-");
if (second_part == NULL) {
return 1;
}
int nr = atoi(second_part);
printf("%d\n", nr);
return 0;
}
You can look at Why is there no strtoi in stdlib.h? for error check atoi.
Keep walking down str() until code finds something numeric using strtol().
int main() {
char str[] = "ababbababa-1998";
char *p = str;
char *endptr;
while (*p) {
long number = strtol(p, &endptr, 10);
// Was conversion successful?
if (endptr != p) {
printf("%ld\n", number);
return EXIT_SUCCESS;
}
p++;
}
puts("No conversion");
return EXIT_FAILURE;
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ASCII '0'
int
main(void) {
char const str[] = "ababbababa-1998";
int i, result = 0;
for (i = 0; str[i]; i++) {
if (isdigit(str[i])) {
result *= 10;
result += str[i] - ASCII;
}
}
printf("number = %d\n", result);
return 0;
}
If you want to extract all the numeric digits from a string you could use this function I created.
You will need these header files for this function to work.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void getNumbers(char data[]) {
int index = 0;
char current;
for( int i = 0; i < strlen(data); ++i ) {
current = data[i];
if (current >= 48 && current <= 57) {
data[index++] = current;
}
}
data[index] = '\0';
}
You can use the above function like this.
char foobar[] = "1A2B3C4D5E6F7G8H9I";
getNumbers(foobar);
printf("%s", foobar);
The above code will output 123456789

Reversing a two dimensional character array in C

i am trying to write a program which reverses a entire string and also may print reversing each word of the string more than one time.
For example my string is:
"2
Fox jumps over the lazy dog."
for this, the output should be:
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF.
I am trying to store each word in a 2d array and then reverse each word but i am not able to do that.
here is my code. kindly help
Note: how do we provide EOF in console
#include <stdio.h>
#include <stdlib.h>
int main() {
char string[100][100];
char ch;
int i = 0, j = 0, l = 0, count = 0, x = 0, y = 0;
while ((ch = getchar()) != EOF) {
string[i][l++] = ch;
if (ch == ' ') {
string[i][l] = '\n';
i++;
l = 0;
count++;
}
}
for (x = 0; x <= count; x++) {
int length = strlen(string[x]) - 1;
for (y = length; y >= 0; --y)
printf("%s", string[y]);
}
return 0;
}
Here are a few changes to your code check the comments for explanation.
int main()
{
char string[100][100];
char ch;
int i=0,j=0, l=0, count=0, x=0, y=0;
while((ch=getchar())!=EOF)
{
string[i][l++] = ch;
if(ch==' ')
{
string[i][l] = '\0'; //make the string null terminated otherwise you cant work with its length
i++;
l=0;
count++;
}
}
string[i][l]='\0'; //make the last string null terminated
for(x=count; x>=0; x--) //read from last counter
{
int length = strlen(string[x])-1;
for(y=length; y>=0; --y)
{
printf("%c", string[x][y]); //print by each character and not string.
}
}
return 0;
}
Corrections in your code:
C strings are null terminated, but you are terminating your strings with newline \n character, which is wrong.
You are storing the whitespace with the string, reversing will be difficult in this case.
Your print statement won't reverse the string, print it character by character.
For the output that you need, you can consider this code.
#include <stdio.h>
#include <stdlib.h>
int main() {
char string[100][100];
char ch;
int i = 0, j = 0, l = 0, count = 0, x = 0, y = 0;
while ((ch = getchar()) != EOF) {
if (ch == ' ') {
string[i][l] = '\0'; /// Null terminate the string
i++;
l = 0;
count++;
}
else
string[i][l++] = ch; /// Don't add whitespace to the string
}
string[i][l] = '\0';
for (x = count; x >= 0; x--) {
int length = strlen(string[x]) - 1;
for (y = length; y >= 0; --y)
printf("%c", string[x][y]); /// Print the string in reverse
printf(" ");
for (y = length; y >= 0; --y)
printf("%c", string[x][y]); /// Twice
printf(" ");
}
return 0;
}
Input
2 Fox jumps over the lazy dog.
Output
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF 2 2
See http://ideone.com/qaIoW9
If I understand you want to duplicate each reversed word N times as specified by the first number in the string, then something like the following would work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *strrevdup (char* str);
int main (int argc, char **argv) {
if (argc < 2 ) {
fprintf (stderr, "error: insufficient input, usage: %s \"# string\"\n",
argv[0]);
return 1;
}
char *str = strdup (argv[1]);
char *p = str;
char *rev = NULL;
int mult = 0;
int i = 0;
while (*p && *p != ' ') p++;
*p = 0;
mult = atoi (str);
*p = ' ';
if (!mult) return 1;
while (*p && *p == ' ') p++;
rev = strrevdup (p);
char *r = rev;
printf ("\n the reversed string with duplicated words '%d' times is:\n\n", mult);
for (p = strtok (r, " "); p; p = strtok (NULL, " \n"))
for (i = 0; i < mult; i++)
printf (" %s", p);
printf ("\n\n");
free (str);
free (rev);
return 0;
}
/** strrevdup - reverse duplicate string, swaps src & dest each iteration.
* Takes valid string, duplicates and reverses, original is preserved.
* Returns pointer to reversed string on success, NULL otherwise.
* Requires string.h, caller is responsible for freeing memory allocated.
*/
char *strrevdup (char* str)
{
if (!str) {
printf ("%s() error: invalid string\n", __func__);
return NULL;
}
char *rstr = strdup (str);
char *begin = rstr;
char *end = rstr + strlen (rstr) - 1;
char tmp;
while (end > begin){
tmp=*end;
*end-- = *begin;
*begin++ = tmp;
}
return rstr;
}
Output
$ ./bin/strrevndup "2 Fox jumps over the lazy dog."
the reversed string with duplicated words '2' times is:
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF
you may try this code although it will reverse and print words in different lines.. you may try few more things to get the desired answer.
` #include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
char string[1024][1024];
char ch;
int t,z;
scanf("%d",&t);
z=t;
int i=0, l=0, count=0, x=0, y=0;
getchar();
while((ch=getchar())!=EOF)
{
if(ch=='\n')
{
i++;
l=0;
count++;
string[i][l++] = ch;
i++;
l=0;
}
else if(ch==' ')
{
i++;
l=0;
count++;
}
else{
string[i][l++] = ch;
}
}
for(x=count+1; x>=0; x--)
{
if(string[x][0]=='\n')
{
printf("\n");
}
else{
char *rev=strrev(string[x]);
while(t--)
printf("%s ",rev);
t=z;
}
}
return 0;
}`

Loop with simple counter malfunctioning?

I have a program that takes a char array and calls the function convert. The function determines whether the character is a letter or number. The program is supposed to output the first letter it finds in the string. and the first numbers it finds in the string. My loop to stop looking for letters after it finds one isn't working.
Any thoughts?
Code is written in C using the Borland Compiler.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int convert (char array[],char **);
int main()
{
int intval;
char array[512], *charptr;
printf("Input a string that starts with a series of decimal digits:\n>");
while ( gets( array ) != NULL ){
intval = convert(array, &charptr );
printf ("Intval contains %d, Charptr contains '%s'\n", intval, charptr);
}
system("pause");
return 0;
}
int convert (char array[],char ** charptr)
{
int i, x, c = 0;
char b[512];
for (i=0;i<strlen(array);i++){
if (isalpha(array[i]))
{
if(c >= 1){
*charptr = &array[i];
c++;
}
else
break;
}
else if ( isdigit(array[i]))
x = 10*x + array[i] - '0';
}
return x;
}
UPDATE:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int convert (char array[],char ** charptr);
int main()
{
int intval;
char array[512], *charptr;
printf("Input a string that starts with a series of decimal digits:\n>");
while ( gets( array ) != NULL ){
intval = convert(array, &charptr );
printf ("Intval contains %d, Charptr contains '%s'\n", intval, charptr);
}
system("pause");
return 0;
}
int convert (char array[],char ** charptr)
{
int i, x, c;
char b[512];
for (i=0;array[i] != 0;i++){
if ( isdigit(array[i]))
x = 10*x + array[i] - '0';
else if (isalpha(array[i]))
{
c++;
if(c >= 1){
*charptr = &array[i];
}
}
}
return x;
}
You have a logic error. c is initialized to 0. There is a line to increment c but it is inside an if block that will never be true.
if(c >= 1){
*charptr = &array[i];
c++;
}
Catch 22???
Perhaps you meant to use:
int convert (char array[],char ** charptr)
{
int i, x, c = 0;
char b[512];
for (i=0;i<strlen(array);i++){
if (isalpha(array[i]))
{
// No need for checking the value of c
// return as soon you find an alphabet.
*charptr = &array[i];
break;
}
else if ( isdigit(array[i]))
// If you are looking for an alphabet only,
// why do you have this block of code???
x = 10*x + array[i] - '0';
}
return x;
}
Update
Perhaps, this is what you are looking for.
int convert (char array[], char ** charptr)
{
size_t i;
int x = 0;
size_t len = strlen(array);
// Set charptr to NULL in case there are no letters in the input.
*charptr = NULL;
for (i=0;i<len;i++){
if ( isalpha(array[i]))
{
*charptr = &array[i];
return x;
}
else if ( isdigit(array[i]))
{
x = 10*x + array[i] - '0';
}
}
return x;
}
int scanString(char array[],char * charptr)
{
int len = strlen(array);
int digs = 0;
int x = 0;
*charptr = 0;
for (int i=0;i<len;i++){
if (charptr == 0 && isalpha(array[i]))
{
*charptr = array[i];
}
else if (digs == 0 && isdigit(array[i])){
x = array[i] - '0';
digs = 1;
}
if(digs > 0 && charptr != 0)
break;
}
return x;
}
the spec says return the first character found so changed the charptr.

Check substring exists in a string in C

I'm trying to check whether a string contains a substring in C like:
char *sent = "this is my sample example";
char *word = "sample";
if (/* sentence contains word */) {
/* .. */
}
What is something to use instead of string::find in C++?
if (strstr(sent, word) != NULL) {
/* ... */
}
Note that strstr returns a pointer to the start of the word in sent if the word word is found.
Use strstr for this.
https://cplusplus.com/reference/cstring/strstr
So, you'd write it like..
char *sent = "this is my sample example";
char *word = "sample";
char *pch = strstr(sent, word);
if(pch)
{
...
}
Try to use pointers...
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "String1 subString1 Strinstrnd subStr ing1subString";
char sub[] = "subString";
char *p1, *p2, *p3;
int i=0,j=0,flag=0;
p1 = str;
p2 = sub;
for(i = 0; i<strlen(str); i++)
{
if(*p1 == *p2)
{
p3 = p1;
for(j = 0;j<strlen(sub);j++)
{
if(*p3 == *p2)
{
p3++;p2++;
}
else
break;
}
p2 = sub;
if(j == strlen(sub))
{
flag = 1;
printf("\nSubstring found at index : %d\n",i);
}
}
p1++;
}
if(flag==0)
{
printf("Substring NOT found");
}
return (0);
}
You can try this one for both finding the presence of the substring and to extract and print it:
#include <stdio.h>
#include <string.h>
int main(void)
{
char mainstring[]="The quick brown fox jumps over the lazy dog";
char substring[20], *ret;
int i=0;
puts("enter the sub string to find");
fgets(substring, sizeof(substring), stdin);
substring[strlen(substring)-1]='\0';
ret=strstr(mainstring,substring);
if(strcmp((ret=strstr(mainstring,substring)),substring))
{
printf("substring is present\t");
}
printf("and the sub string is:::");
for(i=0;i<strlen(substring);i++)
{
printf("%c",*(ret+i));
}
puts("\n");
return 0;
}
And here is how to report the position of the first character off the found substring:
Replace this line in the above code:
printf("%s",substring,"\n");
with:
printf("substring %s was found at position %d \n", substring,((int) (substring - mainstring)));
My own humble (case sensitive) solution:
uint8_t strContains(char* string, char* toFind)
{
uint8_t slen = strlen(string);
uint8_t tFlen = strlen(toFind);
uint8_t found = 0;
if( slen >= tFlen )
{
for(uint8_t s=0, t=0; s<slen; s++)
{
do{
if( string[s] == toFind[t] )
{
if( ++found == tFlen ) return 1;
s++;
t++;
}
else { s -= found; found=0; t=0; }
}while(found);
}
return 0;
}
else return -1;
}
Results
strContains("this is my sample example", "th") // 1
strContains("this is my sample example", "sample") // 1
strContains("this is my sample example", "xam") // 1
strContains("this is my sample example", "ple") // 1
strContains("this is my sample example", "ssample") // 0
strContains("this is my sample example", "samplee") // 0
strContains("this is my sample example", "") // 0
strContains("str", "longer sentence") // -1
strContains("ssssssample", "sample") // 1
strContains("sample", "sample") // 1
Tested on ATmega328P (avr8-gnu-toolchain-3.5.4.1709) ;)
This code implements the logic of how search works (one of the ways) without using any ready-made function:
public int findSubString(char[] original, char[] searchString)
{
int returnCode = 0; //0-not found, -1 -error in imput, 1-found
int counter = 0;
int ctr = 0;
if (original.Length < 1 || (original.Length)<searchString.Length || searchString.Length<1)
{
returnCode = -1;
}
while (ctr <= (original.Length - searchString.Length) && searchString.Length > 0)
{
if ((original[ctr]) == searchString[0])
{
counter = 0;
for (int count = ctr; count < (ctr + searchString.Length); count++)
{
if (original[count] == searchString[counter])
{
counter++;
}
else
{
counter = 0;
break;
}
}
if (counter == (searchString.Length))
{
returnCode = 1;
}
}
ctr++;
}
return returnCode;
}
I believe that I have the simplest answer. You don't need the string.h library in this program, nor the stdbool.h library. Simply using pointers and pointer arithmetic will help you become a better C programmer.
Simply return 0 for False (no substring found), or 1 for True (yes, a substring "sub" is found within the overall string "str"):
#include <stdlib.h>
int is_substr(char *str, char *sub)
{
int num_matches = 0;
int sub_size = 0;
// If there are as many matches as there are characters in sub, then a substring exists.
while (*sub != '\0') {
sub_size++;
sub++;
}
sub = sub - sub_size; // Reset pointer to original place.
while (*str != '\0') {
while (*sub == *str && *sub != '\0') {
num_matches++;
sub++;
str++;
}
if (num_matches == sub_size) {
return 1;
}
num_matches = 0; // Reset counter to 0 whenever a difference is found.
str++;
}
return 0;
}
Using C - No built in functions
string_contains() does all the heavy lifting and returns 1 based index. Rest are driver and helper codes.
Assign a pointer to the main string and the substring, increment substring pointer when matching, stop looping when substring pointer is equal to substring length.
read_line() - A little bonus code for reading the user input without predefining the size of input user should provide.
#include <stdio.h>
#include <stdlib.h>
int string_len(char * string){
int len = 0;
while(*string!='\0'){
len++;
string++;
}
return len;
}
int string_contains(char *string, char *substring){
int start_index = 0;
int string_index=0, substring_index=0;
int substring_len =string_len(substring);
int s_len = string_len(string);
while(substring_index<substring_len && string_index<s_len){
if(*(string+string_index)==*(substring+substring_index)){
substring_index++;
}
string_index++;
if(substring_index==substring_len){
return string_index-substring_len+1;
}
}
return 0;
}
#define INPUT_BUFFER 64
char *read_line(){
int buffer_len = INPUT_BUFFER;
char *input = malloc(buffer_len*sizeof(char));
int c, count=0;
while(1){
c = getchar();
if(c==EOF||c=='\n'){
input[count]='\0';
return input;
}else{
input[count]=c;
count++;
}
if(count==buffer_len){
buffer_len+=INPUT_BUFFER;
input = realloc(input, buffer_len*sizeof(char));
}
}
}
int main(void) {
while(1){
printf("\nEnter the string: ");
char *string = read_line();
printf("Enter the sub-string: ");
char *substring = read_line();
int position = string_contains(string,substring);
if(position){
printf("Found at position: %d\n", position);
}else{
printf("Not Found\n");
}
}
return 0;
}
The same will be achieved with this simpler code: Why use these:
int main(void)
{
char mainstring[]="The quick brown fox jumps over the lazy dog";
char substring[20];
int i=0;
puts("enter the sub string to find");
fgets(substring, sizeof(substring), stdin);
substring[strlen(substring)-1]='\0';
if (strstr(mainstring,substring))
{
printf("substring is present\t");
}
printf("and the sub string is:::");
printf("%s",substring,"\n");
return 0;
}
But the tricky part would be to report at which position in the original string the substring starts...
My code to find out if substring is exist in string or not
// input ( first line -->> string , 2nd lin ->>> no. of queries for substring
following n lines -->> string to check if substring or not..
#include <stdio.h>
int len,len1;
int isSubstring(char *s, char *sub,int i,int j)
{
int ans =0;
for(;i<len,j<len1;i++,j++)
{
if(s[i] != sub[j])
{
ans =1;
break;
}
}
if(j == len1 && ans ==0)
{
return 1;
}
else if(ans==1)
return 0;
return 0;
}
int main(){
char s[100001];
char sub[100001];
scanf("%s", &s);// Reading input from STDIN
int no;
scanf("%d",&no);
int i ,j;
i=0;
j=0;
int ans =0;
len = strlen(s);
while(no--)
{
i=0;
j=0;
ans=0;
scanf("%s",&sub);
len1=strlen(sub);
int value;
for(i=0;i<len;i++)
{
if(s[i]==sub[j])
{
value = isSubstring(s,sub,i,j);
if(value)
{
printf("Yes\n");
ans = 1;
break;
}
}
}
if(ans==0)
printf("No\n");
}
}
#include <stdio.h>
#include <string.h>
int findSubstr(char *inpText, char *pattern);
int main()
{
printf("Hello, World!\n");
char *Text = "This is my sample program";
char *pattern = "sample";
int pos = findSubstr(Text, pattern);
if (pos > -1) {
printf("Found the substring at position %d \n", pos);
}
else
printf("No match found \n");
return 0;
}
int findSubstr(char *inpText, char *pattern) {
int inplen = strlen(inpText);
while (inpText != NULL) {
char *remTxt = inpText;
char *remPat = pattern;
if (strlen(remTxt) < strlen(remPat)) {
/* printf ("length issue remTxt %s \nremPath %s \n", remTxt, remPat); */
return -1;
}
while (*remTxt++ == *remPat++) {
printf("remTxt %s \nremPath %s \n", remTxt, remPat);
if (*remPat == '\0') {
printf ("match found \n");
return inplen - strlen(inpText+1);
}
if (remTxt == NULL) {
return -1;
}
}
remPat = pattern;
inpText++;
}
}

Resources