In C find position of substring in a string - c

Here is a program to accept a:
Sentence from a user.
Word from a user.
How do I find the position of the word entered in the sentence?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char sntnc[50], word[50], *ptr[50];
int pos;
puts("\nEnter a sentence");
gets(sntnc);
fflush(stdin);
puts("\nEnter a word");
gets(word);
fflush(stdin);
ptr=strstr(sntnc,word);
//how do I find out at what position the word occurs in the sentence?
//Following is the required output
printf("The word starts at position #%d", pos);
return 0;
}

The ptr pointer will point to the beginning of word, so you can just subtract the location of the sentence pointer, sntnc, from it:
pos = ptr - sntnc;

Just for reference:
char saux[] = "this is a string, try to search_this here";
int dlenstr = strlen(saux);
if (dlenstr > 0)
{
char *pfound = strstr(saux, "search_this"); //pointer to the first character found 's' in the string saux
if (pfound != NULL)
{
int dposfound = int (pfound - saux); //saux is already pointing to the first string character 't'.
}
}

The return of strstr() is a pointer to the first occurence of your "word", so
pos=ptr-sntc;
This only works because sntc and ptr are pointers to the same string. To clarify when I say occurence it is the position of the first matching char when the matching string is found within your target string.

You can use this simple strpos modification
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strpos(char *haystack, char *needle, int offset);
int main()
{
char *p = "Hello there all y'al, hope that you are all well";
int pos = strpos(p, "all", 0);
printf("First all at : %d\n", pos);
pos = strpos(p, "all", 10);
printf("Second all at : %d\n", pos);
}
int strpos(char *hay, char *needle, int offset)
{
char haystack[strlen(hay)];
strncpy(haystack, hay+offset, strlen(hay)-offset);
char *p = strstr(haystack, needle);
if (p)
return p - haystack+offset;
return -1;
}

For some reasons I was having trouble with strstr(), and I also wanted index.
I made this function to find the position of substring inside a bigger string (if exists) otherwise return -1.
int isSubstring(char * haystack, char * needle) {
int i = 0;
int d = 0;
if (strlen(haystack) >= strlen(needle)) {
for (i = strlen(haystack) - strlen(needle); i >= 0; i--) {
int found = 1; //assume we found (wanted to use boolean)
for (d = 0; d < strlen(needle); d++) {
if (haystack[i + d] != needle[d]) {
found = 0;
break;
}
}
if (found == 1) {
return i;
}
}
return -1;
} else {
//fprintf(stdout, "haystack smaller\n");
}
}

My comment to the ORIGINAL post in this thread:
This declaration is INCORRECT:
char sntnc[50], word[50], *ptr[50];
C code would not even compile : it will fail on this line:
ptr = strstr(sntnc,word);
So the line shall be changed to :
char sntnc[50], word[50], *ptr;
And you do NOT need memeory allocated to 'ptr string'. You just need a pointer to char.

Related

How to locate and convert to integers an array of string in C?

