The code below is related to calculating length of string
#include <stdio.h>
int strl (char *s);
main ()
{
int len1 = str ("hah");
printf ("%d", len1);
}
int
str (char *s)
{
int length = 0;
while (*s != '\0')
{
length++;
s++;
}
return (length);
}
When I call the function str, I am assigning a string literal to pointer and not the address of the string literal to the pointer but it turn out that address is stored. How can pointers store address of "hah" without specifying its address?
"hah" is of type char[] so when you pass it to function, it decays to pointer to its first element, as any other array.
You don't need to be specifying its address, first of all - you've typed str("hah"); and not strl("hah"); (same when you wrote the function) - the string literal does actaully count as a variable in the function's stack memory and memory is allocated to it. What's more is that when appointing a string literal this way:
char* str = "hah";
char* sstr = "hah";
when printing:
printf("%d %d", str, sstr);
you'd get the same number. Using string literal - the compiler searches for the same string in the memory and if it's not there - it's allocating memory to it. In this case - there WAS a string the same so the addresses the pointers points to would be the same.
The correct program would be this way:
#include <stdio.h>
int strl(char *s);
int main()
{
int len1=strl("hah");
printf("%d",len1);
return 0;
}
int strl(char *s)
{
int length=0;
while (*s!='\0')
{
length++;
s++;
}
return (length);
}
just changing str to strl as you mistook str for strl or the opposite :P
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);
I am trying to add 10 strings containing the word "data" in a char array and return the result. Here is my code:
#include <stdio.h>
#include <string.h>
char* concat () {
char src[50], dest[1];
strcpy(src, "data");
int i =0;
for (i=0; i<=10; i++) {
strcat(dest, src);
strcat(dest, ",");
}
return(dest);
}
int main () {
printf("Final destination string : |%s|", concat());
return 0;
}
But when I return my dest char array I get a segmentation fault.
i can not return my dest char array, i have segmentation fault => because dest is array of only one char, you can't store store "data" 10 times into dest. Instead of dest[1] , take dest as char pointer and allocate memory dynamically.
you may want to do like below
#include <stdio.h>
#include <string.h>
char* concat () {
char src[50], *dest;
dest = malloc(100 * sizeof(char)); /* allocating 100 bytes for dest, allocate according to your requirement */
strcpy(src, "data");
int i =0,j;
for (i=0,j=0; i<=10; i++) {
strcat(dest+j, src);//first time dest points to starting address
strcat(dest, ",");
j = strlen(dest);/* next time put data at dest+j location */
}
dest[j]= '\0';
return dest ;
}
int main () {
char * ret = NULL;
printf("Final destination string : |%s|\n", ret = concat());
free(ret); /* to avoid memory leakage */
return 0;
}
I hope it helps.
You have the wrong idea that strcat allocates memory when it concatenates strings. It is wrong. So by using 1-length char array in strcat you have invoked undefined behavior because it will write to memory that is out of the bound of the single element char array.
Also the dest variable having automatic storage duration - you can't use it once the scope on which it is declared ends(which is in this case when the function ends). Using a variable after it's lifetime is over is undefined behavior.
Another thing is the strcat's first parameter is null terminated char array which is not the case here, so it is also undefined behavior using the wrong parameter to the strcat.
Provided that dest can hold any concatenated string you are working on this function you can do this
char s[]="data";
char* dest = malloc(MAXLEN);
if(!dest){ perror("malloc"); exit(EXIT_FAILURE);}
for(int i = 0; i <10; i++){
if(!i) strcpy(dest,src);
else
strcat(dest,src);
strcat(dest,",");
}
return dest;
In main():
char *s;
printf("Final destination string : |%s|", (s=concat()));
free(s);
I want to manually set each individual character for my pointer instead of typing out the string/having another array and then simply copying the values. This is homework, but I have it finished.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*function declarations */
void assignAlpha(char *pointer);
void assignNumeric(char *pointer);
int main()
{
char *cp;
assignAlpha(cp);
assignNumeric(cp);
}
void assignAlpha(char *pointer)
{
/* allocate space for a-z character string */
pointer = malloc(26*sizeof(char));
char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
strcpy(pointer, alphabet);
/*print the values*/
printf("%s\n", pointer);
/*free the memory allocated */
free(pointer);
}
void assignNumeric(char *pointer)
{
/* allocate space for the 0-9 character string*/
pointer = malloc(10*sizeof(char));
/* input values */
char alphaArray[10];
int currentChar = 30;
int i;
for(i = 0; i <10; i++)
{
alphaArray[i] = i + '0';
currentChar++;
}
/* copy string to pointer */
strcpy(pointer, alphaArray);
/* print out the results */
printf("%s\n", pointer);
/* free the memory allocated */
free(pointer);
}
What I have tried doing, but it seems to fail:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*function declarations */
void assignAlpha(char *pointer);
void assignNumeric(char *pointer);
int main()
{
char *cp;
assignAlpha(cp);
assignNumeric(cp);
}
void assignAlpha(char *pointer)
{
/* allocate space for a-z character string */
pointer = malloc(26*sizeof(char));
int i;
for (i=0; i < 26; i++)
{
pointer = i + 'a';
pointer++;
}
/*print the values*/
printf("%s\n", pointer);
/*free the memory allocated */
free(pointer);
}
I thought that if I go through each memmory address that I have allocated and set the value to the next character it would work, but I apparently was wrong. Like I said this was a homework assignment, but I could hand in what I have that works and be fine. Any guidance on how to do this (if its possible) would be appericated!
Edit: I get the following error compiling "Assignment makes pointer from integer without a cast"
When you assign to a pointer, you need to dereference it, like this:
*pointer = i + 'a';
Instead of:
pointer = i + 'a';
Otherwise, all you're doing is changing the value of the pointer itself, not the value of the memory location it is pointing to.
This explains your error: you're trying to assign the value i + 'a' (which is an integer) to a pointer type.
Another issue is that your malloc call needs to allocate 27 characters, not 26, because you also need a terminating NUL character.
Finally, when you go to print, your pointer has moved past the end of the string (because you've been incrementing it in your loop). The easiest way to fix this is to change pointer = i + 'a'; to pointer[i] = i + 'a'; and remove the pointer++
I have Wrote the Following Code Snippet but it is not working.
Can anyone help me? Where i am Wrong ??
char *xstrrev(char *string)
{
int len=0,i=0;
char *reverse;
while(*string!='\0')
{
len++;
string++;
}
len=len-1;
while(len>=0)
{
*reverse=string[len];
reverse++;
len--;
}
*reverse='\0';
return reverse;
}
int main()
{
char name[10];
scanf("%s",name);
printf("%s",xstrrev(name));
return 0;
}
I am unable to return whole string in the main function
The problem starts (and ends) with
*reverse=string[len];
where reverse is not initialized. This invokes undefined behavior.
You need to initialize reverse to make it point to a valid memory location before you can dereference the pointer.
Since you are expecting to _return_ the new _string_ from your function and use it in the caller, you should use memory allocator functions, like malloc() to allocate memory and initialize the reverse with the returned pointer, after the success check of the malloc() call. You also need to take care of free()-ing the allocated memory , once you're done using it.
After that, as per your logic, you're doing reverse++; and in the end, you're returning reverse, so think of the exact value which is getting returned. You're returning a pointer to the end of the string, not a pointer to the start of it. You need to keep a copy of the actual start of reverse and return that.
Three problems:
[1] reverse not pointing to valid memory area.
[2] returning reverse will return the last byte address of string reverse. so need to store the start of reverse and return the start of reverse.
[3] string is completely parsed while calculating the length, so again, start of original string needs to be saved and used subsequently
char *xstrrev(char *string)
{
char *original_string = string;
int len=0,i=0;
//[1] char *reverse;
while(*string!='\0')
{
len++;
string++;
}
//[3] till here "string" is completely parsed, so it points to past the end.
char *reverse = (char*)malloc(len + 1);
char *reverse_to_be_returned = reverse;
len=len-1;
while(len>=0)
{
//[3] *reverse=string[len];
*reverse = original_string[len];
reverse++;
len--;
}
*reverse='\0';
//[2] return reverse;
return reverse_to_be_returned;
}
You need to allocate space for char *reverse to point to. This can be done with malloc or strdup.
Basically:
malloc()allocates requested memory on the heap, and returns a void* pointer in the end.
You also need to check the return pointer of any call to malloc(), as sometimes it can return NULL if something wrong happens.
You also need to free this requested memory at the end, just to be safe.
Additionally, since you are returning a pointer, you need to make sure it points at the start of the string, instead of the end.
Your code can look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMESTRLEN 10
char *xstrrev(char *string);
int
main(void) {
char name[NAMESTRLEN+1];
char *result;
printf("Enter string: ");
scanf("%10s", name);
result = xstrrev(name);
printf("Reversed string = %s\n", result);
free(result);
return 0;
}
char
*xstrrev(char *string) {
char *result;
size_t slen, count = 0;
int i;
slen = strlen(string);
result = malloc(slen+1); /* +1 for nullbyte */
if (!result) {
printf("Cannot allocate space for string.\n");
exit(EXIT_FAILURE);
}
for (i = slen-1; i >= 0; i--) {
result[count++] = string[i];
}
result[count] = '\0';
return result;
}
so I was practicing writing c code with pointers using the K&R. For one problem with strcat function, I couldn't find out what was wrong with my code, which according to Visual Studio, returned the destination string unchanged after the strcat function. Any suggestion is appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strcat(char* s, char* t);
int main(void)
{
char *s="hello ", *t="world";
strcat(s,t);
printf("%s",s);
return 0;
}
int strcat(char* s,char* t)
{
int i;
i=strlen(s)+strlen(t);
s=(char*) malloc(i);
while(*s!='\0')
s++;
while('\0'!=(*s++=*t++))
;
return 0;
}
I'm pretty sure that strcat returns a char* in the real implementation (holding the original value of the first string).
strcat is not supposed to alter the first parameter's address, so you shouldn't call malloc.
Point #2 means that you need to declare char *s as char s[20] in main (where 20 is some arbitrary number big enough to hold the whole string).
If you really want to alter the value of the an input parameter you will need to pass the address of the value - so it would need to be strcat(char **s, ...) in the function declaration/definition, and called with strcat(&s, ...) in main.
1) defining string in this way
char *s="hello "
means that you are defined a literal string. a literal string is saved into read only memory so you can not edit it
you have to define your string as a char array in order to be able to edit it
char s[100] = "hello ";
2) when you define your function in this way
int strcat(char* s,char* t)
you can not change the address of s into the function strcat(). So assigning memory with malloc() into the function will not change the s address when leaving the function
3) change your function strcat to
int strcat(char** s,char* t)
{
int i;
char *u, *v;
i=strlen(*s)+strlen(t);
v = *s;
u=(char*) malloc(i+1);
while(*v!='\0')
*u++ = *v++;
while('\0'!=(*u++=*t++));
*s = u;
return 0;
}
and you call it in the main with:
char *s="hello ", *t="world";
strcat(&s,t);
In
strcat(char* s, char* t)
the 's' is send by value. The value of 's' at call time is copied into the stack then strcat() is call. At the return of strcat the modified version is discard from the stack. So the calling value of 's' is never changed (and you create a memory leak).
Beward, in C every memory cell can be change, even parameters or instructions sections; some changes can be very hard to understand.
Since you are trying to do like the real strcat it's said that the first parameter
The string s1 must have sufficient space to hold the result.
so you don't need to use malloc
char *strcat(char* s, const char* t);
int main(void)
{
char s[15] = {0}; //
char *t = "world"; //const char * so you can't change it
strcpy(s, "Hello ");
strcat(s,t);
printf("%s\n",s);
return (0);
}
char *strcat(char* s, const char* t)
{
int i = 0;
while (s[i] != '\0')
i++;
while (*t != '\0')
s[i++] = *t++;
s[i] = '\0'; //useless because already initialized with 0
return (s);
}
#include<stdio.h>
#include<string.h>
#define LIMIT 100
void strcatt(char*,char*);
main()
{
int i=0;
char s[LIMIT];
char t[LIMIT];
strcpy(s,"hello");
strcpy(t,"world");
strcatt(s,t);
printf("%s",s);
getch();
}
void strcatt(char *s,char *t)
{
while(*s!='\0')
{
s++;
}
*s=' ';
++s;
while(*t!='\0')
{
*s=*t;
s++;
t++;
}
*s=*t;
}
Dear user,
you don't have to complicate things that much. The simpliest code for strcat, using pointers:
void strcat(char *s, char *t) {
while(*s++); /*This will point after the '\0' */
--s; /*So we decrement the pointer to point to '\0' */
while(*s++ = *t++); /*This will copy the '\0' from *t also */
}
Although, this won't give you report about the concatenation's success.
Look at this main() part for the rest of the answer:
int main() {
char s[60] = "Hello ";
char *t = "world!";
strcat(s, t);
printf("%s\n", s);
return 0;
}
The s[60] part is very important, because you can't concatenate an another string to it's end if it doesn't have enough space for that.