Copying array to array using pointer - c

Like a question below, i have to use the pointer concept to copy array from one to another in mystrcpy2 function, unlike mystrcpy function that does not use the pointer concept. Anyway, I typed my answer, " dest = src;" which seemed to be overly simple but right answer for me. But when I type in the input, like "Hello World", it shows like "Hello World ???" like strange letters in the back. But when I type short words like "abc", the result is exactly "abc."
Is it simply a matter of computer or did I do something wrong?
I"m also wondering if "while (*src) *dest++=*src++;" works as well?
/*Complete the mystrcpy2() function that copies the null-terminated string pointed by src to the string pointed by dest.
The mystrcpy2() should give the same result with the mystrcpy() that uses an index based array traversal approach.
Note that adding local variables are not allowed in implementing the mystrcpy2().
Write and submit the source code of your "mystrcpy2()" function.
*/
#include <stdio.h>
void mystrcpy(char dest[], char src[])
{
int i=0,j=0;
while (src[i])
dest[j++] = src[i++];
}
void mystrcpy2(char *dest, char *src)
{
dest = src;
}
int main(void)
{
char mystr1[256];
char mystr2[256];
gets(mystr1);
mystrcpy(mystr2, mystr1);
puts(mystr2);
mystrcpy2(mystr2, mystr1);
puts(mystr2);
return 0;
}

Your implementation of mystrcpy2 does not copy anything. In fact, it does nothing at all. When you execute dest = src, you are copying the memory location pointed to by the src variable, not the data at that location. To actually copy the data, you need to deference the pointer, using '*'. So you would do
*dest = *src;
This copies the data from src to dest. But it only copies one character. You need to increment src and dest and then do this again to copy the next character, and you need to keep doing this until you hit the string terminator i.e. until *src == 0. Here's the full implementation.
void mystrcpy2(char *dest, char *src)
{
while (*src != 0) {
*dest = *src;
dest++;
src++;
}
// don't forget to add a terminator
// to the copied string
*dest = 0;
}
And here's the exact same thing in a shorter version.
void mystrcpy2(char *dest, char *src)
{
while (*(dest++) = *(src++));
}

Related

C: One error In strcpy function and cannot find it