I have a problem I am trying to solve. I have an array of string and integers and I want to convert only the integers(163) to actual integers in C.
I have managed to locate my desired numbers (163) array location but i am unsure how to convert them to numbers. I have tried to use strtol, atoi and strtoumax but I havent been succesful.
I have added my code below.
char busy[30] = {"this is; it was; 163; 234;;"};
int tag = 0;
int location = 0;
for (int i = sizeof(busy); i > 0; i--) {
printf("%c\n", busy[i]);
if (busy[i] == ';') {
tag = tag+1;
printf("tag is %i \n", tag);
}
if (tag == 4) {
printf("for loop is %i\n", i);
location = i;
break;
}
}
location = location+1;
int loca_saved = 0;
int loca_finish = 0;
int tag1 = 0;
while (busy[location] != ';') {
if (busy[location] == ' ' && busy[location - 1] == ';') {
//printf("not printing whitespace between semicolon and characters\n");
location++;
}
else {
if (tag1 == 0) {
tag1 = tag1+1;
loca_saved = location; //this is to tell me the array location for the first char
}
if (busy[location + 1] == ';') {
loca_finish = location; //this is to tell me the array location for the last char
}
putchar(busy[location]); //this is to print my desired characters(163)
location++;
}
}
strspn and strcspn can be used to parse a string.
Instead of sscanf, strtol could be used to get the number.
#include <stdio.h>
#include <string.h>
int main ( void) {
char busy[] = "this is; it was; 163; 234;";
char *dlm = "0123456789";
char *parse = busy;
int number = 0;
while ( *parse) {
parse += strcspn ( parse, dlm);//count to next delimiter
if ( 1 == sscanf ( parse, "%d", &number)) {
printf ( "%d\n", number);
}
parse += strspn ( parse, dlm);//skip delimeters
}
return 0;
}
Parsing could also work off the semicolon.
Some fields will not have an integer.
#include <stdio.h>
#include <string.h>
int main ( void) {
char busy[] = "this is; it was; 163; 234;";
char *dlm = ";";
char *parse = busy;
int number = 0;
while ( *parse) {
if ( 1 == sscanf ( parse, "%d", &number)) {
printf ( "%d\n", number);
}
else {
printf ( "could not parse integer\n");
}
parse += strcspn ( parse, dlm);//count to next delimiter
parse += strspn ( parse, dlm);//skip delimeters
//the above line will skip all consecutive delimiters
//to process each delimiter use the line below
//++parse;//skip one delimiter
}
return 0;
}
Since you have a modifiable string you can use strtok to separate it into substrings based on the ; delimiter. This code does that in in case a substring is a number, it gets printed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
char str[30] = {"this is; it was; 163; 234;;"};
for(char* p=strtok(str, ";"); p!=NULL; p=strtok(NULL,str))
{
char* endptr;
int i = strtol(p,&endptr,10);
if(endptr != p)
{
printf("%d\n", i);
}
}
}
Output:
163
234
strtol sets the "endptr" parameter to point at the beginning of the string in case it fails, so we can use that to determine if a substring was a number or not.
It all depends on the exact grammar that you would like to parse. Note, for example, that negative integers start with a - character, and that there has to be a maximum integer value. Since you are working quite "low level", you may want to perform the conversion to an integer while you are reading the string, e.g.:
#include <ctype.h>
#include <stdio.h>
int main(void)
{
char busy[30] = {"this is; it was; 163; 234;;"};
for (char *p = busy; *p; ++p) // Loop over the string
if (isdigit(*p)) // Found first digit of an unsigned integer
{
unsigned n = (unsigned) (*p - '0'); // Store the value of the first digit in 'n'
// While reading the number, shift the digits to the appropriate positions
while (isdigit(*++p))
n = n * 10U + (unsigned) (*p - '0');
printf("%u\n", n); // We have finished parsing the integer, print it
}
}
Using atoi can also work, but it will require two passes over each integer: one in atoi itself and another one to move past the integer in the string you're parsing.
The function strtol allows you to pass a pointer to your pointer which is set to one place after the read integer, which avoids the issue. You can use this to advance the pointer. In this code example, the pointer is either advanced manually or by strtol:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char busy[30] = {"this is; it was; 163; 234;;"};
for (char *p = busy; *p; )
if (isdigit(*p))
printf("%ld\n", strtol(p, &p, 10));
else
++p;
}
Another alternative, without the use of isdigit:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char busy[30] = {"this is; it was; 163; 234;;"};
for (char *p = busy; *p; )
{
char *end;
long n = strtol(p, &end, 10);
if (p != end) // Pointer was advanced, so an integer was read
{
printf("%ld\n", n);
p = end;
}
else // Pointer was not advanced, do so manually
++p;
}
}

How to extract some formatted string from the buffer using scanf?

