I have an array that looks like this:
char test[100]
then I want to compare whether or not this array has this specific sentence
if (test == "yup this is the sentence") {
// do stuff
}
Is this correct? Is there a better approach to this? Thank you.
You cannot do that in C. What you're doing here is checking identity equality (id est if your two pointers point the same memory zone).
What you can do is use libc strstr that does what you want :
#include <string.h>
if (strstr(test, "yup this is the sentence") != NULL)
{
// do stuff if test contains the sentence
}
Type man 3 strstr in a terminal to get more info about the function, and all its behaviours.
If you want to understand the behaviour of the function, here it is recoded in pure C, with one loop only :
char *strstr(const char *s1, const char *s2)
{
int begin;
int current;
begin = 0;
current = 0;
if (!*s2)
return ((char *)s1);
while (s1[begin])
{
if (s1[begin + current] == s2[current])
current++;
else
{
current = 0;
begin++;
}
if (!s2[current])
return ((char *)s1 + begin);
}
return (0);
}
It is part from a school project. The full project contains all the C library basic functions.
You can check out some other string manipulation functions here :
https://github.com/kube/libft/tree/master/src/strings
You could use strstr:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main(void) {
char test[256] = "This is a looooooonnnnggggg string which contains ('yup this is the sentence') my needed string inside";
if (strstr(test, "yup this is the sentence") != NULL){
printf("True\n");
}else{
printf("False\n");
}
return 0;
}
or you could use some pointer arithmetic:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void checkString(char *string1, char *string2);
int main(void){
char test[256] = "This is a looooooonnnnggggg string which contains ('yup this is the sentence') my needed string inside";
char string2[] = "yup this is the sentence";
checkString(test, string2);
return 0;
}
void checkString(char *string1, char *string2){
char *s1, *s2, *s3;
size_t lenstring1 = strlen(string1);
size_t lenstring2 = strlen(string2);
if (lenstring2 < 1){
printf("There is no substring found");
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\nwas found at index : %zu\n",string2,i+1);
}
}
s1++;
}
if(found == 0){
printf("No match Found");
}
}
Output:
yup this is the sentence
was found at index : 53
Related
How do i make below program work properly, The main problem i have seen so far is str1 is not defined properly which may be the real cause for the program not working properly.
#include<stdio.h>
#include<string.h>
int main()
{
char string[]="We will rock you";
char s1[10],s2[10];
printf("Enter string 1 ");
gets(s1);
printf("Enter string 2 ");
gets(s2);
int start,end,compare;
for(int i=0;string[i]!='\0';i++)
if(string[i]==s1[0])
{
start=i;
break;
}
//printf("%d",start);
end=start+strlen(s1);
//printf("\n%d",end);
char str1[30],check[10];
//Defining string 1
for(int i=0;i<start;i++)
str1[i]=string[i];
//printf("\n%sd",str1);
//Defining check
for(int i=start;i<end;i++)
check[i-start]=string[i];
//printf("\n%s\n",check,str1);
compare=strcmp(check,s1);
//printf("\n%d",compare);
if(compare==0)
strcat(str1,s1);
printf("\n%s",str1);
for(int i=end,j=strlen(str1);i<strlen(string);i++)
{
str1[j]=string[i];
}
strcpy(string,str1);
printf("\n%s",string);
}
I know this is not the best way to do it, it has so many loopholes as it wont work for words appearing again and it may also change words like (ask, task or asking) if str1 is given ask.
But still help me , What am i doing wrong???
What am i doing wrong???
For starters the function gets is unsafe and is not supported by the C Standard. Instead either use scanf or fgets.
If in this for loop
int start,end,compare;
for(int i=0;string[i]!='\0';i++)
if(string[i]==s1[0])
{
start=i;
break;
}
the condition string[i]==s1[0] does not evaluate to true then the variable start will have an indeterminate value because it is not initialized and all the subsequent code after the for loop invokes undefined behavior because there is used the uninitialized variable start.
If the condition evaluates to true then the value of end
end=start+strlen(s1);
can be larger than the length of the original string string. That again can invoke undefined behavior in this for loop
for(int i=0;i<start;i++)
str1[i]=string[i];
After this for loop
for(int i=start;i<end;i++)
check[i-start]=string[i];
//printf("\n%s\n",check,str1);
compare=strcmp(check,s1);
the array check does not contain a string. So calling the function strcmp also invokes undefined behavior.
It seems that in this call there is at least a typo.
if(compare==0)
strcat(str1,s1)
it seems you mean
strcat( str1, s2 );
^^^
If s1 was not found in string then this loop
for(int i=end,j=strlen(str1);i<strlen(string);i++)
{
str1[j]=string[i];
}
just does not make a sense.
Pay attention to that in general the length of s2 can be greater than the length of s1. In this case you may not change s1 to s2 within string declared like
char string[]="We will rock you";
because that results in accessing memory outside the array.
Function replacing string in the string.
char *strreplace(char *haystack, const char *needle, const char *replace, char *buff)
{
int length = strlen(haystack);
int needlelength = strlen(needle);
int replacelength = strlen(replace);
char *ptr = buff;
char *start, *source, *dest;
if (buff == NULL)
{
ptr = malloc((length + 1) * sizeof(char));
source = ptr;
dest = haystack;
}
else
{
source = haystack;
dest = buff;
}
if (ptr != NULL)
{
if (buff == NULL) strcpy(ptr, haystack);
else
{
if (!length)
{
*buff = 0;
}
}
while (needlelength && *source)
{
size_t chunklen;
char *result;
start = source;
if ((result = strstr(source, needle)) == NULL)
{
strcpy(dest, source);
break;
}
chunklen = result - start;
strncpy(dest, start, chunklen);
dest += chunklen;
strcpy(dest, replace);
dest += replacelength;
source = result;
source += needlelength;
}
if (buff == NULL)
{
free(ptr);
ptr = haystack;
}
else
{
ptr = buff;
}
}
return ptr;
}
Hello and Sorry for bad English.
I think this code can help you
char* replace ( char text[] , char mainchar, char replace_char )
{
char out [120];
char* out_pointer = out ;
register char index_2=0;
for ( register char index_1 = 0 ; index_1 < strlen (text) ; ++index_1 )
{
if ( text[index_1] != mainchar )
{
out_pointer[index_2]=text[index_1];
++index_2 ;
}
else
{
out_pointer[index_2]=replace_char;
++index_2 ;
}
}
return out_pointer;
}
To use this function in your source code, proceed as follows :
#include <stdio.h>
#include <string.h>
int main ()
{
char* replace ( char text[] , char mainchar, char replace_char )
{
char out [120];
char* out_pointer = out ;
register char index_2=0;
for ( register char index_1 = 0 ; index_1 < strlen (text) ; ++index_1 )
{
if ( text[index_1] != mainchar )
{
out_pointer[index_2]=text[index_1];
++index_2 ;
}
else
{
out_pointer[index_2]=replace_char;
++index_2 ;
}
}
return out_pointer;
}
char Array[100];
strcpy (Array, replace("Hello", 'H', 'e'));
printf ("%s", Array);
}
I'm trying to tokenize a string without using a strtok().
When I run characters of string, it will print in each line.
For instance, when I run:
printfTokens("Hello from other side!");
The output should be:
Hello
from
other
side!
As I'm just learning C, I'm stuck for hours on how to implement this program. So far, I only know the basics and playing around with not (still haven't learned any calloc, malloc, etc).
So far I have this code, but the output does not print anything.
#include <stdio.h>
#include <string.h>
#define MAX_WORD 100
void printfTokens(char *inputString) {
int i;
/*int inputStringLength;
for(i = 0; inputString[i] != '/0'; i++) {
inputStringLength++;
}*/
while(inputString[i] != '\0') {
char testing[MAX_WORD];
while(inputString[i] != ' ') {
testing[inputString[i]]++;
i++;
}
printf("%s", testing);
i++;
}
}
int main() {
printfTokens("TESTING ONE! TWO! THREE!");
return 0;
}
You do not initialize the variable i.
while(inputString[i] != '\0') can be written while(inputString[i]).
testing[inputString[i]]++ makes sense to count the number of occurrences of a given character from inputString, but it does not make sense to print it. You may want to do something like:
while(1)
{
char testing[MAX_WORD], *t=testing;
while(inputString[i]&&(inputString[i]!=' '))
*t++=inputString[i++];
if (t>testing) printf("%s", testing);
if (!inputString[i]) break;
i++;
}
It would be better to name MAX_WORD_LENGTH instead of MAX_WORD.
These are a few problems in your code.
Sample tokenization function.
size_t tokenize(const char *inputString, const char *delim, char **argv, size_t maxtokens)
{
size_t ntokens = 0;
char *tokenized = strdup(inputString);
if(tokenized)
{
argv[0] = tokenized;
while(*tokenized)
{
if(strchr(delim, *tokenized))
{
*tokenized = 0;
ntokens++;
if(ntokens == maxtokens - 1)
{
break;
}
argv[ntokens] = tokenized + 1;
}
tokenized++;
}
}
return ntokens + 1;
}
int main()
{
char *tokens[10];
size_t ntokens = tokenize("TESTING ONE! TWO! THREE!", " ", tokens , 10);
for(size_t i = 0; i < ntokens; i++)
{
printf("Token[%zu] = `%s`\n", i, tokens[i]);
}
free(tokens[0]);
return 0;
}
https://godbolt.org/z/znv8PszG6
This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I tried to develop a function which take a string reverse letters and return pointer to string.
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = 0;
char *result = malloc(20);
while(*s != '\0')
{
cCounter++;
s++;
}
printf("String contains %d symbols\n", cCounter);
int begin = cCounter;
for(; cCounter >= 0; cCounter--)
{
result[begin - cCounter] = *s;
s--;
}
result[13] = '\0';
return result;
}
in main function I invoke the function and tried to print the result in this way:
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
return 0;
}
but the result is unexpected, there is no reverse string.
What is my fault?
There are multiple mistakes in the shared code, primarily -
s++; move the pointer till '\0'. It should be brought back 1 unit to
point to actual string by putting s--. Other wise the copied one will start with '\0' that will make it empty string.
Magic numbers 20 and 13. where in malloc() 1 + length of s should be
sufficient instead or 20. For 13 just move a unit ahead and put '\0'
However, using string.h library functions() this can be super easy. But I think you are doing it for learning purpose.
Therefore, Corrected code without using string.h lib function() should look like this:
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = 0;
while(*s != '\0')
{
cCounter++;
s++;
}
s--; //move pointer back to point actual string's last charecter
printf("String contains %d symbols\n", cCounter);
char *result = (char *) malloc(sizeof(char) * ( cCounter + 1 ));
if( result == NULL ) /*Check for failure. */
{
puts( "Can't allocate memory!" );
exit( 0 );
}
char *tempResult = result;
for (int begin = 0; begin < cCounter; begin++)
{
*tempResult = *s;
s--; tempResult++;
}
*tempResult = '\0';
//result[cCounter+1] = '\0';
return result;
}
Calling from main
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
}
Output
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
As per WhozCraig suggestion just by using pointer arithmetic only -
char *reverseStr(const char s[])
{
const char *end = s;
while (*end)
++end;
char *result = malloc((end - s) + 1), *beg = result;
if (result == NULL)
{
perror("Failed to allocate string buffer");
exit(EXIT_FAILURE);
}
while (end != s)
*beg++ = *--end;
*beg = 0;
return result;
}
Your code can be simplified using a string library function found in string.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = strlen(s);
char *result = malloc(cCounter + 1);
printf("String contains %d symbols\n", cCounter);
int begin = cCounter;
for(; cCounter > 0; cCounter--)
{
result[begin - cCounter] = s[cCounter - 1];
}
result[begin] = '\0';
return result;
}
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
return 0;
}
Output:
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
I want to split a String in C.
My String is defined by my Struct:
struct String
{
char *c;
int length;
int maxLength;
}
Then I have a function that does the splitting. Perhaps C has something that does this, but although I wanted my own, I have not found anything that will do it so far.
String ** spliter(String *s)
{
if(s == NULL)
return NULL;
// set of splitters: {'\n', ' '}
}
Input looks something like this: This is Sparta.
Then I want to return a pointer to each character array.
*p1 = This
*p2 = is
*p3 = Sparta.
If that makes any sense, I want an array of pointers, and each pointer points to a character array.
I will have to realloc the String as I increment the size of each character array. Probably my biggest problem is imagining how the pointers work.
Similar problem: c splitting a char* into an char**
So, how do I go about doing this?
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string test = "aa aa bbc cccd";
vector<string> strvec;
string strtemp;
string::size_type pos1, pos2;
pos2 = test.find(' ');
pos1 = 0;
while (string::npos != pos2)
{
strvec.push_back(test.substr(pos1, pos2 - pos1));
pos1 = pos2 + 1;
pos2 = test.find(' ', pos1);
}
strvec.push_back(test.substr(pos1));
vector<string>::iterator iter1 = strvec.begin(), iter2 = strvec.end();
while (iter1 != iter2)
{
cout << *iter1 << endl;
++iter1;
}
return 0;
}
Have you looked at strtok? It should be possible to do this using strtok.
here is a exemple :
String ** spliter(String *s)
{
int i;
int j;
char *p1;
char *p2;
char *p3;
i = 0;
j = 0;
if(s == NULL)
return NULL;
p1 = malloc(sizeof(*p1) * strlen(s));
p2 = malloc(sizeof(*p2) * strlen(s));
p3 = malloc(sizeof(*p3) * strlen(s));
while (s[i] != ' ')
{
p1[j++] = s[i];
i++;
}
i++;
j = 0;
while (s[i] != ' ')
{
p2[j++] = s[i];
i++;
}
i++;
j = 0;
while (s[i] != '\0')
{
p3[j++] = s[i];
i++;
}
printf("%s\n", p1);
printf("%s\n", p2);
printf("%s\n", p3);
}
You're looking for strtok, check out man 3 strtok, or here if you're not on *nix.
You would use it like this: (Assuming that you can write the add_string code yourself.)
String ** spliter(String *s)
{
if(s == NULL)
return NULL;
String **return_strings = NULL;
char *delim = " \n";
char *string = strtok(s, delim);
int i = 0;
for(i = 0; add_string(return_strings, string, i) != -1; i++) {
string = strtok(NULL, delim);
}
return strings;
}
Note that if you need to save the original string (strtok modifies the string it works on), you'll need to call strdup on the original string, then operate on the copy.
EDIT: OP said he was having trouble thinking about the pointers. With the above code sample, add_string only has to worry about dealing with a string of characters, as opposed to an array of pointers to pointers to characters. So it might look something like this:
int add_string(String **strings, char *s, int len)
{
if(s == NULL)
return -1;
String *current_string = NULL;
strings = realloc(strings, sizeof(String) * (len + 1));
current_string = strings[len];
/* fill out struct fields here */
}
add strdup and strtok can work on a copy of the string. The split() call is more generic than the other spliter() examples, but does the same thing with strtok on a duplicate.
char **
split(char **result, char *w, const char *src, const char *delim)
{
int i=0;
char *p;
strcpy(w,src);
for(p=strtok(w, delim) ; p!=NULL; p=strtok('\0', delim) )
{
result[i++]=p;
result[i]=NULL;
}
return result;
}
void display(String *p)
{
char *result[24]={NULL};
char *w=strdup(p->c);
char **s=split(result, w, p->, "\t \n"); split on \n \t and space as delimiters
for( ; *s!=NULL; s++)
printf("%s\n", *s);
free(w);
}
I have a small problem.
I have a function that takes in two parameters (two strings). For example:
String1 = "hello"
String2 = "leo"
I need to remove all characters from String2 in String1. In this case, my final result should be: "h". I need to incorporate pointers when doing this! I've got this code so far, but it's only remove "e" from "hello". I don't know why it's not working. If someone has a better or efficient way of doing this, please help!
void rmstr(char str1[], char str2[])
{
//Pointers to traverse two strings
char *p_str1 = &str1[0];
char *p_skip;
int length = (int)strlen(str2);
int i;
while(*p_str1 != '\0')
{
for (i = 0; i < length; i++)
{
if(*p_str1 == str2[i])
{
for(p_skip = p_str1; *p_skip == str2[i]; ++p_skip);
memcpy(p_str1, p_skip, &str1[strlen(str1)+1] - p_skip);
}
if(*p_str1 != '\0')
{
++p_str1;
}
}
}
}
char* rmstr(char *str1, char *str2, char *ans) {
char *p1 = str1;
char *p2 = str2;
char *res = ans;
while (*p1 != '\0') {
p2 = str2;
while (*p2 != '\0') {
if (*p1 == *p2) // A character in str1 is found inside str2
break;
p2++;
}
if (*p2 == '\0') { // No match found
*ans = *p1;
ans++;
}
p1++;
}
*ans = '\0';
return res;
}
Testing code:
int main(void) {
char str1[] = "hello";
char str2[] = "elo";
char ans[10];
printf(rmstr(str1, str2, ans));
return 0;
}
Well, this answer has less variables and maybe easier to read.
#include "stdio.h"
/* check if c belongs to the second str */
int char_belong_to_str(char c, char *str)
{
while(*str)
if (c == *str++)
return 1;
return 0;
}
void rmstr(char str1[], char str2[])
{
int result_len = 0; /* saves the result str len*/
char * p_new = str1;
while (*str1)
{
char c = *str1;
if (!char_belong_to_str(c, str2)) /* if not found in str2, save it*/
{
*(p_new + result_len) = c;
++result_len;
}
++str1;
}
*(p_new+result_len) = '\0';
printf("%s \n", p_new);
}
int main()
{
char p1[] = "hello";
char p2[] = "elo";
rmstr(p1, p2);
return 0;
}