I want to chain 2 strings in C. The function I use called concat()
First I defined something like this and it worked
char* concat(const char *s1, const char *s2)
{
char* result = malloc (15);
int lengh1 = simple_strlen (s1);
int lengh2 = simple_strlen (s2);
int i=0,j;
for ( i = 0 ;i < lengh1;i++){
if (i!=lengh1-1)
result[i]=s1[i];
else{
result[i]=s1[i];
for ( j=i+1 ; j< lengh1+lengh2;j++){
result[j] = s2[j-i-1];
}
}
}
return result;
}
But then I was asked to do it without malloc() so I defined something like this:
char* concat( char *result, const char *s2)
{
int lengh1 = simple_strlen (result);
int lengh2 = simple_strlen (s2);
int i=0;
for ( i = 0 ;i < lengh2;i++){
result[i+lengh1]=s2[i];
}
return result;
}
but it has segmentation fault
example:
int main(int argc , char* argv[], char* envp[])
{
printf(concat( "hello", "world"));/*output expected "helloworld"*/
return 0;
}
There are multiple problems in your code:
in the malloc version, the space allocated for the destination string is hard coded at 15 instead of computing it as lengh1 + lengh2 + 1, enough space for both strings and the trailing null byte.
you do not set the null terminator at the end of the destination string in both versions.
in your version without malloc, you must provide a large enough array as the destination for concat(). A string constant cannot be modified. A simple solution is to pass the destination buffer and the source strings as separate arguments.
Here are modified versions:
char *concat(const char *s1, const char *s2) {
int length1 = simple_strlen(s1);
int length2 = simple_strlen(s2);
char *result = malloc(length1 + length2 + 1);
int i, j;
for (i = 0; i < length1; i++) {
result[i] = s1[i];
}
for (i = 0; i < length2; i++) {
result[length1 + i] = s2[1];
}
result[length1 + length2] = '\0';
return result;
}
Without malloc():
#include <string.h>
char *concat(char *dest, const char *s1, const char *s2) {
char *p = dest;
while (*s1)
*p++ = *s1++;
while (*s2)
*p++ = *s2++;
*p = '\0';
return dest;
}
int main() {
char buf[100];
/* output expected "helloworld" */
printf("%s\n", concat(buf, "hello", "world"));
return 0;
}
As mentioned by the prior commenters, you need to allocate memory somewhere to store the concatenated string. If you are not allowed to allocate on the heap via malloc, then you can do something like this:
#include "stdafx.h"
# include <string.h>
char* concat( char * result , const char *s1, const char *s2)
{
int lengh1 = strlen(s1);
int lengh2 = strlen(s2);
int i = 0;
for (i = 0; i < lengh1; i++) {
result[i] = s1[i];
}
for (i = 0; i < lengh2; i++) {
result[i+ lengh1] = s2[i];
}
return result;
}
int main()
{
char mybuffer[100];
memset(mybuffer, 0, sizeof(mybuffer));
printf(concat( mybuffer,"hello", "world"));/*output expected "helloworld"*/
return 0;
}
Related
I am having trouble with the very last line in my function, where I am stilly learning the basics of C. I have the signature of this function given and am tasked to write a function to concatenate two strings. The commented line outputs the correct result.
#include <stdio.h>
#include <stdlib.h>
// 1) len = dst-len + max_dst_len
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int total_len = len + max_dst_len;
char *new_str = malloc(sizeof(char) * total_len);
for (int i = 0; i < len; i++) {
new_str[i] = dst[i];
}
for (int i = len; i < total_len; i++) {
new_str[i] = src[i - len];
}
new_str[total_len] = '\0';
//printf("%s <--\n", new_str);
dst = *new_str;
return total_len;
}
int main() {
char test1[] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, 10));
printf("%s\n", test1);
}
You should not be adding max_dst_len to the length of dst. max_dst_len is the amount of memory that's already allocated in dst, you need to ensure that the concatenated string doesn't exceed this length.
So you need to subtract len from max_dst_len, and also subtract 1 to allow room for the null byte. This will tell you the maximum number of bytes you can copy from src to the end of dst.
In your main() code, you need to declare test1 to be at least 10 bytes if you pass 10 as the max_dst_len argument. When you omit the size in the array declaration, it sizes the array just big enough to hold the string you use to initialize it. It's best to use sizeof test1 as this argument, to ensure that it's correct for the string you're concatenating to.
#include <stdio.h>
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int len_to_copy = max_dst_len - len - 1;
int i;
for (i = 0; i < len_to_copy && src[i] != '\0'; i++) {
dst[len+i] = src[i];
}
dst[i] = '\0';
//printf("%s <--\n", new_str);
return i + len;
}
int main() {
char test1[6] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, sizeof test1));
printf("%s\n", test1);
}
I'm new to pointers and I can already see how confusing they can be.
I have tried to look this up in several threads and google but they don't quite return what I'm looking for maybe out of my inexperience.
I'm being passed an array of strings and I have to pass it again to another function however I'm extremely confused on how to do this and don't know what * or & to use or where.
My code:
#include <stdlib.h>
#include <stdio.h>
char *ft_strcat(char *dest, char *src)
{
unsigned int c;
unsigned int count;
count = 0;
while (dest[count] != 0)
{
count++;
}
c = 0;
while (src[c] != '\0')
{
dest[c + count] = src[c];
c++;
}
dest[c + count] = 0;
return (dest);
}
int size_str(char *str)
{
int c;
c = 0;
while (str[c] != '\0')
{
c++;
}
return (c - 1);
}
int size_all(int size, char *strs[], char *sep)
{
int i;
int counter;
i = 0;
counter = 0;
counter += size_str(sep) * (size - 1);
while (i < size)
{
counter += size_str(strs[i]);
i++;
}
return (counter);
}
char *ft_strjoin(int size, char **strs, char *sep)
{
int i;
char *str;
str = malloc(sizeof(char) * size_all(size, strs, sep));
str = strs[0];
i = 1;
while (i < size)
{
str = ft_strcat(str, strs[i]);
}
return (str);
}
int main(void)
{
char *sep = " ";
char a1[] = "Batata";
char a2[] = "frita";
char a3[] = "\'e";
char a4[] = "melhor";
char a5[] = "que";
char a6[] = "Banana";
char *strs[] = {a1, a2, a3, a4, a5, a6};
char *final = ft_strjoin(6, strs, sep);
printf("%s", final);
}
I thought that size all would have to have an extra dereference operator on the declaration of the function and an reference operator when I call it, but this works just fine. Am I doing something wrong or am I just misunderstanding how pointers work? Don't I have to add an extra * each time I pass it?
Finally why doesn't while (src[c] != '\0') work?
In size_str:
There's nothing wrong with while (src[c] != '\0'), but return (c - 1); is causing an off-by-one error with your string lengths. The NUL byte wasn't counted in the loop, there's no need to subtract 1.
In ft_strcat:
The first loop is repeating work that could be handled by a call to size_str.
In ft_strjoin:
str = malloc(sizeof(char) * sizeall(size, strs, sep)));
sizeof (char) is uneccessary, as it is always 1. You need an additional 1 byte added to the length passed to malloc to make room for the NUL byte in your final string.
Remember that pointers are values too. str = strs[0]; assigns the pointer held in strs[0] to the the variable str. It does not copy the contents of strs[0]. You are overwriting the value returned by malloc with a pointer to a different piece of memory.
Instead, given this set of functions, initialize the memory returned by malloc to be the empty string, by setting the first byte to NUL, and use ft_strcat to concatenate the first string.
There's no need to continually reassign the result of ft_strcat, as you are already altering str, and the return value will never change.
A complete example. One must not forget to free the resulting string when it is no longer needed.
#include <stdlib.h>
#include <stdio.h>
int size_str(char *str)
{
int i = 0;
while (str[i])
i++;
return i;
}
char *ft_strcat(char *dest, char *src)
{
int i = 0,
length = size_str(dest);
do
dest[length++] = src[i];
while (src[i++]);
return dest;
}
int size_all(int size, char **strs, char *sep)
{
int total_length = size_str(sep) * (size - 1);
for (int i = 0; i < size; i++)
total_length += size_str(strs[i]);
return total_length;
}
char *ft_strjoin(int size, char **strs, char *sep)
{
char *result = malloc(1 + size_all(size, strs, sep));
result[0] = '\0';
ft_strcat(result, strs[0]);
for (int i = 1; i < size; i++) {
ft_strcat(result, sep);
ft_strcat(result, strs[i]);
}
return result;
}
int main(void)
{
char *sep = " ";
char a1[] = "Batata";
char a2[] = "frita";
char a3[] = "\'e";
char a4[] = "melhor";
char a5[] = "que";
char a6[] = "Banana";
char *strs[] = {a1, a2, a3, a4, a5, a6};
char *final = ft_strjoin(6, strs, sep);
printf("%s\n", final);
free(final);
}
Output:
Batata frita 'e melhor que Banana
I have worked lately about this problematic, string joint. I noticed that you forgot to add an if condition where the size would be 0. Moreover, the while loop need an iteration, which means that it will give you an infinite loop.
You can find as follows some adjustment to your code:
int i;
char *str;
int j;
int k;
i = 0;
k = 0;
str = (char *)malloc(sizeof(char) * sizeall(size, strs, sep) + 1));
if (size == 0)
return (0);
while (i < size)
{
j = 0;
while (strs[i][j])
str[k++] = strs[i][j++];
j = 0;
if (i < size - 1)
while (sep[j])
str[k++] = sep[j++];
i++;
}
str[k] = '\0';
return (str);
Feel free to ask me if there is something you did not understand, and good luck.
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)
Im trying to rewrite strcpy function but im getting stuck in this, my function does not run when the first arg is the static array of chars, only run if it is an allocated pointer. I think the problem is the realloc statement in my function. Please help me for my problem...
#include <stdio.h>
#include <stdlib.h>
int myStrlen(const char *);
char *myStrcpy(char *, const char *);
int main() {
char str1[40];
char str2[] = "one piece";
char *str;
str = (char*)malloc(1 * sizeof(char));
myStrcpy(str, str2);
printf("%s", str);
myStrcpy(str1, str2);
printf("%s", str1);
return 0;
}
int myStrlen(const char *str) {
int i = 0, len = 0;
while (str[i++] != '\0') {
len++;
}
return len;
}
char *myStrcpy(char *str1, const char *str2) {
int len1, len2;
len1 = myStrlen(str1);
len2 = myStrlen(str2);
str1 = (char*)realloc(str1, len2 * sizeof(char));
for (int i = 0; i < len2; i++) {
str1[i] = str2[i];
}
str1[len2] = '\0';
return str1;
}
Please help me to make my code using pointer work...
Btw, here is my function without using pointer, any ideas?
void myStrcpy(char str1[], char str2[]) {
int i = 0;
while (str2[i] != '\0') {
str1[i] = str2[i];
i++;
}
str1[i] = '\0';
}
void myStrncpy(char str1[], char str2[], int n) {
int i = 0;
while (str2[i] != '\0' || i <= n) {
str1[i] = str2[i];
i++;
}
str1[i] = '\0';
}
Your first implementation uses realloc() for no valid purpose. For standard function strcpy(), str1 is assumed to point to an array with enough space to store a copy of str2.
If your intent is to implement different semantics from that of strcpy, make the name more explicit and pass it the address of the destination pointer because realloc() is likely to return a different pointer. In your example, the original value of str is used after the call to myStrcpy(), which is incorrect.
Your second implementation is almost correct:
You should use size_t for the type of i. Strings can be longer than INT_MAX on current systems.
You should make the source strings const.
myStrncpy should stop when i reaches n, use && i < n
Testing i < n before dereferencing the str2 pointer allows an invalid pointer to be passed along with a zero value for n, which can be useful.
myStrcpy and myStrncpy should return the destination pointer.
Note that myStrncpy has much better semantics than strncpy. The standard function strncpy does not do what most programmers expect. Its semantics are error prone, it should not be used to avoid potential confusion.
Here is a simplified version:
#include <stdlib.h>
size_t myStrlen(const char *str) {
size_t len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
char *myStrcpy(char *str1, const char *str2) {
size_t i = 0;
while (str2[i] != '\0') {
str1[i] = str2[i];
i++;
}
str1[i] = '\0';
return str1;
}
char *myStrncpy(char *str1, const char *str2, size_t n) {
size_t i = 0;
while (i < n && str2[i] != '\0') {
str1[i] = str2[i];
i++;
}
str1[i] = '\0';
return str1;
}
A properly written strcpy and strncpy should not need any heap allocation.
char *mystrcpy(char *dest, char *src)
{
char *start = &dest[0];
while(*src) *dest++ = *src++;
return start;
}
char *mystrncpy(char *dest, const char *src, size_t n)
{
size_t i = 0;
char *start = &dest[0];
while(*src && i < n)
{
*dest++ = *src++;
i++;
}
for(; i < n; i++) *dest++ = 0;
return start;
}
for exemple i need to invers "Paris" to "siraP"...
My main:
int main(void)
{
char w1[] = "Paris";
ReverseWord(w1);
printf("The new word is: %s",w1);
return0;
}
and my function:
void ReverseWord(char *Str)
{
int counter=0;
for(int i=0; *(Str+i)!='\0'; i++)
counter++;
int length = counter-1;
char temp[length];
for(int j=0; temp[j]=='\0'; j++)
temp[j]=Str[length-j];
}
Now I have my renverse word in temp[].
I need to put it in my pointer *Str.
How can I do it??
Thanks
If you want use temp must then your function like this
void ReverseWord(char *Str)
{
int i,j;
if(str)
{
int length=strlen(Str);
char temp[length+1];
for( j=0; j<length; j++)
temp[j]=Str[length-1-j];
temp[j]='\0';
strcpy(Str,temp);
}
}
Without using temp as follows
void ReverseWord(char *Str)
{
int end= strlen(Str)-1;
int start = 0;
while( start<end )
{
Str[start] ^= Str[end];
Str[end] ^= Str[start];
Str[start]^= Str[end];
++start;
--end;
}
}
void ReverseWord(char *Str)
{
size_t len;
char temp, *end;
len = strlen(Str);
if (len < 2)
return;
end = Str + len - 1;
while (end > Str)
{
temp = *end;
*end-- = *Str;
*Str++ = temp;
}
}
One more option, this time with dangerous malloc(3).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *rev(char s[]) {
char *buf = (char *)malloc(sizeof(char) * strlen(s));
int i, j;
if(buf != NULL)
for(i = 0, j = strlen(s) - 1; j >= 0; i++, j--)
buf[i] = s[j];
return buf;
}
int main(int argc, char **argv) {
printf("%s\n", rev(argv[1]));
return 0;
}
Run with "foo bar foobar baz" and get zab raboof rab oof back:
~/tmp$ ./a.out "foo bar foobar baz"
zab raboof rab oof
Here I think you can study two algorithms:
C string length calculate: the end of the c string is '\0'
How to reverse a c string in place
And if you need to test the code, you should alloc testing strings in heap or strack. If you write a literal string, you may meet a bus error because of the literal string being saved in text-area which is a read only memory.
And the following is the demo:
#include <stdio.h>
#include <stdlib.h>
void reverse_string(char* str)
{
size_t len;
char tmp, *s;
//Get the length of string, in C the last char of one string is \0
for(s=str;*s;++s) ;
len = s - str;
//Here we use the algorithm for reverse the char inplace.
//We only need a char tmp place for swap each char
s = str + len - 1;
while(s>str){
tmp = *s;
*s = *str;
*str = tmp;
s--;
str++;
}
}
int main()
{
char* a = "abcd";
//Here "abcd" will be saved in READ Only Memory. If you test code, you will get a bus error.
char* b = (char*)calloc(1,10);
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
a = "abcde";
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
}
you can do it simply by following code
for(int k=0;k<strlen(temp);k++)
{
Str[k]=temp[k];
}