I need to extract both "rudolf" and "12" from that long string: "hello, i know that rudolph=12 but it so small..." using scanf, how can I do it?
This buffer can contains any formatted strings like ruby=45 or bomb=1, and I dont know it in advance.
I am trying something like that, but it was unsuccessful
#include <stdio.h>
int main()
{
char sentence[] = "hello, i know that rudolph=12 but it so small...";
char name[32];
int value;
sscanf(sentence, "%[a-z]=%d", name, &value);
printf("%s -> %d\n", name, value);
getchar();
return 0;
}
Iterate through the sentence using a temporary pointer and %n to extract each sub-string.
%n will give the number of characters processed by the scan to that point. Add that to the temporary pointer to advance through the sentence.
Try to parse from each sub-string the name and value. The scanset %31[^=] will scan a maximum of 31 characters, leaving room in name for a terminating zero. It will scan all characters that are not an =. Then the format string will scan the = and try to scan an integer.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char sentence[] = "hello, i know that rudolph=12 but it so small...";
char string[sizeof sentence] = "";
char name[32] = "";
char *temp = sentence;
int value = 0;
int count = 0;
int parsed = 0;
while (1 == sscanf(temp, "%s%n", string, &count)) {
temp += count;
if (2 == sscanf(string, "%31[^=]=%d", name, &value)) {
parsed = 1;
break;
}
}
if (parsed) {
printf("%s %d\n", name, value);
}
return 0;
}
You can write your own string serach engine. Which could be quite simple, let's for example:
advance until you find one of [a-z]
remember position
advance until the end of [a-z]
check if it's = now
if it is, there was our variable name
advance until end of value
return it
if there's no =, omit everything that is not a [a-z] ie. can't be variable name
A sample program:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct find_assignment_s {
const char *line;
const char *var;
size_t varlen;
const char *val;
size_t vallen;
};
struct find_assignment_s find_assignment_init(const char *line) {
return (struct find_assignment_s){.line = line};
}
int find_assignment(struct find_assignment_s *t) {
while (*t->line) {
const char *p = t->line;
while (*p && isalpha((unsigned char)*p)) p++;
// There is at least one alphabetic character and there is a space right after.
if (t->line != p && *p == '=') {
// Found a "variable="!
t->var = t->line;
t->varlen = p - t->line;
// value is up until a space is found
t->val = p + 1;
while (*p && !isspace((unsigned char)*p)) p++;
t->vallen = p - t->val;
// Advance the pointer behind value.
t->line = *p ? p + 1 : p;
return 1;
}
// Ignore spaces
while (*p && !isalpha((unsigned char)*p)) p++;
// Advance over whole word.
t->line = p;
}
return 0;
}
int main() {
const char line[] = "hello, i know that rudolph=12 but it so small... a=b c=d fdnajn=123";
for (struct find_assignment_s fs = find_assignment_init(line);
find_assignment(&fs) == 1; ) {
printf("%.*s = %.*s\n", (int)fs.varlen, fs.var, (int)fs.vallen, fs.val);
}
}
outputs:
rudolph = 12
a = b
c = d
fdnajn = 123

Deleting a char and moving it in a string

