I am following this algorithm that will copy one string to another string:
[S is a source string and T is a target string]
1. Set I = 0
2. Repeat step 3 while S[I] ≠ Null do
3. T[I] = S[I]
4. I = I + 1
[End of loop]
5. Set T[I] = Null
6. Return
I have attempted it but it instead removes the first n characters from source string relative to length of target string. For example:
#include <stdio.h>
#include <stdlib.h>
char const* stringCopy(char* T, char const* S){
while(*S){
*T++ = *S++;
}
//*T = 0;
return T;
}
int main(void){
char sentence[100] = "some sentence";
char* again = "another";
printf("%s", stringCopy(sentence, again));
return EXIT_SUCCESS;
}
You return the incremented original pointer T. Make a copy of T for the copy loop and return the original pointer.
#include <stdio.h>
#include <stdlib.h>
char const* stringCopy(char* T, char const* S){
char *ptr = T;
while(*ptr++ = *S++);
return T;
}
int main(void){
char sentence[100] = "some sentence";
char* again = "another";
printf("%s", stringCopy(sentence, again));
return EXIT_SUCCESS;
}
Related
I have a structure inside which char array and int value is maintained. I want to treat this char array as a flat array to store the list of strings and the offset will track the starting position where the string is added in the array.
Structure is shown below:
struct A
{
char element[256];
int offset;
}
Also, I want to delete the strings after performing some operation if found.
Please let me know if this feasible. If yes then how?
Yes, append to a.element[a.offset].
To delete, set a.element[0] to the null byte. C strings end at a null byte.
#include <stdio.h>
#include <string.h>
typedef struct
{
char element[256];
int offset;
} A;
void A_append(A* a, const char *str) {
// Concatenate on the end of element.
strcat(&a->element[a->offset], str);
// Increment the offset to the new end.
a->offset += strlen(str);
}
void A_delete(A* a) {
a->element[0] = '\0';
a->offset = 0;
}
int main() {
A a = { .element = "" };
a.offset = 0;
char string1[] = "one";
A_append(&a, string1);
char string2[] = "two";
A_append(&a, string2);
puts(a.element);
A_delete(&a);
puts(a.element);
}
You can also store a pointer to the end of element. It's the same thing, just more direct.
#include <stdio.h>
#include <string.h>
typedef struct
{
char element[256];
char *end;
} A;
void A_append(A* a, const char *str) {
// Concatenate nto the end of element.
strcat(a->end, str);
// Increment the pointer to the new end.
a->end += strlen(str);
}
void A_delete(A* a) {
a->element[0] = '\0';
a->end = a->element;
}
int main() {
A a = { .element = "" };
a.end = a.element;
char string1[] = "one";
A_append(&a, string1);
char string2[] = "two";
A_append(&a, string2);
puts(a.element);
A_delete(&a);
puts(a.element);
}
Finally, if you want to store a list of strings, not concatenate them, consider storing them as pointers.
Since all we have to go on is the question if it's feasible - and the answer is yes. Here's a way showing that it is:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct A A;
struct A {
char element[256];
int offset;
};
A *A_create() {
A *a = malloc(sizeof *a);
a->offset = 0;
return a;
}
void A_destroy(A *a) {
free(a);
}
// return false if the string doesn't fit
// true if it's successfully added
bool A_add_string(A *a, const char *str) {
size_t len = strlen(str);
if(a->offset + len >= sizeof a->element) return false;
memcpy(a->element + a->offset, str, len + 1);
a->offset += len + 1;
return true;
}
You can now create an A, add \0 terminated strings to it and finally destroy it:
A *a = A_create();
A_add_string(a, "Hello");
A_add_string(a, "world");
A_destroy(a);
i,m trying to write this code, it should counting the number of substring, which are not including in the string, for examples(below), in the main i was trying with pointer to work with String without using arrays but it didnt work at all!!
// count_target_string("abc of", "of") -> 1
// count_target_string("abcof", "of") -> 0
// count_target_string("abc of abc of", "of") -> 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int countTargetString(char* text , char* string){
char d[]=" ";
char * portion = strtok(text,d);
int result=0;
while (portion!=NULL){
if (strcmp(portion,string)==0){
result++;
}
portion = strtok(NULL,d);
}
return result;
}
int main(){
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
return 0;
}
strtok modifies the string.
char *test ="abc of abc of"; defines the pointer to the string literal. Modification of the string literal invokes Undefined Behaviour (UB). It is why your code does "not work at all" Same if you pass string literal reference directly to the function (ie use a string literal as a parameter) countTargetString("abc of abc of","of"));.
Your pointer must reference a modifiable string:
int main()
{
char mystring[] = "abc of abc of";
char *test = mystring;
char *d = "of";
printf("%d\n",countTargetString(test,d));
}
In the both calls of the function countTargetString
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
you are passing pointers to string literals.
Though in C opposite to C++ string literals have types of non-constant character arrays nevertheless you may not change a string literal. Any attempt to change a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
And the function strtok changes the source string inserting terminating zero characters '\0' to extract substrings.
It is always better even in C to declare pointers to string literals with the qualifier const.
Instead of the function strtok you can use function strstr.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t countTargetString( const char *s1, const char *s2 )
{
size_t count = 0;
size_t n = strlen( s2 );
for ( const char *p = s1; ( p = strstr( p, s2 ) ) != NULL; p += n )
{
if ( ( p == s1 || isblank( ( unsigned char )p[-1] ) ) &&
( p[n] == '\0' || isblank( ( unsigned char )p[n] ) ) )
{
++count;
}
}
return count;
}
int main( void )
{
printf("%zu\n",countTargetString("abc of abc of","of"));
const char *test ="abc of abc of";
const char *d = "of";
printf("%zu\n",countTargetString(test,d));
}
The program output is
2
2
As you can see the function parameters are also declared with the qualifier const because the function does not change passed strings.
Pay attention to that in any case to count occurrences of substrings in a string it is a bad idea to change the original string.
While strtok will not work with a string literal, strspn and strcspn can be used.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int countTargetString(char* text , char* string){
char d[]=" ";
int result = 0;
size_t span = 0;
while ( *text) {
text += strspn ( text, d);
span = strcspn ( text, d);
if ( strncmp ( text, string, span)) {
++result;
}
text += span;
}
return result;
}
int main( void) {
printf("%d\n",countTargetString("abc of abc of","of"));
char *test ="abc of abc of";
char *d = "of";
printf("%d\n",countTargetString(test,d));
return 0;
}
int count_substr(const char* target, const char* searched) {
int found = 0;
unsigned long s_len = strlen(searched);
for (int i = 0; target[i]; i++) {
// use memcmp to NOT compare the null terminator of searched
if (memcmp(target + i, searched, s_len) == 0) {
found++;
i += s_len - 1;
}
}
return found;
}
This is a very basic implementation of substring counting. For the fastest solution possible, copy the boyer moore pattern matching algorithm from wikipedia or wherever you want and modify it to cound instead of terminationg on a match.
Recursion. I checked other online solutions and they seem to be pretty much identical to mine.
The code should reverse the string (in its position) but it does not. E.g when input is st2 = "abcdefg" the output is an empty string. I was expecting st2 = "gfedcba". What am i missing?
#include <stdio.h>
#include <string.h>
void recurse_reverse(char s[], int sz)
{
int i=0,j = sz -1;
if(i<j)
{
swap(&s[i],&s[j]);
recurse_reverse(s+1, sz-2);
}
}
void swap( char* s1, char *s2)
{
char tmp;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
int main(void)
{
char st1[9] = "abcdefg", st2[9];
strcpy(st2,st1);
recurse_reverse(st2,9);
printf("s1 = %s\ns2 = %s",st1,st2);
printf("\n" );
return 0;
}
You are swapping the 2 zero bytes at the end of st1. Hence, the st2 starts with a null byte and thus the printf() isn't printing anything.
You just need to fix your argument passing. Instead of
recurse_reverse(st2,9);
do
recurse_reverse(st2,strlen(st1));
You probably want to add logic to make sure your destination array st2 has sufficient space.
I added a printf statement to debug the issue and got the below output. You are trying to access 9th variable which is a terminated null character \0 hence you only get \0 as output and not the actual reversed string.
Instead of hardcoding the size of string you can use strlen to get the string length.
1st char = a and 9th char is ▒
1st char = b and 9th char is
1st char = c and 9th char is g
1st char = d and 9th char is f
s1 = abcdefg
s2 = ▒
Solution
Intended code change
recurse_reverse(st2,strlen(st1));
Output
1st char = a and 9th char 9th char is g
1st char = b and 9th char 9th char is f
1st char = c and 9th char 9th char is e
s1 = abcdefg
s2 = gfedcba
#include <stdio.h>
#include <string.h>
void swap( char* s1, char *s2);
void recurse_reverse(char s[], int sz)
{
int i=0,j = sz-1;
if(i<j)
{
swap(&s[i],&s[j]);
recurse_reverse(s+1, sz-2);
}
}
void swap( char* s1, char *s2)
{
char tmp;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
int main(void)
{
char st1[9] = "abcdefg", st2[9];
int len=0;
strcpy(st2,st1);
len =strlen(st2);
recurse_reverse(st2,len);
printf("s1 = %s\ns2 = %s",st1,st2);
printf("\n" );
return 0;
}
I need to create a function to concatenate 2 strings, in my case they are already given. I will need to concatenate the strings 'hello' and 'world!' to make it into 'helloworld!'. However, I can't use library functions besides strlen(). I also need to use malloc. I understand malloc would create n amounts of bytes for memory, however, how would I make it so that it can return a string array if thats possible.
Here is what I have so far,
#include <stdio.h>
#include <string.h>
int *my_strcat(const char* const str1, const char *const str2)
{
int s1, s2, s3, i = 0;
char *a;
s1 = strlen(str1);
s2 = strlen(str2);
s3 = s1 + s2 + 1;
a = char *malloc(size_t s3);
for(i = 0; i < s1; i++)
a[i] = str1[i];
for(i = 0; i < s2; i++)
a[i+s1] = str2[i];
a[i]='\0';
return a;
}
int main(void)
{
printf("%s\n",my_strcat("Hello","world!"));
return 0;
}
Thanks to anyone who can help me out.
This problem is imo a bit simpler with pointers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *mystrcat(char *a, char *b) {
char *p, *q, *rtn;
rtn = q = malloc(strlen(a) + strlen(b) + 1);
for (p = a; (*q = *p) != '\0'; ++p, ++q) {}
for (p = b; (*q = *p) != '\0'; ++p, ++q) {}
return rtn;
}
int main(void) {
char *rtn = mystrcat("Hello ", "world!");
printf("Returned: %s\n", rtn);
free(rtn);
return 0;
}
But you can do the same thing with indices:
char *mystrcat(char *a, char *b) {
char *rtn = malloc(strlen(a) + strlen(b) + 1);
int p, q = 0;
for (p = 0; (rtn[q] = a[p]) != '\0'; ++p, ++q) {}
for (p = 0; (rtn[q] = b[p]) != '\0'; ++p, ++q) {}
return rtn;
}
Here is an alternate fix. First, you forgot #include <stdlib.h> for malloc(). You return a pointer to char from the function my_strcat(), so you need to change the function prototype to reflect this. I also changed the const declarations so that the pointers are not const, only the values that they point to:
char * my_strcat(const char *str1, const char *str2);
Your call to malloc() is incorrectly cast, and there is no reason to do so anyway in C. It also looks like you were trying to cast the argument in malloc() to size_t. You can do so, but you have to surround the type identifier with parentheses:
a = malloc((size_t) s3);
Instead, I have changed the type declaration for s1, s2, s3, i to size_t since all of these variables are used in the context of string lengths and array indices.
The loops were the most significant change, and the reason that I changed the consts in the function prototype. Your loops looked fine, but you can also use pointers for this. You step through the strings by incrementing a pointer, incrementing a counter i, and store the value stored there in the ith location of a. At the end, the index i has been incremented to indicate the location one past the last character, and you store a '\0' there. Note that in your original code, the counter i was not incremented to indicate the location of the null terminator of the concatenated string, because you reset it when you looped through str2. #jpw shows one way of solving this problem.
I changed main() just a little. I declared a pointer to char to receive the return value from the function call. That way you can free() the allocated memory when you are through with it.
Here is the modified code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * my_strcat(const char *str1, const char *str2)
{
size_t s1, s2, s3, i = 0;
char *a;
s1 = strlen(str1);
s2 = strlen(str2);
s3 = s1+s2+1;
a = malloc(s3);
while(*str1 != '\0') {
a[i] = *str1;
str1++;
i++;
}
while(*str2 != '\0') {
a[i] = *str2;
str2++;
i++;
}
a[i] = '\0'; // Here i = s1 + s2
return a;
}
int main(void)
{
char *str = my_strcat("Hello", "world!");
printf("%s\n", str);
/* Always free allocated memory! */
free(str);
return 0;
}
There are a few issues:
In the return from malloc you don't need to do any cast (you had the syntax for the cast wrong anyway) (see this for more information).
You need to include the header stdlib.h for the malloc function.
And most importantly, a[i]='\0'; in this i is not what you need it to be; you want to add the null char at the end which should be a[s3]='\0'; (the length of s1+s2).
This version should be correct (unless I missed something):
#include <stdio.h>
#include <stdlib.h> //for malloc
#include <string.h>
char *my_strcat(const char* const str1, const char *const str2)
{
int s1,s2,s3,i=0;
char *a;
s1 = strlen(str1);
s2 = strlen(str2);
s3 = s1+s2+1;
a = malloc(s3);
for(i = 0; i < s1; i++) {
a[i] = str1[i];
}
for(i = 0; i < s2; i++) {
a[i+s1] = str2[i];
}
a[s3-1] = '\0'; // you need the size of s1 + s2 + 1 here, but - 1 as it is 0-indexed
return a;
}
int main(void)
{
printf("%s\n",my_strcat("Hello","world!"));
return 0;
}
Testing with Ideone renders this output: Helloworld!
i would like to copy data of char* to another last address of char*
illustration
var1 -> O
var2 -> K
first step
var1 -> OK
var2 -> K
copy var2 to var1
result
var1 -> OK
written code
#include <stdio.h>
#include <string.h>
void timpah(char *dest, char *src, int l_dest, int l_src)
{
int i = 0;
while(i < l_dest)
{
dest[l_dest+i] = src[l_src+i];
i++;
}
}
int main()
{
char res[2024];
res[1] = 0x4f;
char a[] = {0x4b};
timpah(res,a,1,1);
printf("%s [%d]\n",res,strlen(res));
return 0;
}
run
root#xxx:/tmp# gcc -o a a.c
root#xxx:/tmp# ./a
[0]
question
why my code is not working ? or is there any function had exists already to perform these, but i haven't know it yet ?
thx for any attention
You aren't setting res[0] at any point. If res[0] contains \0 your string ends there. You are probably making things harder than they have to be; you can always use strncpy and strncat.
You probably should have a look at strncat(), strncpy(), etc
#include <stdio.h>
#include <string.h>
void timpah(char *dest, char *src, int l_dest, int l_src)
{
int i = 0;
while(i < l_dest)
{
dest[l_dest+i] = src[l_src+i];
i++;
}
}
int main()
{
char res[2024];
res[0] = 0x4f;
char a[] = {0x4b};
timpah(res,a,1,0);
res[2] = '\0';
printf("%s [%d]\n",res,strlen(res));
return 0;
}