I know that this strcpy function below is incorrect, but I cannot seem to figure out the one or two things I need to change to fix it. Any help would be greatly appreciated as I am completely stuck on this:
void strcpy(char *destString, char *sourceString)
{
char *marker, *t;
for(marker = sourceString, t = destString; *marker; marker++, t++)
*t = *marker;
}
Well it depends on your environment..
For example I see a few things I don't like:
You do not check for input parameters to be != NULL. This will cause a *0 access
I see you are not terminating your string with the '\0' character (or 0).. So, after the loop (please intent.) add *t = 0;
strcpy() is a predefined function and you are trying to create your own strcpy function. so, when you compile your program, you are getting conflicting types error. So, first rename your function name.
If you want to implement your own strcpy(), then i would suggest to implement strncpy(). It will copy at-most n-1 bytes from source null-terminated character array to destination character array and also add null character at the end of the destination character array.
void strcpy(char *dest, const char *src, size_t n)
{
if ((dest == NULL) || (src == NULL))
return;
int i;
for(i=0; i<(n-1) && src[i]; i++)
dest[i] = src[i];
dest[i]='\0';
}
It wouldn't let buffer overflow.
Note - My implementation is different from standard library strncpy() implementation. The standard library function strncpy() copies at most n bytes of src. If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
I know that this strcpy function below is incorrect, but I cannot seem to figure out the one or two things I need to change to fix it.
You only need to add null character at the end of destination array.
void strcpy(char *destString, char *sourceString)
{
char *marker, *t;
for(marker = sourceString, t = destString; *marker; marker++, t++)
*t = *marker;
*t='\0';
}
This is a very simple aproach:
void copy(char * src, char * dst){
while(*src != '\0'){
*dst = *src;
src++;
dst++;
}
*dst = '\0';
}
int main(int argc, char** argv){
char src [] = "hello";
char dst [] = "----";
copy(src, dst);
printf("src: %s\n", src);
printf("dst: %s\n", dst );
}
It's more or less like wildplasser comment. First you iterate over the src pointer. In c, if you have '\0' (in a well formed string) then you can exit because it is the final character. Ok, you iterate over the src pointer and assign the value of src (*src) to the value of dst (*dst) and then you only have to increase both pointers...
It's all
A very easy strcpy function would be:
int strcpy(char *dest,char *source)
{
if (source==NULL)
{
printf("The source pointer is NULL");
return 0;
}
if (dest==NULL)
{
dest=(char*)malloc((strlen(source)+1)*sizeof(char));
}
int i;
for (i=0;source[i]!='\0';i++)
{
dest[i]=source[i];
}
dest[i]='\0';
return 1;
}
You should have no problem copying strings this way. Always use indexes instead of pointer operations, it's easier imo.
If you use an IDE, you should learn to use the debug function to discover the errors and problems, usually when you deal with strings one of the most common RUNTIME problems is the lack of a '\0', which automatically make your string functions go to memory zones where they shouldn`t be.

How to copy a string in C

if I have the function scopy that copies a C String from src to dest
char * scopy(char *dest, char *src) {
char* r = dest;
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = *src;
return r;
}
Why does this function work when called on 2 String initialized like this
char a[6] = "abbbb" and
char b[4] = "dcd"
but doesn't work on Strings initialized like this
char * a = "abbbb" and
char * b = "dcd"
This function invokes undefined behavior when used like that because it tries to modify a string literal, so you can't say it works in either case.
The fact that it appears to work on the char[] is a coincidence -- an unfortunate one, because it gives the wrong impression.
In the code below, variable ptr is pointing to a read-only memory section, which contains "xyz\0". You can change the variable itself, but you can't change the contents of the memory it is pointing to...
char* ptr = "xyz";
In the code below, variable arr is pointing to a read/write memory section, which contains "xyz\0". You can't change the variable itself, but you can change the contents of the memory it is pointing to...
char arr[] = "xyz";
The above should help you to understand why you are getting a segmentation fault in the first case...
Having said that, you have yet another problem in your code - if the string pointed by src is longer than the string pointed by dest, then *dest = *src will most likely cause a segmentation fault:
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
char*a = "abbbb" is called a string literal, which iirc behaves differently than a char[] in c. Specifically, I do not believe you can modify the individual characters for a string literal.
Try looking here for more information between the two constructors

Interview Question-Concatenate two Strings without using strcat in C

Recently I attended an interview where they asked me to write a C program to concatenate two strings without using strcat(), strlen() and strcmp() and that function should not exceed two (2) lines.
I know how to concatenate two strings without using strcat(). But my method has nearly 15 lines. I dont know how to write it in two lines.
I expect they wanted something like this:
void mystrcat(char * dest, const char * src)
{
//advance dest until we find the terminating null
while (*dest) ++dest;
//copy src to dest including terminating null, until we hit the end of src
//Edit: originally this:
//for (; *dest = *src, *src; ++dest, ++src);
//...which is the same as this
for (; *dest = *src; ++dest, ++src);
}
It doesn't return the end of the concatenated string like the real strcat, but that doesn't seem to be required.
I don't necessarily know if this sort of thing is a good interview question - it shows that you can code tersely, and that you know what strcat does, but that's about it.
Edit: as aib writes, the statement
while (*dest++ = *src++);
...is perhaps a more conventional way of writing the second loop (instead of using for).
Given that the task was to concatenate two strings, not to create a duplicate of strcat, I'd go with the simple option of creating a completely new string that is a combination of the two.
char buffer[REASONABLE_MAX] = {0};
snprintf(buffer, REASONABLE_MAX - 1, "%s%s", string1, string2);
The proper answer to that question is that the question would demonstrate a skill that it is bad to have. They are wanting you to demonstrate the ability to write hacker code. They are wanting you to invent your own implementation of things provided already by every C compiler, which is waste of time. They are wanting you to write streamlined code which, by definition, is not readable. The 15 line implementation is probably better if it is more readable. Most projects do not fail because the developers wasted 150 clock cycles. Some do fail because someone wrote unmaintainable code. If you did have to write that, it would need a 15 line comment. So my answer to that would be, show me the performance metrics that defend needing to not use the standard libraries and requiring the most optimal solution. Time is much better spent on design and gathering those performance metrics.
Never forget - you are also interviewing them.
//assuming szA contains "first string" and szB contains "second string"
//and both are null terminated
// iterate over A until you get to null, then iterate over B and add to the end of A
// and then add null termination to A
// WARNING: memory corruption likely if either string is not NULL terminated
// WARNING: memory corruption likely if the storage buffer for A was not allocated large
// enough for A to store all of B's data
// Justification: Performance metric XXX has shown this optimization is needed
for(int i=0; szA[i]!='\0'; i++);
for(int j=0; (j==0)||(szB[j-1]!='\0'); j++) szA[i+j] = szB[j];
*edit, 9/27/2010
After reading some other solutions to this, I think the following is probably the best code answer:
//Posted by Doug in answer below this one
void my_strcat(char * dest, const char * src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
}
But I would follow that up with a safe version of that:
void my_safe_strcat(char * dest, const unsigned int max_size, const char * src)
{
int characters_used=0;
while (*dest) { ++dest; characters_used++; }
while ( (characters_used < (max_size-1) ) && (*dest++ = *src++) ) characters_used++;
*dest = 0; //ensure we end with a null
}
And follow that up with (full answer, which compiler will optimize to be the same as above, along with application which was the real question):
void my_readable_safe_strcat(char * dest, const unsigned int max_size, const char * src)
{
unsigned int characters_used = 0;
while (*dest != '\0')
{
++dest;
characters_used++;
}
while ( (characters_used < (max_size-1) ) && (*dest = *src) )
{
dest++;
src++;
characters_used++;
}
*dest = 0; //ensure we end with a null
}
int _tmain(int argc, _TCHAR* argv[])
{
char szTooShort[15] = "First String";
char szLongEnough[50] = "First String";
char szClean[] = "Second String";
char szDirty[5] = {'f','g','h','i','j'};
my_readable_safe_strcat(szTooShort,15,szClean);
printf("This string should be cut off:\n%s\n\n",szTooShort);
my_readable_safe_strcat(szLongEnough,50,szClean);
printf("This string should be complete:\n%s\n\n",szLongEnough);
my_readable_safe_strcat(szLongEnough,50,szDirty);
printf("This string probably has junk data in it, but shouldn't crash the app:\n%s\n\n",szLongEnough);
}
Two lines? Bwah...
void another_strcat(char* str1, const char* str2)
{
strcpy(strchr(str1, '\0'), str2);
}
EDIT: I'm very upset that people are so against strcpy and strchr. Waah! So, I thought I'd play by the spirit of the rules:
char thing(char* p, const char* s)
{
return *p ? thing(&p[1], s) : *s ? (*p++ = *s++, thing(p, s)) : *p = '\0';
}
I still can't understand how anyone would take 2 whole lines ;-P.
I tested this bit in VS2008, and it worked fine.
void NewStrCat(char* dest, const char* src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
}
Any function can be made to fit in a single line by simply removing all the \n.
However, I think you're looking for this answer:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char string1[32] = "Hello";
char string2[] = ", World!";
char *dst = string1 + strlen(string1);
char *src = string2;
while (*dst++ = *src++); //single statement
printf("\"%s\"\n", string1);
return EXIT_SUCCESS;
}
The explanation is rather simple:
src++ returns a pointer to the current character being copied before incrementing to point to the next one. * dereferences this pointer, and a similar expression on the LHS copies it to dst. Result of the whole = expression is the character that was copied, hence a simple while loops it until a \0 is encountered and copied.
However:
strcat() is easier to read and possibly much faster. Any other solution is feasible only when strcat() is not available. (Or when you're in an interview, apparently.)
And replace strcat() above with strncat() unless you're really really sure the destination string is big enough.
Edit: I missed the part about strlen() being disallowed. Here's the two-statement function:
void my_strcat(char * restrict dst, const char * restrict src)
{
while (*dst) ++dst; //move dst to the end of the string
while (*dst++ = *src++); //copy src to dst
}
Note that the standard strcat() function returns the original value of dst.
One line:
sprintf(string1, "%s%s", string1, string2);
(Note that this might possibly invoke undefined behavior.)
Addendum
The ISO C99 standard states that:
If copying takes place between objects that overlap, the behavior is undefined.
That being said, the code above will still probably work correctly. It works with MS VC 2010.
I have a feeling such questions are meant to be elimination questions rather than selection. It is easier to eliminate candidates for them based on such convoluted questions rather than select candidates by asking them more real world questions.
Just a rant from me, since I am also looking for a job and facing such questions and answered quite a few of them thanks to SO!
void StringCatenation(char *str1,char *str2)
{
int len1,i=0;
for(len1=0;*(str1+len1);len1++);
do{
str1[len1+i]=str2[i];
i++;
}
while(*(str2+i);
}
void my_strcat(char* dest, const char* src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
*dest = '\0';
}
Destination string must end with NULL terminated.

Programs executes correctly and then segfaults

I'm trying to learn C programming and spent some time practicing with pointers this morning, by writing a little function to replace the lowercase characters in a string to their uppercase counterparts. This is what I got:
#include <stdio.h>
#include <string.h>
char *to_upper(char *src);
int main(void) {
char *a = "hello world";
printf("String at %p is \"%s\"\n", a, a);
printf("Uppercase becomes \"%s\"\n", to_upper(a));
printf("Uppercase becomes \"%s\"\n", to_upper(a));
return 0;
}
char *to_upper(char *src) {
char *dest;
int i;
for (i=0;i<strlen(src);i++) {
if ( 71 < *(src + i) && 123 > *(src + i)){
*(dest+i) = *(src + i) ^ 32;
} else {
*(dest+i) = *(src + i);
}
}
return dest;
}
This runs fine and prints exactly what it should (including the repetition of the "HELLO WORLD" line), but afterwards ends in a Segmentation fault. What I can't understand is that the function is clearly compiling, executing and returning successfully, and the flow in main continues. So is the Segmentation fault happening at return 0?
dest is uninitialised in your to_upper() function. So, you're overwriting some random part of memory when you do that, and evidently that causes your program to crash as you try to return from main().
If you want to modify the value in place, initialise dest:
char *dest = src;
If you want to make a copy of the value, try:
char *dest = strdup(src);
If you do this, you will need to make sure somebody calls free() on the pointer returned by to_upper() (unless you don't care about memory leaks).
Like everyone else has pointed out, the problem is that dest hasn't been initialized and is pointing to a random location that contains something important. You have several choices of how to deal with this:
Allocate the dest buffer dynamically and return that pointer value, which the caller is responsible for freeing;
Assign dest to point to src and modify the value in place (in which case you'll have to change the declaration of a in main() from char *a = "hello world"; to char a[] = "hello world";, otherwise you'll be trying to modify the contents of a string literal, which is undefined);
Pass the destination buffer as a separate argument.
Option 1 -- allocate the target buffer dynamically:
char *to_upper(char *src)
{
char *dest = malloc(strlen(src) + 1);
...
}
Option 2 -- have dest point to src and modify the string in place:
int main(void)
{
char a[] = "hello world";
...
}
char *to_upper(char *src)
{
char *dest = src;
...
}
Option 3 -- have main() pass the target buffer as an argument:
int main(void)
{
char *a = "hello world";
char *b = malloc(strlen(a) + 1); // or char b[12];
...
printf("Uppercase becomes %s\n", to_upper(a,b));
...
free(b); // omit if b is statically allocated
return 0;
}
char *to_upper(char *src, char *dest)
{
...
return dest;
}
Of the three, I prefer the third option; you're not modifying the input (so it doesn't matter whether a is an array of char or a pointer to a string literal) and you're not splitting memory management responsibilities between functions (i.e., main() is solely responsible for allocating and freeing the destination buffer).
I realize you're trying to familiarize yourself with how pointers work and some other low-level details, but bear in mind that a[i] is easier to read and follow than *(a+i). Also, there are number of functions in the standard library such as islower() and toupper() that don't rely on specific encodings (such as ASCII):
#include <ctype.h>
...
if (islower(src[i])
dest[i] = toupper(src[i]);
As others have said, your problem is not allocating enough space for dest. There is another, more subtle problem with your code.
To convert to uppercase, you are testing a given char to see if it lies between 71 ans 123, and if it does, you xor the value with 32. This assumes ASCII encoding of characters. ASCII is the most widely used encoding, but it is not the only one.
It is better to write code that works for every type of encoding. If we were sure that 'a', 'b', ..., 'z', and 'A', 'B', ..., 'Z', are contiguous, then we could calculate the offset from the lowercase letters to the uppercase ones and use that to change case:
/* WARNING: WRONG CODE */
if (c >= 'a' && c <= 'z') c = c + 'A' - 'a';
But unfortunately, there is no such guarantee given by the C standard. In fact EBCDIC encoding is an example.
So, to convert to uppercase, you can either do it the easy way:
#include <ctype.h>
int d = toupper(c);
or, roll your own:
/* Untested, modifies it in-place */
char *to_upper(char *src)
{
static const char *lower = "abcdefghijklmnopqrstuvwxyz";
static const char *upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static size_t n = strlen(lower);
size_t i;
size_t m = strlen(src);
for (i=0; i < m; ++i) {
char *tmp;
while ((tmp = strchr(lower, src[i])) != NULL) {
src[i] = upper[tmp-lower];
}
}
}
The advantage of toupper() is that it checks the current locale to convert characters to upper case. This may make æ to Æ for example, which is usually the correct thing to do. Note: I use only English and Hindi characters myself, so I could be wrong about my particular example!
As noted by others, your problem is that char *dest is uninitialized. You can modify src's memory in place, as Greg Hewgill suggests, or you can use malloc to reserve some:
char *dest = (char *)malloc(strlen(src) + 1);
Note that the use of strdup suggested by Greg performs this call to malloc under the covers. The '+ 1' is to reserve space for the null terminator, '\0', which you should also be copying from src to dest. (Your current example only goes up to strlen, which does not include the null terminator.) Can I suggest that you add a line like this after your loop?
*(dest + i) = 0;
This will correctly terminate the string. Note that this only applies if you choose to go the malloc route. Modifying the memory in place or using strdup will take care of this problem for you. I'm just pointing it out because you mentioned you were trying to learn.
Hope this helps.

Access violation when using strcpy?

I've tried reinventing the strcpy C function, but when I try to run it I get this error:
Unhandled exception at 0x00411506 in brainf%ck.exe: 0xC0000005: Access violation writing location 0x00415760.
The error occurs in the *dest = *src; line. Here's the code:
char* strcpy(char* dest, const char* src) {
char* dest2 = dest;
while (*src) {
*dest = *src;
src++;
dest++;
}
*dest = '\0';
return dest2;
}
EDIT: Wow, that was fast. Here's the calling code (strcpy is defined in mystring.c):
#include "mystring.h"
#include <stdio.h>
int main() {
char* s = "hello";
char* t = "abc";
printf("%s", strcpy(s, t));
getchar();
return 0;
}
char* s = "hello";
char* t = "abc";
printf("%s", strcpy(s, t));
The compiler placed your destination buffer, s, in read-only memory since it is a constant.
char s[5];
char* t = "abc";
printf("%s", strcpy(s, t));
Should fix this problem. This allocates the destination array on the stack, which is writable.
The obvious potential problem is that your output buffer doesn't have enough memory allocated, or you've passed in NULL for dest. (Probably not for src or it would have failed on the line before.)
Please give a short but complete program to reproduce the problem, and we can check...
Here's an example which goes bang for me on Windows:
#include <stdlib.h>
char* strcpy(char* dest, const char* src) {
char* dest2 = dest;
while (*src) {
*dest = *src;
src++;
dest++;
}
*dest = '\0';
return dest2;
}
void main() {
char *d = malloc(3);
strcpy(d, "hello there this is a longish string");
}
Note that in this case I had to exceed the actual allocated memory by a fair amount before I could provoke the program to die - just "hello" didn't crash, although it certainly could depending on various aspects of the compiler and execution environment.
Your strcpy() is fine. You are writing to read-only memory. See this description here.
If you had written this, you'd be fine:
#include "mystring.h"
#include <stdio.h>
int main() {
char s[] = "hello";
char t[] = "abc";
printf("%s", strcpy(s, t));
getchar();
return 0;
}
There is a problem with calling of your reinvented strcpy routine in the main routine, both character array:
char* s = "hello";
char* t = "abc";
will land into memory READ ONLY segment at compile time. As you're trying to write to memory pointed by s in the routine strcpy, and since it points to a location in a READ ONLY segment, it will be caught, and you'll get an exception. These strings are READ ONLY!
Make sure dest has it's memory allocated before calling that function.
Probably an issue with the caller: did you check the dest pointer? Does it point to something valid or just garbage? Besides that, the least you could do is check for null pointers, like if (!dest || !source) { /* do something, like return NULL or throw an exception */ } on function entry. The code looks OK. Not very safe, but OK.
There are several errors.
You don't allocate a return buffer that can hold the copied string.
You don't check to see if src is null before using *src
You are both tring to get the answer in a parameter and return the value. Do one or the other.
You can easily overrun the dest buffer.
Good luck.
when ever the code starting execution(generaly it starts from main function). here the code means sequence of execution.so, when the process(sequence of execution) starts , the PCB(process control block) is created,the pcb having complete infromation about the process like process address space,kernal stack,ofdt table like this.
in your code
char* s = "hello";
char* t = "abc";
this is the what you have taken inputs of two strings like this.
here, the the strings(which means double quoted) which are present in text section of the process address space . here text section is the one of the section which is present in the process address space and text section only having the permissions of read-only. that is why when you trying to modify the source string/destination string, we MUST NOT allowable to change the whatever data is present in the text setion. so, this is what the reason for your code you need to be CAUTIOUS. hope you understand.

Resources