I need ideas for a recursive code that deletes a specific char in a string, and move all the other sting chars together
for Example :
"the weather is cloudy"
the entered char is 'e':
result :
"th wathr is cloudy"
I really don't have any idea how to start, thanks for the help.
#include <stdio.h>
void remove_impl(char* s, char c, char* d) {
if (*s != c) {
*d++ = *s;
}
if (*s != '\0') {
remove_impl(++s, c, d);
}
}
void remove(char* s, char c) {
remove_impl(s, c, s);
}
int main() {
char s[] = "the weather is cloudy";
remove(s, 'e');
puts(s);
}
How it works? Consider remove_impl. s is the original string, c is the character to be deleted from s, d is the resulting string, into which the characters of s, not equal to c, are written. Recursively iterates through the characters of s. If the next character is not equal to c, then it is written in d. The recursion stop point is the condition of checking that the end of s is reached. Since it is necessary to modify the source string, the wrapper is implemented (remove) in which as d, the original string (s) is passed.
An easy way to do it is to loop over the string and add any letter that doesn't match the unwanted letter.
Here's a demonstration:
char *source = "the weather is cloudy";
int source_len = strlen(source);
char *target = (char *)calloc(source_len, sizeof(char));
int target_len = 0;
char to_remove = 'e';
for(int i = 0; i < source_len; i++)
{
if(source[i] != to_remove)
{
target[target_len++] = source[i];
}
}
puts(target); // Output "th wathr is cloudy" in the console
My turn to make a proposal ! I add a assert test and use existing functions (strchr and strcpy).
#include <string.h>
#include <stdio.h>
#include <assert.h>
int removeChar(char *str, char chr)
{
assert(str != 0); // Always control entry !
char *str_pnt = strchr(str, chr);
if (str_pnt) {
strcpy(str_pnt, str_pnt+1);
removeChar(str_pnt, chr);
}
}
void main (void)
{
char str[] = "the weather is cloudy";
char char_to_delete = 'e';
removeChar(str, char_to_delete);
puts(str);
}
This can be done in many ways. What i am thinking right now is store not Allowed char array which going to filter which char should show or not. Something like following..
#include <stdio.h>
#include <string.h>
// Global Scope variable declaration
int notAllowedChar[128] = {0}; // 0 for allowed , 1 for not allowed
char inputString[100];
void recursion(int pos, int len) {
if( pos >= len ) {
printf("\n"); // new line
return;
}
if( notAllowedChar[inputString[pos]]) {// not printing
recursion( pos + 1 , len );
}
else {
printf("%c", inputString[pos]);
recursion( pos + 1 , len );
}
}
int main() {
gets(inputString); // taking input String
printf("Enter not allowed chars:: "); // here we can even run a loop for all of them
char notAllowed;
scanf("%c", &notAllowed);
notAllowedChar[notAllowed] = 1;
int len = strlen(inputString);
recursion( 0 , len );
}
How this work
Lets say we have a simple string "Hello world"
and we want l should be removed from final string, so final output will be "Heo word"
Here "Hello world" length is 11 chars
before calling recursion function we make sure 'l' index which is 108 ascii values link 1 in notAllowedChar array.
now we are calling recursion method with ( 0 , 11 ) value , In recursion method we are having mainly 2 logical if operation, first one is for base case where we will terminate our recursion call when pos is equal or more than 11. and if its not true , we will do the second logical operation if current char is printable or not. This is simply just checking where this char is in notAllowedChar list or not. Every time we increase pos value + 1 and doing a recursion call, and finally when pos is equal or more than 11 , which means we have taken all our decision about printing char or not our recursion will terminate. I tried assign variable with meaningful name. If you still not understand how this work you should go with simple recursion simulation basic ( search in youtube ) and also you should try to manually debug how value is changing in recursion local scope. This may take time but it will be worthy to understand. All the very best.
#include <stdio.h>
/**
* Returns the number of removed chars.
* Base case: if the current char is the null char (end of the string)
* If the char should be deleted return 1 + no of chars removed in the remaining string.
* If it's a some other char simply return the number of chars removed in the remaining string
*/
int removeCAfterwardsAndCount(char* s,char c){
if((*s) == '\0'){
return 0;
}
if((*s) == c){
int noOfChars = removeCAfterwardsAndCount(s+1,c);// s+1 means the remaining string
s[noOfChars] = *s; // move the current char (*s) noOfChars locations ahead
return noOfChars +1; // means this char is removed... some other char should be copied here...
}
else{
int noOfChars = removeCAfterwardsAndCount(s+1,c);
s[noOfChars ] = *s;
return noOfChars ; // means this char is intact ...
}
}
int main()
{
char s[] = "Arifullah Jan";
printf("\n%s",s);
int totalRemoved = removeCAfterwardsAndCount(s,'a');
char *newS = &s[totalRemoved]; // the start of the string should now be originalPointer + total Number of chars removed
printf("\n%s",newS);
return 0;
}
Test Code Here
To avoid moving the chars using loops. I am just moving the chars forward which creates empty space in the start of the string. newS pointer is just a new pointer of the same string to eliminate the empty/garbage string.
#include <stdio.h>
void RemoveChar(char* str, char chr) {
char *str_old = str;
char *str_new = str;
while (*str_old)
{
*str_new = *str_old++;
str_new += (*str_new != chr);
}
*str_new = '\0'; }
int main() {
char string[] = "the weather is cloudy";
RemoveChar(string, 'e');
printf("'%s'\n", string);
return 0; }
#include <stdio.h>
#include <string.h>
char *remove_char(char *str, int c)
{
char *pos;
char *wrk = str;
while((pos = strchr(wrk, c)))
{
strcpy(pos, pos + 1);
wrk = pos;
}
return str;
}
int main()
{
char str[] = "Hello World";
printf(remove_char(str, 'l'));
return 0;
}
Or faster but mode difficult to understand version:
char *remove_char(char *str, int c)
{
char *pos = str;
char *wrk = str;
while(*wrk)
{
if(*wrk == c)
{
*wrk++;
continue;
}
*pos++ = *wrk++;
}
*pos = 0;
return str;
}
Both require the string to be writable (so you cant pass the pointer to the string literal for example)

string length in c without using string library

