this code is not printing the copied value of two strings given that are target and source been created above then a function is created that is stringcopy .
#include <stdio.h>
int stringcopy(char *target, char *source) {
char *start = target;
while (*target != '\0') { // this means while target is not equal to 0 that is null charecter
*target = *source;
target++;
source++;
}
*target ='\0';
return *start;
}
int main() {
char source[34] = "Harry";
char target[34];
char copy = stringcopy(target, source);
printf("%s", copy);
return 0;
}
*target != '\0' but *target is uninitialized. You mean *source != '\0'.
Next problem: int stringcopy should be char *stringcopy. Your code will appear to work on a 32 bit platform otherwise, but it will blow up x64. You need to return the correct type.
Third problem: char copy = ; should be char *copy = ; I'm guessing you got here by arbitrarily mutating the code to get it to compile due to the second problem.
Forth problem: return *start; should be return start;. Thanks to Gerhardh for catching it.
Related
According to this:
strcpy vs strdup,
strcpy could be implemented with a loop, they used this while(*ptr2++ = *ptr1++). I have tried to do similar:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
for(char *src="abcdef\0";(*des++ = *src++););
printf("%s\n",des);
}
But that prints nothing, and no error. What went wrong?
Thanks a lot for answers, I have played a bit, and decided how best to design the loop to see how the copying is proceeding byte by byte. This seems the best:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(7);
for(char *src="abcdef", *p=des; (*p++=*src++); printf("%s\n",des));
}
In this loop
for(char *src="abcdef\0";(*des++ = *src++););
the destination pointer des is being changed. So after the loop it does not point to the beginning of the copied string.
Pay attention to that the explicit terminating zero character '\0' is redundant in the string literal.
The loop can look the following way
for ( char *src = "abcdef", *p = des; (*p++ = *src++););
And then after the loop
puts( des );
and
free( des );
You could write a separate function similar to strcpy the following way
char * my_strcpy( char *des, const char *src )
{
for ( char *p = des; ( *p++ = *src++ ); );
return des;
}
And call it like
puts( my_strcpy( des, "abcdef" ) )'
free( des );
You are incrementing des so naturally at the end of the cycle it will be pointing past the end of the string, printing it amounts to undefined behavior, you have to bring it back to the beginning of des.
#include <stdio.h>
#include <stdlib.h>
int main(){
int count = 0;
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
// '\0' is already added by the compiler so you don't need to do it yourself
for(char *src="abcdef";(*des++ = *src++);){
count++; //count the number of increments
}
des -= count + 1; //bring it back to the beginning
printf("%s\n",des);
free(dest); //to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
Or make a pointer to the beginning of des and print that instead.
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
char *ptr = des;
for(char *src="abcdef";(*des++ = *src++);){} //using {} instead of ;, it's clearer
printf("%s\n",ptr);
free(ptr) // or free(dest); to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
printf("%s\n",des); is undefined behavior (UB) as it attempts to print starting beyond the end of the string written to allocated memory.
Copy the string
Save the original pointer, check it and free when done.
const char *src = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(strlen(src) + 1); // 7
char *d = dest;
while (*d++ = *src++);
printf("%s\n", dest);
free(dest);
Copy the string literal
const char src[] = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(sizeof src); // 8
for (size_t i = 0; i<sizeof src; i++) {
dest[i] = src[i];
}
printf("%s\n", dest);
free(dest);
You just need to remember the original allocated pointer.
Do not program in main. Use functions.
#include <stdio.h>
#include <stdlib.h>
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
for(wrk = dest; *wrk++ = *str++;);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
or even better
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrcpy(char *dest, const char *src)
{
char *wrk = dest;
while((*wrk++ = *src++)) ;
return dest;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
mystrcpy(dest, str);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
You allocate the destination buffer des and correctly copy the source string into place. But since you are incrementing des for each character you copy, you have moved des from the start of the string to the end. When you go to print the result, you are printing the last byte which is the nil termination, which is empty.
Instead, you need to keep a pointer to the start of the string, as well as having a pointer to each character you copy.
The smallest change from your original source is:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
char *p = des;
for(char *src="abcdef";(*p++ = *src++););
printf("%s\n",des);
}
So p is the pointer to the next destination character, and moves along the string. But the final string that you print is des, from the start of the allocation.
Of course, you should also allocate strlen(src)+1 worth of bytes for des. And it is not necessary to null-terminate a string literal, since that will be done for you by the compiler.
But that prints nothing, and no error. What went wrong?
des does not point to the start of the string anymore after doing (*des++ = *src++). In fact, des is pointing to one element past the NUL character, which terminates the string, thereafter.
Thus, if you want to print the string by using printf("%s\n",des) it invokes undefined behavior.
You need to store the address value of the "start" pointer (pointing at the first char object of the allocated memory chunk) into a temporary "holder" pointer. There are various ways possible.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
des = temp;
printf("%s\n",des);
free(des);
}
Alternatives:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
printf("%s\n", tmp);
free(tmp);
}
or
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*tmp++ = *src++) ; );
printf("%s\n", des);
free(des);
}
Side notes:
"abcdef\0" - The explicit \0 is not needed. It is appended automatically during translation. Use "abcdef".
Always check the return of memory-management function if the allocation succeeded by checking the returned for a null pointer.
Qualify pointers to string literal by const to avoid unintentional write attempts.
Use sizeof(char) * 10 instead of plain 10 in the call the malloc. This ensures the write size if the type changes.
int main (void) instead of int main (void). The first one is standard-compliant, the second not.
Always free() dynamically allocated memory, since you no longer need the allocated memory. In the example above it would be redundant, but if your program becomes larger and the example is part-focused you should free() the unneeded memory immediately.
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 am working on a string reversal problem where I am trying to swap values from two ends with one another. As a part of the reverse function, I have a line that checks whether the pointer has reached the end-of-string character (in the form of while(*end!= '\0')). However, this doesn't seem to be working, and at the end of the while loop when I de-reference "end" I get blank. When I use (while(*end)), everything works perfectly but I have to then decrement my pointer "end" to make sure I am accessing the last element of my string. Why can't I check the pointer against the string literal '\0'?
#include<stdio.h>
void reverse(char* s);
void main(){
char str[]="abcdef";
printf("%s\n",str);
reverse(str);
printf("%s\n",str);
}
void reverse(char* p){
char* start = p;
char* end = p;
char tmp;
int length =0;
while(*end!='\0'){
end+=1;
length+=1;
}
printf("%c\n",*end); // problem line
int c;
for (c = 0; c < length/2; c++)
{
tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
//printf("%s\n",p);
}
In the //Problem line the value of *end is '\0' - You should print the integer value of '\0' to verify which is 0 & it works - apart from that you'll need to uncomment the } from reverse function.
'\0' is a non printable character: Reference: Non-printable and Printable ASCII Characters
#include <stdio.h>
#include <string.h>
size_t mystrlen(const char *str)
{
const char *ptr = str;
while(*ptr++);
return ptr - str;
}
char *reverse(char *str)
{
size_t len = mystrlen(str);
char *end = str + len -1;
char *saved = str;
len /= 2;
while(len--)
{
char tmp = *str;
*str++ = *end;
*end-- = tmp;
}
return saved;
}
int main(void)
{
char str[] = "This is the string which will be reversed";
printf("%s\n", reverse(str));
}
your code works. end reaches '\0'. but printf prints string until the first '\0'. so your print appears empty. if you add after the while loop:
--end;
or change the while to: while(*(end+1))
your code will do what you want it to
You don't need the length variable, and you can use pre-decrement on end.
#include <stdio.h>
void reverse(char *start);
int main(void) {
char str[]= "abcdef";
printf("%s\n", str);
reverse(str);
printf("%s\n", str);
}
void reverse(char* start) {
char *end = start;
while(*end != '\0') {
end++;
}
while(start < end) {
char temp = *--end;
*end = *start;
*start++ = temp;
}
}
I am trying to append a string t in a string s using pointers.
#include<stdio.h>
#include "my_functions.h"
int main(void)
{
char* s = "H"; /*First string*/
char* t = "W"; /*String to be appended*/
char* buff; /*used to store the initial value of s pointer*/
buff = s;
while(*s != '\0')
{
s++;
}
/*At the end of the loop I will get a memory add where string s
ends*/
/*Start appending second string at that place*/
char* temp; /*Creating a temporary pointer to store content
value of second string*/
temp = t;
t = s; /*t now points to the new starting position for
appending operation*/
*t = *temp; /*------ERROR-------*/
/*Rest is to just print the whole appended string at
once*/
s = buff;
while(*s!='\0')
{
printf("%c\t",*s);
s++;
}
printf("Works Fine");
return 0;
}
I am not getting any output on the terminal, nor any errors. The Idea is to change the content of new location of t which is '\0' to the content of t to be appended that is 'W'. I am a noob. Any suggestions? Where Am I wrong?
I suggest you to study this code:
char *strcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while (*dest++ = *src++)
;
return ret;
}
Obviously the input parameter dest MUST be a pointer that points a memory area at least big as the sum of the two strings length (pointed by dest and src) + 1 byte (the 0 terminator).
I need to extract substrings that are between Strings I know.
I have something like char string = "abcdefg";
I know what I need is between "c" and "f", then my return should be "de".
I know the strncpy() function but do not know how to apply it in the middle of a string.
Thank you.
Here's a full, working example:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
char *first = strstr(string, from);
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
char *last = strstr(first, to);
if (last == NULL) {
last = &string[strlen(string)];
}
char *sub = calloc(strlen(string) + 1, sizeof(char));
strncpy(sub, first, last - first);
printf("%s\n", sub);
free(sub);
return 0;
}
You can check it at this ideone.
Now, the explanation:
1.
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
Declarations of strings: main string to be checked, beginning delimiter, ending delimiter. Note these are arrays as well, so from and to could be, for example, cd and fg, respectively.
2.
char *first = strstr(string, from);
Find occurence of the beginning delimiter in the main string. Note that it finds the first occurence - if you need to find the last one (for example, if you had the string abcabc, and you wanted a substring from the second a), it might need to be different.
3.
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
Handle situation, in which the first delimiter doesn't appear in the string. In such a case, we will make a substring from the beginning of the entire string. If it does appear, however, we move the pointer by length of from string, as we need to extract the substring beginning after the first delimiter (correction thanks to #dau_sama).
Depending on your specifications, this may or may not be needed, or another result might be expected.
4.
char *last = strstr(first, to);
Find occurence of the ending delimiter in the main string. Note that it finds the first occurence.
As noted by #dau_sama, it's better to search for ending delimiter from the first, not from beginning of the entire string. This prevents situations, in which to would appear earlier than from.
5.
if (last == NULL) {
last = &string[strlen(string)];
}
Handle situation, in which the second delimiter doesn't appear in the string. In such a case, we will make a substring until end of the string, so we get a pointer to the last character.
Again, depending on your specifications, this may or may not be needed, or another result might be expected.
6.
char *sub = calloc(last - first + 1, sizeof(char));
strncpy(sub, first, last - first);
Allocate sufficient memory and extract substring based on pointers found earlier. We copy last - first (length of the substring) characters beginning from first character.
7.
printf("%s\n", sub);
Here's the result.
I hope it does present the problem with enough details. Depending on your exact specifications, you may need to alter this somehow. For example, if you needed to find all substrings, and not just the first one, you may want to make a loop for finding first and last.
TY guys, worked using the form below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between_substring(char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main (void){
char source[] = "abcdefg";
char *target;
target = between(source, 'c', 'f');
printf("%s", source);
printf("%s", target);
return 0;
}
Since people seemed to not understand my approach in the comments, here's a quick hacked together stub.
const char* string = "abcdefg";
const char* b = "c";
const char* e = "f";
//look for the first pattern
const char* begin = strstr(string, b);
if(!begin)
return NULL;
//look for the end pattern
const char* end = strstr(begin, e);
if(!end)
return NULL;
end -= strlen(e);
char result[MAXLENGTH];
strncpy(result, begin, end-begin);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between(const char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main(void){
const char* string = "abcdefg";
char *substr = between(string, 'c', 'f');
if(substr!=NULL){
puts(substr);
free(substr);
}
return 0;
}