I have written following c code to update the char array rb but it is printing garbage value
#include <stdio.h>
void update(char* buff){
char word[] = "HII_O";
buff = word;
return;
}
int main(){
char rb[6];
update(rb);
rb[5] = '\0';
printf("[%s]\n",rb);
return 0;
}
The restriction is we can't use any other library. So how to solve this
Within the function update the parameter buff is a local variable of the function that will not be alive after exiting the function.
You can imagine the function call the following way
update( rb );
//...
void update( /*char* buff*/){
char *buff = rb;
char word[] = "HII_O";
buff = word;
return;
}
As you see the original array was not changed.
That is at first the pointer buff was initialized by the address of the first element of the source array rb.
char *buff = rb;
and then this pointer was reassigned with the address of the first element of the local character array word
buff = word;
What you need is to copy characters of the string literal "HII_O" into the source array rb using standard string function strcpy or strncpy.
For example
#include <string.h>
#include <stdio.h>
void update(char* buff){
strcpy( buff, "HII_O" );
}
int main(){
char rb[6];
update(rb);
printf("[%s]\n",rb);
return 0;
}
As you cannot use any library function, just do de copying cell by cell, change
void update( /*char* buff*/){
char *buff = rb;
char word[] = "HII_O";
buff = word;
return;
}
(you cannot assign arrays as a whole in C)
into:
void update(char *buff) {
char *word = "HII_O";
int index;
/* copy characters, one by one, until character is '\0' */
for (index = 0; word[index] != '\0'; index = index + 1) {
buff[index] = word[index];
}
/* index ended pointing to the next character, so we can
* do the next assignment. */
buff[index] = '\0'; /* ...and copy also the '\0' */
}
buff is a local variable to the function. It is initialized to point to the first element of the rb array in main but changes to buff will not change the rb array. So
buff = word;
makes buff point to the string literal "HII_O" but there is no change to the rb array.
The normal solution would be
void update(char* buff){
strcpy(buff, "HII_O");
}
However, you write ...
The restriction is we can't use any other library.
Well, in order to set a fixed value like your code does, you don't need any library function.
You don't any need other variables, string literals, etc.
Just simple character assignments like:
void update(char* buff){
buff[0] = 'H';
buff[1] = 'I';
buff[2] = 'I';
buff[3] = '_';
buff[4] = 'O';
buff[5] = '\0';
}
int main(){
char rb[6];
update(rb);
printf("[%s]\n",rb);
return 0;
}
Related
Why this works:
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char st[] = "Hello";
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
And this doesn't:
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char*st = "Hello";
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
In first I initialized my string using:
char st[]="Hello"; (using array)
And in latter I used:
char*st="Hello"; (using pointer)
I'm kind of getting confused between these 2 initialization types, what's the key difference between declaring a string by using char st[]="Hello"; and by using char*st = "Hello";.
With char st[] = "Hello";, st[] is a modifiable array of characters. The call slice(st, 1, 6); takes the array st and converts to a pointer to the first element of the array. slice() then receives that pointer, a pointer to modifiable characters.
With char *st = "Hello";, st is a pointer that points to a string literal "Hello". With the call slice(st, 1, 6);, the function receives a copy of the pointer - a pointer to the string literal. Inside slice(), code st[i] = ... is attempting to modify a string literal, that is undefined behavior (UB). It might work, it might fail, it might work today and fail tomorrow - it is not defined.
Do not attempt to modify a string literal.
... passing strings to a function ...
In both cases, code does not pass a string to slice(), but a pointer to a string. Knowing that subtle distinction helps in understanding what is truly happening.
This is an artifact of old syntax in C:
char * s = "Hello world!";
is a non-const character pointer to const memory. It is still permitted by syntax, but the string is still not a mutable object. To be pedantic it should really be written as:
const char * s = "Hello world!";
In contrast:
char s[] = "Hello world!";
allocates a local (on the stack), mutable array and copies the string data to it (from wherever the non-mutable copy is stored in memory). Your function can then do as it likes to your local copy of the string.
The type char [] is different from the type char* (char* is a variable - int. but char[] is an array which is not a variable). However, an array name can be used as a pointer to the array.
So we can say that st[] is technically similar to *str .
the problem in the 2nd version of your code
If you have read-only strings then you can use const char* st = "hello"; or simply char* st = "hello"; . So the string is most probably be stored in a read-only memory location and you'll not be able to modify it.
However, if you want to be able to modify it, use the malloc function:
char *st= (char*) malloc(n*sizeof(char)); /* n-The initial size that you need */
// ...
free(st);
**So to allocate memory for st, count the characters ("hello"-strlen(st)=5) and add 1 for this terminating null character , and functions like scanf and strcpy will add the null character;
so the code becomes :
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char *st =malloc(6*sizeof(char)) ;
const char *cpy="hello";
strcpy(st, cpy); /* copies the string pointed by cpy (including the null character) to the st. */
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
you can fill your string also by a for loop or by scanf() .
in the case of a large allocation you must end your code with free(st);
So I've looked around on SO and can't find code that answers my question. I have written a function that is supposed to reverse a string as input in cmd-line. Here is the function:
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string)];
for (x = strlen(string) - 1; x > 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
string = line;
}
When I call my reverse() function, the string stays the same. i.e., 'abc' remains 'abc'
If more info is needed or question is inappropriate, let me know.
Thanks!!
You're declaring your line array one char shorter remember the null at the end.
Another point, it should be for (x = strlen(string) - 1; x >= 0; x--) since you need to copy the character at 0.
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string) + 1];
for (x = strlen(string) - 1; x >= 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
for(x = 0; x < strlen(string); x++)
{
string[x] = line[x];
}
}
Note that this function will cause an apocalypse when passed an empty string or a string literal (as Bobby Sacamano said).
Suggestion you can probably do: void reverse(char source[], char[] dest) and do checks if the source string is empty.
I think that your answer is almost correct. You don't actually need an extra slot for the null character in line. You just need two minor changes:
Change the assignment statement at the bottom of the procedure to a memcpy.
Change the loop condition to <-
So, your correct code is this:
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string)];
for (x = strlen(string) - 1; x >= 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
memcpy(string, line, sizeof(char) * strlen(line));
}
Since you want to reverse a string, you first must decide whether you want to reverse a copy of the string, or reverse the string in-situ (in place). Since you asked about this in 'C' context, assume you mean to change the existing string (reverse the existing string) and make a copy of the string in the calling function if you want to preserve the original.
You will need the string library
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Array indexing works, and this version takes that approach,
/* this first version uses array indexing */
char*
streverse_a(char string[])
{
int len; /*how big is your string*/
int ndx; /*because 'i' is hard to search for*/
char tmp; /*hold character to swap*/
if(!string) return(string); /*avoid NULL*/
if( (len=strlen(string)) < 2 ) return(string); /*one and done*/
for( ndx=0; ndx<len/2; ndx++ ) {
tmp=string[ndx];
string[ndx]=string[len-1-ndx];
string[len-1-ndx]=tmp;
}
return(string);
}
But you can do the same with pointers,
/* this is how K&R would write the function with pointers */
char*
streverse(char* sp)
{
int len, ndx; /*how big is your string */
char tmp, *bp, *ep; /*pointers to begin/end, swap temporary*/
if(!sp) return(sp); /*avoid NULL*/
if( (len=strlen(bp=sp)) < 2 ) return(sp); /*one and done*/
for( ep=bp+len-1; bp<ep; bp++, ep-- ) {
tmp=*bp; *bp=*ep; *ep=tmp; /*swap*/
}
return(sp);
}
(No, really, the compiler does not charge less for returning void.)
And because you always test your code,
char s[][100] = {
"", "A", "AB", "ABC", "ABCD", "ABCDE",
"hello, world", "goodbye, cruel world", "pwnz0r3d", "enough"
};
int
main()
{
/* suppose your string is declared as 'a' */
char a[100];
strcpy(a,"reverse string");
/*make a copy of 'a', declared the same as a[]*/
char b[100];
strcpy(b,a);
streverse_a(b);
printf("a:%s, r:%s\n",a,b);
/*duplicate 'a'*/
char *rp = strdup(a);
streverse(rp);
printf("a:%s, r:%s\n",a,rp);
free(rp);
int ndx;
for( ndx=0; ndx<10; ++ndx ) {
/*make a copy of 's', declared the same as s[]*/
char b[100];
strcpy(b,s[ndx]);
streverse_a(b);
printf("s:%s, r:%s\n",s[ndx],b);
/*duplicate 's'*/
char *rp = strdup(s[ndx]);
streverse(rp);
printf("s:%s, r:%s\n",s[ndx],rp);
free(rp);
}
}
The last line in your code does nothing
string = line;
Parameters are passed by value, so if you change their value, that is only local to the function. Pointers are the value of the address of memory they are pointing to. If you want to modify the pointer that the function was passed, you need to take a pointer to that pointer.
Here is a short example of how you could do that.
void reverse (char **string) {
char line = malloc(strlen(*string) + 1);
//automatic arrays are deallocated once the function ends
//so line needs to be dynamically or statically allocated
// do something to line
*string = line;
}
The obvious issue with this is that you can initialize the string with static memory, then this method will replace the static memory with dynamic memory, and then you'll have to free the dynamic memory. There's nothing functionally wrong with that, it's just a bit dangerous, since accidentally freeing the string literal is illegal.
char *test = "hello";
reverse(test);
free(test); //this is pretty scary
Also, if test was allocated as dynamic memory, the pointer to it would be lost and then it would become a memory leak.
So, I have seen this strcpy implementation in C:
void strcpy1(char dest[], const char source[])
{
int i = 0;
while (1)
{
dest[i] = source[i];
if (dest[i] == '\0')
{
break;
}
i++;
}
}
Which to me, it even copies the \0 from source to destination.
And I have also seen this version:
// Move the assignment into the test
void strcpy2(char dest[], const char source[])
{
int i = 0;
while ((dest[i] = source[i]) != '\0')
{
i++;
}
}
Which to me, it will break when trying to assign \0 from source to dest.
What would be the correct option, copying \0 or not?
The code should look like as follows:
char * strcpy(char *strDest, const char *strSrc)
{
assert(strDest!=NULL && strSrc!=NULL);
char *temp = strDest;
while(*strDest++ = *strSrc++); // or while((*strDest++=*strSrc++) != '\0');
return temp;
}
You can NOT delete the second line char *temp = strDest; and directly return strDest. This will cause error for the returned content. For example, it will not return correct value (should be 22) will checking the length of returned char *.
char src_str[] = "C programming language";
char dst_str[100];
printf("dst_str: %d\n", strlen(strcpy(dst_str, src_str)));
Both copy the terminator, thus both are correct.
Note that strcpy2() does the assignment (the copying) first, then the comparison. So it will copy the terminator before realizing it did, and stopping.
Also, note that functions whose names start with str are reserved, so neither of these are actually valid as "user-level" code.
You're wrong. Both copy the \0 (NUL terminator) character. You have to copy the NUL terminator character always or your string will be broken: you'll never know when/where it ends.
Both copy the terminator, thus both are correct.
strcpy2() does the copying first, then the compares. Thus it will copy the terminator and stops.
The functions whose names start with str are reserved, so use any other variables or naming types
It is recommended not to advance the input pointers to the source and destination memory spaces, since the pointers will be used in main right away.
I've mentioned alternate methodical syntax, where in case someone might wonder the code output.
void strcpy1(char * s, char * p)
{
char * temp1 = s;
char * temp2 = p;
while(*temp1 != '\0')
{
*temp2 = *temp1;
temp1++;
temp2++;
}
*temp2 = '\0';
}
void main()
{
char * a = "Hello";
char b[10];
strcpy1(a,b);
printf("%s", b);
return 0;
}
Both strcpy1() and strcpy2() does the same. Both copy the NUL character to the end of the destination array.
Here is full implementation. You do not have to consider the \0 at the end in the first string, it will be copied automatically from the second string as per logic
//str copy function self made
char *strcpynew(char *d, char *s){
char *saved = d;
while ((*d++ = *s++) != '\0');
return saved; //returning starting address of s1
}
//default function that is run by C everytime
int main(){
//FOR STRCPY
char s1[] = "rahul"; //initializing strings
char s2[] = "arora"; //initializing strings
strcpynew(s1, s2);
printf("strcpy: %s\n", s1); //updated string after strcpy
}
You can use this code, the simpler the better !
Inside while() we copy char by char and moving pointer to the next. When the last char \0 will pass and copy while receive 0 and stop.
void StrCopy( char* _dst, const char* _src )
{
while((*_dst++ = *_src++));
}
char * strcpy(char *strDest, const char *strSrc)
{
assert(strDest!=NULL && strSrc!=NULL);
assert(strSrc + strlen(strSrc) < d || strSrc > strDest); // see note
char *temp = strDest;
while(*strDest++ = *strSrc++)
;
return temp;
}
// without the check on line 4, the new string overwrites the old including the null deliminator, causing the copy unable to stop.
Both copy the '\0'. That's what you have to do if you want to fully emulate the original strcpy
Language: C
I am trying to program a C function which uses the header char *strrev2(const char *string) as part of interview preparation, the closest (working) solution is below, however I would like an implementation which does not include malloc... Is this possible? As it returns a character meaning if I use malloc, a free would have to be used within another function.
char *strrev2(const char *string){
int l=strlen(string);
char *r=malloc(l+1);
for(int j=0;j<l;j++){
r[j] = string[l-j-1];
}
r[l] = '\0';
return r;
}
[EDIT] I have already written implementations using a buffer and without the char. Thanks tho!
No - you need a malloc.
Other options are:
Modify the string in-place, but since you have a const char * and you aren't allowed to change the function signature, this is not possible here.
Add a parameter so that the user provides a buffer into which the result is written, but again this is not possible without changing the signature (or using globals, which is a really bad idea).
You may do it this way and let the caller responsible for freeing the memory. Or you can allow the caller to pass in an allocated char buffer, thus the allocation and the free are all done by caller:
void strrev2(const char *string, char* output)
{
// place the reversed string onto 'output' here
}
For caller:
char buffer[100];
char *input = "Hello World";
strrev2(input, buffer);
// the reversed string now in buffer
You could use a static char[1024]; (1024 is an example size), store all strings used in this buffer and return the memory address which contains each string. The following code snippet may contain bugs but will probably give you the idea.
#include <stdio.h>
#include <string.h>
char* strrev2(const char* str)
{
static char buffer[1024];
static int last_access; //Points to leftmost available byte;
//Check if buffer has enough place to store the new string
if( strlen(str) <= (1024 - last_access) )
{
char* return_address = &(buffer[last_access]);
int i;
//FixMe - Make me faster
for( i = 0; i < strlen(str) ; ++i )
{
buffer[last_access++] = str[strlen(str) - 1 - i];
}
buffer[last_access] = 0;
++last_access;
return return_address;
}else
{
return 0;
}
}
int main()
{
char* test1 = "This is a test String";
char* test2 = "George!";
puts(strrev2(test1));
puts(strrev2(test2));
return 0 ;
}
reverse string in place
char *reverse (char *str)
{
register char c, *begin, *end;
begin = end = str;
while (*end != '\0') end ++;
while (begin < --end)
{
c = *begin;
*begin++ = *end;
*end = c;
}
return str;
}
Using pointer arithmetic, it's possible to assign characters from one array to another. My question is, how does one do it given arbitrary start and stop points?
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
char *ptr1 = &string1[start];
char *ptr2 = string2;
while (*ptr2++ = *ptr1++) { } //but stop after 3 elements???
printf("%s",&string2);
}
There's some kind of pointer arithmetic I'm missing to count/test the quantity of elements in a particular array. I do NOT want to declare an integral to count the loop! I want to do it all using pointers. Thanks!
When you write ptr1++;, it is equivalent to ptr1 = ptr1 + 1;. Adding an integer to a pointer moves the memory location of the pointer by the size (in bytes) of the type being pointed to. If ptr1 is a char pointer with value 0x5678 then incrementing it by one makes it 0x5679, because sizeof(char) == 1. But if ptr1 was a Foo *, and sizeof(Foo) == 12, then incrementing the pointer would make its value 0x5684.
If you want to point to an element that is 3 elements away from an element you already have a pointer to, you just add 3 to that pointer. In your question, you wrote:
char *ptr1 = &string1[start]; // array notation
Which is the same thing as:
char *ptr1 = string1 + start; // pointer arithmetic
You could rewrite as follows:
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
// Ensure there is enough room to copy the substring
// and a terminating null character.
assert(count < sizeof(string2));
// Set pointers to the beginning and end of the substring.
const char *from = string1 + start;
const char *end = from + count;
// Set a pointer to the destination.
char *to = string2;
// Copy the indicated characters from the substring,
// possibly stopping early if the end of the substring
// is reached before count characters have been copied.
while (from < end && *from)
{
*to++ = *from++
}
// Ensure the destination string is null terminated
*to = '\0';
printf("%s",&string2);
}
Using const and meaningful variable names (from, to, or src, dst, instead of ptr1, ptr2) helps you avoid mistakes. Using assert and ensuring the string is null-terminated helps you avoid having to debug segfaults and other weirdness. In this case the destination buffer is already zeroed, but when you copy parts of this code to use in another program it may not be.
#include <stdio.h>
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
char *ptr1 = &string1[start];
char *stop = ptr1 + count;
char *ptr2 = string2;
while ((ptr1 < stop) && (*ptr2++ = *ptr1++));
printf("%s",string2);
return 0;
}
I usually use a specific set of variable names in these situations, called:
src - source
dst - destination
end - the end of either the source (used here) or the destination
So:
int main(void)
{
char string1[] = "something";
int start = 2;
int count = 3;
char string2[10] = {0};
const char *src = &string1[start];
const char *end = &string1[start+count];
char *dst = string2;
assert(count < sizeof(string2);
while (src < end)
*dst++ = *src++;
*dst = '\0'; // Null-terminate copied string!
printf("%s",&string2);
return(0);
}
Or, more plausibly, packaged as a function:
char *copy_substr(char *dst, const char *str, size_t start, size_t len)
{
const char *src = str + start;
const char *end = src + len;
while (src < end)
*dst++ = *src++;
*dst = '\0';
return(dst);
}
int main(void)
{
char string1[] = "something";
char *end;
char string2[10] = {0};
end = copy_substr(string2, string1, 2, 3);
printf("%s",&string2);
return(0);
}
The function returns a pointer to the end of the string which is aconventional and doesn't provide a marked benefit in the example, but which does have some merits when you are building a string piecemeal:
struct substr
{
const char *str;
size_t off;
size_t len;
};
static struct substr list[] =
{
{ "abcdefghijklmnopqrstuvwxyz", 2, 5 },
...
{ "abcdefghijklmnopqrstuvwxyz", 18, 3 },
};
int main(void)
{
char buffer[256];
char *str = buffer;
char *end = buffer + sizeof(buffer) - 1;
size_t i;
for (i = 0; i < 5; i++)
{
if (str + list[i].len >= end)
break;
str = copy_substr(str, list[i].str, list[i].off, list[i].len);
}
printf("%s\n", buffer);
return(0);
}
The main point is that the return value - a pointer to the NUL at the end of the string - is what you need for string concatenation operations. (In this example, with strings that have known lengths, you could survive without this return value without needing to use strlen() or strcat() repeatedly; in contexts where the called function copies an amount of data that cannot be determined by the calling routine, the pointer to the end is even more useful.)
In order to get the size (i.e. number of elements) in a static array, you would usually do
sizeof(string1) / sizeof(*string1)
which will divide the size (in bytes) of the array by the size (in bytes) of each element, thus giving you the number of elements in the array.
But as you're obviously trying to implement a strcpy clone, you could simply break the loop if the source character *ptr1 is '\0' (C strings are zero-terminated). If you only want to copy N characters, you could break if ptr1 >= string1 + start + count.