char* str =
"\
a-a-a-a\
differing the text, because that was the lecture thing\
the text has been changed\
I know!\
the text has been changed\
";
i deeply thinking about this for hours but can`t figure it out..
with using only stdio.h
string.h is not allowed, but using only basic things..
how can I get string length? someone please help me.
the goal is to find frequency of input pattern in a given string
ex) ha => 2, di => 1..
help me.
As for length of string, the implementation of strlen isn't very complicated.
All you should do is to loop over the string until you find a \0 (end of string) and count the number of times you looped.
unsigned int mystrlen(const char* str)
{
unsigned int length = 0;
while (*str != 0)
{
str++;
length++;
}
return length;
}
This could be shortened into
unsigned int len = 0;
for (; str[len]; len++);
A string in pure C is just a pointer to a memory.
IF the last element is 0, then you can use strlen or whatever checks for that.
But if that is not the case you need to memorize the length in a variable.
So if it is 0-terminated just loop to the first element that is 0 (not '0') and thats the end. If you counted the elements you have the string-length.
This works for some test input string, but i higly recommend to check it with more cases.
Suppose we have implemented strstr().
strstr()
Is a C library function from string.h Library
char *strstr(const char *haystack, const char *needle)
This function finds the first occurrence of the substring needle in the source string haystack.
The terminating \0 characters are not compared.
source: TutorialsPoint
(with some edition)
Code
#include <stdio.h>
#include <string.h>
unsigned int Neostrlen(const char* str)
{
unsigned int length = 0;
while (*str != 0)
{
str++;
length++;
}
return length;
}
int BluePIXYstrlen(char* str)
{
int len = 0;
sscanf(str, "%*[^0]%n", &len);
return len;
}
int Jeanfransvastrlen(char* str)
{
int i;
for (i=0;str[i];i++);
return i;
}
int main(int argc, char **argv){
//is it true, no need to malloc????
char* str =
"\
P-P-A-P\
I have a pen, I have a apple\
Uh! Apple-Pen!\
I have a pen, I have pineapple\
Uh! Pineapple-Pen!\
Apple-Pen, Pineapple-Pen\
Uh! Pen-Pineapple-Apple-Pen\
Pen-Pineapple-Apple-Pen\
";
printf("len: %d\n", Jeanfransvastrlen(str));
printf("len: %d\n", Neostrlen(str));
printf("len: %d\n", BluePIXYstrlen(str));
printf("sss:%s\n\n\n", str);
char * search = "have";//search for this substring
int lenSr= Neostrlen(search);
printf("lenSr: %d\n", lenSr);
char * ret;
ret = strstr(str, search);
int count = 0;
while (ret){
//printf("The substring is: %s\n\n\n\n", ret);
count++;
for (int i=0;i<lenSr;i++){
printf("%c", ret[i]);
}
printf("\nEnd sub\n");
for (int i=0;i<lenSr;i++){
ret++;
}
ret = strstr(ret, search);
}
printf("count: %d\n", count);
return 0;
}
Edited
For only using stdio.h you can substitute all strstr() with this version of mystrstr() adopted from leetcode
mystrstr()
char* mystrstr(char *str, const char *target) {
if (!*target) {
return str;
}
char *p1 = (char*)str;
while (*p1) {
char *p1Begin = p1, *p2 = (char*)target;
while (*p1 && *p2 && *p1 == *p2) {
p1++;
p2++;
}
if (!*p2){
return p1Begin;
}
p1 = p1Begin + 1;
}
return NULL;
}
Hint
I removed const from first first argument of mystrstr() because of I want to change it later, and this is the only changed i have made on original code.
This version is sensitive to Uppercase and lowercase letters in string,
for example Apple is differ from apple.
As chux said in comments my code return substrings of "ababa" from source
"aba" only {aba} not more. and this is because i change string pointer inside while in last for.
Suggestion
Try to implement your version of strstr(), and strlen()

C: Search vor endindex of first occurence

how can i write following programm:
• a function which searches a string in a second string and returns the endindex of the first occurence
• a function which includes all occurences of the first string in the second string, which will be replaced by a third string
• a main function which scans the three strings and puts the string out within the replacement
it is not allowed to use more headers than stdio.h , stdlib.h and string.h
i could only start with a code like this, as you can see i couldnt solve any of the three problems. i hope you can help me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int endIdx(char *string1, char *string2, char *occu)
{
for (int i = 0; i < strlen(string1); i++)
{
for (int j = 0; j < strlen(string1); j++)
{
if (string1[i] == string2[j])
{
printf("occurence string1[%d] is in string2[%d]\n", i, j);
occu[j] = string1[i];
}
}
}
return 0;
}
int main()
{
char string1[20];
char string2[20];
char occu[20];
printf("Type in the first string: ");
scanf("%s", string1);
printf("Type in the second string: ");
scanf("%s", string2);
endIdx(string1, string2, occu);
printf("%s\n", occu);
}
The following program uses strstr to implement your endIdx-problem.
strstr returns a pointer to the first occurrence of searchTeram in str, or NULL, if it does not occur.
In the first case, we get a start index by taking occurrence - str, i.e. the memory address of the first occurrence minus the memory address where str starts. Adding then the length of searchTerm gives the end index.
In the second case, we simply return -1:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
long endIdx(const char *str, const char *searchTerm) {
long result = -1;
const char* occurrence = strstr(str,searchTerm);
if (occurrence != NULL) {
result = (occurrence - str) + strlen(searchTerm);
}
return result;
}
int main(void)
{
// ----------------012345678901234
const char* str = "Hello world! world is beautiful!";
const char* searchTerm = "world";
long endidx = endIdx(str, searchTerm);
printf("endidx (should be 11): %ld\n", endidx);
endidx = endIdx(str, "not to be contained");
printf("endidx (should be -1): %ld\n", endidx);
return 0;
}

Resources