char *strcat(char*dest, char*src) {
while (dest != '\0') {
*dest++;
}
while (src != '\0') {
*dest++ = *src++;
}
return dest;
}
I keep getting a segmentation fault on the line *dest++ = *src++. Any ideas on how to fix the problem?
Your code has 4 problems:
you are comparing pointers to the null character instead of comparing the character they point to. Since it will take incrementing the pointer an awful lot of times before it becomes 0, if at all, you are reading and/or writing beyond the end of the buffers, from/to invalid memory before this happens, hence the crash.
you do not null terminate the destination string.
you return the pointer to the end of the destination string instead of the original destination string. This might be a useful API, but you should use a different name for that.
the src pointer should be declared as const char * to conform to the standard declaration for this function and to allow passing pointers to constant strings as sources.
Here is a corrected version:
char *strcat(char *dest, const char *src) {
char *saved = dest;
while (*dest != '\0') {
dest++;
}
while ((*dest++ = *src++) != '\0') {
continue;
}
return saved;
}
Okay: the Kernighan way:
char *strcat(char *dest, char *src)
{
char *org = dest;
while(*dest++){;}
// at this moment, *dest MUST be pointing to '\0'
while(*dest++ = *src++){;}
// at this moment, *dest MUST be pointing to '\0' agian
return org;
}
Update (courtously #chqrlie):
char *strcat(char *dest, char *src)
{
char *org = dest;
for(; *dest; dest++) {;}
// at this moment, dest MUST be pointing to '\0'
while(*dest++ = *src++) {;}
// at this moment, dest points past the '\0', but who cares?
return org;
}
dest and source will never become '\0' if they aren't null to begin with (or maybe after a long time to be correct, but you'll probalby run out of memory long before that).
You should use:
while(*dest != '\0'){
dest++;
}
while(*src != '\0'){
*dest++ = *src++;
}
to check the values underneath the pointers.
There are some other problems too:
the resulting string is not null-terminated.
a pointer to the end of the string is returned.
As mentioned by others: src should be a const pointer too.
This should do it:
char *strcat(char *dest, const char *src)
{
char *start_pos = dest;
while(*dest != '\0')
dest++;
while(*src != '\0')
*dest++ = *src++;
*dest = '\0';
return start_pos;
}
Minor detail: I would give this funtion some other name than the standard used strcat().
Related
I need to write function which will check if string s2 is reverse substring of string s1, and return 1 if the condition is true. Function should be made using pointer arithmetic.
For example:
char s1[] = "abcdef";
char s2[] = "edc";
Function would return 1 because string s1 contains reverse string s2.
#include <stdio.h>
int reverseSubstring(const char *s1, const char *s2) {
while (*s1 != '\0') {
const char *p = s1;
const char *q = s2;
while (*p++ == *q++)
if (*q == '\0')
return 1;
s1++;
}
return 0;
}
int main() {
char s1[] = "abcdef";
char s2[] = "edc";
printf("%d", reverseSubstring(s1, s2));
return 0;
}
This function does the opposite. It checks if the string is substring and in my case it returns 0. It should return 1. How to modify this to work?
Note: it is not allowed to use functions from the string.h, stdlib.h libraries, nor the sprintf and sscanf functions from the stdio.h library. It is not allowed to create auxiliary strings or strings in function or globally.
Slight modification to parts of your code:
const char *q = s2;
while(*q) q++; // Make q point to end of string
while (*p++ == *--q) // Decrement instead of incrementing
if (q == s2) // If we have traversed complete substring
return 1;
This is most likely good enough for a school task, which this most likely is. But it might be good to know that the operation q-- will invoke undefined behavior for an empty string because it will make q point to the element before the string. That can be easily fixed. Just add if(*s2 == '\0') return 1; in the beginning of the function because an empty string is a substring of every string.
For completeness, here is a full version with some small fixes and optimizations. I also took the liberty of replacing a while loop with the library function strlen even if it was forbidden in the task. After all, the while loop is described above, and strlen is easy to implement on your own.
const char *
reverseSubstring(const char *s1, const char *s2) {
if(*s2 == '\0') return s1;
const char *end = s2 + strlen(s2);
while (*s1 != '\0') {
const char *p = s1;
const char *q = end;
while (*p++ == *--q)) {
if (q == s2) return s1;
}
s1++;
}
return NULL;
}
Note that I changed the return type. It returns NULL if no match is found, but if a match is found, it returns a pointer to the first match. That means it contains more information for free.
I was trying to implement a string copy function using pointers as shown below:
#include <stdio.h>
#include <stdlib.h>
void copyStringPtr(char *from, char *to);
int main()
{
char strSource[] = "A string to be copied.";
char strDestination[50];
copyStringPtr(strSource, strDestination); // Doesn't work.
return 0;
}
void copyStringPtr(char *src, char *dst)
{
printf("The destination was\t:\t%s\n", dst);
// for(; *src != '\0'; src++, dst++)
// *dst = *src;
while(*src) // The null character is equivalent to 0, so when '\0' is reached, the condition equals to 0 or false and loop is exited.
*dst++ = *src++;
*dst = '\0';
printf("The source is\t\t:\t%s\n", src);
printf("The destination is\t:\t%s\n\n", dst);
}
The expected output is :
The destination was :
The source is : A string to be copied.
The destination is : A string to be copied.
But the output I'm getting is :
The destination was :
The source is :
The destination is :
As it can be seen, even the source doesn't seem to have the initialized value. What am I doing wrong here?
One issue is that you're not initializing char strDestination[50];. Thus it doesn't represent a valid string and when you try to print it here:
printf("The destination was\t:\t%s\n", dst);
It is undefined behavior. You can initialize it like this:
char strDestination[50] = {'\0'};
This explicitly sets the first char to '\0', making it a valid string. And the rest of the array is then default-initialized to '\0' anyway.
Also, after the while loop, your src and dst will point to the null terminator at the end of the strings, so when you print them, it prints nothing. Instead, keep a copy of the original pointers and print those instead:
void copyStringPtr(char *src, char *dst)
{
char* srcOriginal = src;
char* dstOriginal = dst;
...
printf("The source is\t\t:\t%s\n", srcOriginal);
printf("The destination is\t:\t%s\n\n", dstOriginal);
}
Just take a backup of the original pointers before doing the increment. The reason you lose those pointers is, as part of the iteration in the while the start address of the string is lost and the printf() function does not know where the string starts. Since both the original pointers point at \0 at the end of the loop, the printf() function does not see a an actual string to print up-to
You can even make these backup pointers const to disallow modifications made to them.
void copyStringPtr(char *src, char *dst)
{
printf("The destination was\t:\t%s\n", dst);
/*
* backing up the original source/desination
* pointers
*/
const char *b_src = src; const char *b_dst = dst;
while(*src) // The null character is equivalent to 0, so when '\0' is reached, the condition equals to 0 or false and loop is exited.
*dst++ = *src++;
*dst = '\0';
printf("The source is\t\t:\t%s\n", b_src);
printf("The destination is\t:\t%s\n\n", b_dst);
}
Also as noted in Blaze's answer calling printf() on a uninitialized character array invokes undefined behavior.
I just had to make a minor modification as follows:
#include <stdio.h>
#include <stdlib.h>
void copyStringPtr(char *from, char *to);
int main()
{
char strSource[] = "A string to be copied.";
char strDestination[50];
copyStringPtr(strSource, strDestination); // Doesn't work.
printf("The source is\t\t:\t%s\n", strSource);
printf("The destination is\t:\t%s\n\n", strDestination);
return 0;
}
void copyStringPtr(char *src, char *dst)
{
const char *srcOriginal = src;
const char *dstOriginal = dst;
printf("The destination was\t:\t%s\n", dstOriginal);
// for(; *src != '\0'; src++, dst++)
// *dst = *src;
while(*src) // The null character is equivalent to 0, so when '\0' is reached, the condition equals to 0 or false and loop is exited.
*dst++ = *src++;
*dst = '\0';
}
And it worked just fine. As pointed out by #Jabberwocky in his comment, the pointers *src and *dst in copyStringPtr had moved to the end of the character string and was pointing to the NULL terminator.
#include <stdio.h>
#include <stdlib.h>
void copyStringPtr(char *from, char *to);
int main()
{
char strSource[] = "A string to be copied.";
char strDestination[50] = {0};
copyStringPtr(strSource, strDestination);
return 0;
}
void copyStringPtr(char *src, char *dst)
{
char const *const dstOriginal = dst;
if (!src || !dst){
return;
}
printf("The source is\t\t:\t%s\n", src);
while(src && *src)
*dst++ = *src++;
*dst = '\0';
printf("The destination is\t:\t%s\n\n", dstOriginal );
}
I'm trying to copy a string str into str using pointers. i think this can be achieved using a single pointer itself. whenever i run my code im getting str1 to display but with excessive unwanted garbage characters. please help. provide some insights
#include<stdio.h>
void main()
{
char str[10];
char str1[10];
printf("Enter a string");
scanf("%s",str);
char *p;
char *q;
int len=0,i=0;
p=&str;
q=&str;
while (*p!='\0')
{
len=len+1;
p=p+1;
}
printf("%d",len);
printf("\n");
while (len>0)
{
str1[i]=*q;
len=len-1;
}
printf("%s",str1);
}
str1[i] is always the same element because you never increment i. Thus all the other elements remain untouched and there is never an opportunity for the null terminator of q to be copied over.
Then, when you print it, the program has undefined behaviour.
It would probably be better to loop i from 0 to len.
You should also consider initialising your arrays with = {}, so that they contain nulls in the first place.
Furthermore, your scanf is extraordinarily unsafe as it performs no bounds checking.
Here you have an example:
char *mystrcpy(char *dest, const char *src)
{
char *saveddest = dest;
while(*src)
{
*dest++ = *src++;
}
*dest = 0;
return saveddest;
}
or
char *two_in_one_strcpy_strlen(char *dest, const char *src, size_t *len)
{
char *saveddest = dest;
*len = 0;
while(*src)
{
*dest++ = *src++;
*len++;
}
*dest = 0;
return saveddest;
}
This is the strcat function that I have implemented, but I get a segmentation fault when I go to the line *dst++ = *src++;. I have incremented src till '\0' as I want to append the next string starting from there. Can you please tell me why it gives segmentation fault? Am I doing any logical mistake by doing *dst++ = *src++;?
char *strconcat(char *dst, char *src)
{
char *fdst;
fdst = dst;
if (dst == '\0' || src == '\0')
return fdst;
while (*dst != '\0')
dst++;
while (*src != '\0')
*dst++ = *src++;
return fdst;
}
Hey i went through many solution given below and i made following changes but still i get segmentation problem when i start concatenate two strings, here is my entire code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strconcat(char *dst, const char *src);
void main()
{
char *str1 = "Stack";
char *str2 = "overflow";
printf("MY CONCAT:%s\n",strconcat(str1, str2));
printf("INBUILT CONCAT:%s\n",strcat(str1, str2));
}
char *strconcat(char *dst, const char *src)
{
char *fdst;
int dst_len = 0, src_len = 0;
dst_len = strlen(dst);
src_len = strlen(src);
fdst = (char *) malloc(dst_len + src_len + 1);
fdst = dst;
if (src == NULL)
return fdst;
while(*dst)
{
dst++;
fdst++;
}
while(*src)
*fdst++ = *src++;
*fdst = '\0';
return fdst;
}
The idiomatic way is
while (*dst++ = *src++);
Some observations:
You're not copying the termination, leaving a non-terminated string in dst. This is the cause of the actual problems.
This: if(dst == '\0'||src == '\0') is weird, if the intent was comparing against NULL you should do so more directly and not use character literals.
The src argument should be const char * since it's read-only. Using const for pointers that are "input" arguments is a very good idea, since it communicates intent right there in the prototype. It also helps avoid mistakingly writing to the wrong string.
You can't have a function beginning with str, that "namespace" is reserved for the standard library.
Multiple problems here:
PROBLEM - I
The memory allocated with malloc
fdst = (char *) malloc(dst_len + src_len + 1);
is lost as some lines later you are doing this:
fdst = dst;
replacing the address returned by malloc in 'fdst' with the address of the target string..!! Hope you fix it on your own, its darn simple.
PROBLEM - II
After fixing that above problem, you'll have to fix this:
while(*dst)
{
dst++;
fdst++;
}
don't only increment, you'll also have to copy your characters from dst to fdst as this will be your concatenated string.
PROBLEM - III
finally, you are doing this in the end..!!
return fdst;
you realize the mistake there right? Hope you can take care of that [ Hint: save the starting address and return it in the end, not the incremented pointer ;) ]
Note: Not an optimised solution but, fixes your code.
Possible crash causes:
1) may be the length of your dst is not enougth to support concatunation of src and dst.
2) may be you have called your function with input char pointers which they are not pointed to allocated memory (staic or dynamic)
3) may be your input dst char pointer is pointing to a constant string.
another remark you have to finish your dst string with '\0' after the second while
while (*src != '\0')
*dst++ = *src++;
*dst='\0';
Try this:
while(*original)
original++;
while(*add)
{
*original = *add;
add++;
original++;
}
*original = '\0';
It may be helpful.
There are pretty much errors in your code:
if (dst == '\0' || src == '\0') what you are trying by checking this. First of all this is not clear condition - you should use if (dst == NULL || src == NULL) or if (*dst == '\0' || *src == '\0') to be more accurate and make this more clear. Second even if this condition would be right (if (*dst == '\0' || *src == '\0')) you are not achieving what concatenation should. At least if *src == '\0' you should probably return original string - dst.
You should probably check if dst is long enough to store your new string or you should allocate new buffer inside function big enough to hold both dst and src (malloc (strlen(dst) + strlen(src) + 1) - note extra +1 for holding terminating '/0' character)
You are not terminating your result string.
And the answer for your questions: segmentation fault is probably because your dst is NOT long enough to hold both src and dst. You can use hint in point 2. to modify your code or you can declare bigger buffer outside function that will have size at least (strlen(dst) + strlen(src) + 1.
Another reason could be calling this function with constant string e.g char *str = "string";. In this case most probably string is constant and you are not allowed to modify it (in most operating system this will be located in non-modifiable part of program and you will have only pointer to this location).
Your code is correct , see below for explanation !
I think you are using char * for the src and dst string in the caller.
Using an array declaration there will help, since your program is crashing at
*dst++ = *src++;
because dst and src point to strings which are constants and cannot be modified.
In the following code I have just added main, and your function is unchanged !
#include<stdio.h>
char *strconcat(char *dst, char *src)
{
char *fdst;
fdst = dst;
if (dst == '\0' || src == '\0')
return fdst;
while (*dst != '\0')
dst++;
while (*src != '\0')
*dst++ = *src++;
return fdst;
}
void main()
{
char dest[10] = "one" ;
char src[10] = "two" ;
printf("\n%s " , strconcat( dest , src ) ) ;
}
Although you need to change the if statement to
if (*dst == '\0' || *src == '\0')
return fdst;
is this the standard code for strstr i made????
char* fstrset(char *s,char *t)
{
int b, i=0,j=0;
while(*(s+i)!='\0')
{
if(*(t+j)=='\0')
break;
else if(*(s+i)==*(t+j))
{
i++;j++;b=1;
}
else
{ i++;b=0;j=0;
}
}
if(b==0)
return((char*)NULL);
else if(b==1)
return(s+i-j);
}
This is all the standard has to say about it:
7.21.5.7 The strstr function
Synopsis
#include <string.h>
char *strstr(const char *s1, const char *s2);
Description
The strstr function locates the first
occurrence in the string pointed to by
s1 of the sequence of characters
(excluding the terminating null
character) in the string pointed to by
s2.
Returns
The strstr function
returns a pointer to the located
string, or a null pointer if the
string is not found. If s2 points to a
string with zero length, the function
returns s1.
So, it looks like you're missing const qualifiers on arguments.
As for style, note that *(ptr+index) can be replaced by ptr[index], and size_t is the best type to use for indexing a pointer.
As for being a common way to implement it, compare with GCC's code:
char *
strstr (const char *s1, const char *s2)
{
const char *p = s1;
const size_t len = strlen (s2);
for (; (p = strchr (p, *s2)) != 0; p++)
{
if (strncmp (p, s2, len) == 0)
return (char *)p;
}
return (0);
}
Your code is buggy. Given:
char *haystack = "fififi-trixabelle";
char *needle = "fifi-trixabelle";
fstrset(haystack, needle) returns incorrectly returns NULL.
Besides the bug mentioned by caf there are others:
1) Uninitialized b. If s points to '\0', closing brace may be reached, omitting any return statements.
2) If characters match up to the end of string pointed to by s there is no check if the string pointed to by t ends too.
What does this do? It looks like gibberish. Why adding pointers, and mixing them with ints? Sorry, but the whole thing doesn't make sense.
And to answer your question, i don't think so. But if you compile it and it runs, then yes.
Okay, your code does make sense when you look at it closer. Yes, it does look like it will compile, if thats what you mean by standard code.
inline char* strstr(char* __s1, const char* __s2)
{
return __builtin_strstr(const_cast<const char*>(__s1), __s2);
}
a quick read through seems to show that the code works (there are probably edge cases that dont work). You tell us, does it work?
But why do it? just call strstr
There is no 'standard code', just the standard result.
It is unlikely that any implementation in a standard C library uses array indexing, so it is unlikely that your code matches any implementation in line-by-line detail.
char* fstrstr(char *s1,char *s2)
{
int i=0,flag=0;
char *s4,*s3;
// s4 for retaining the value of s2
s4 = s2;
while(*s1 != '\0' && *s2 != '\0')
{
if(*s1 == *s2)
{
*(s3+i) = *s1;
s2++;
s1++;
i++;
flag = 1;
}
else
{
i = 0;
s1++;
// Initialize s2 again from its address
s2 = s4;
flag = 0;
}
}
if(flag == 1)
{
while(*s1 != '\0')
{
*(s3+i) = *s1;
i++;
s1++;
}
*(s3+i) = '\0';
}
if(flag == 1)
return (s3);
if(flag==0)
{
*s3 = NULL;
return (s3);
}
}
There is no "standard code", only standard results.
It is unlikely that any implementation in the standard C library will use array indexes, so your code is unlikely to match any implementation in the line implementation.
char *strstr(const char *s1, const char *s2) {
char *a = s1, *b = s2;
for (;;)
if (!*b) return (char *)s1;
else if (!*a) return NULL;
else if (*a++ != *b++) {a = ++s1; b = s2;}
}