change string to point to next character in function - c

#include <stdio.h>
void change(char *str)
{
(*str++);
return;
}
int main()
{
char *str = "ABC";
printf("before change %s \n",str);
change(str);
printf("after change %s \n",str);
return 0;
}
Output of the program is
ABC
ABC
I want output to be
ABC
BC
I don't want to return string, str needs to be modified in change function; return type of change function should remain void. I don't know how to do this.
I did try to google it but i didn't find the solution.

In C if you want to change the value of an argument to a function, you need to take that argument by pointer. And since here you are trying to change a pointer, it needs to be a pointer to a pointer:
void change(char **str)
{
(*str)++;
}
Then:
change(&str);

The expression (*str++); increments a local copy of str, not str from main. This is because C uses pass-by-value technique for function parameters.
You need to change your function to take a pointer to pointer, and pass a pointer to str in order to achieve the desired effect.

As we are in C would you need a pointer to a pointer.
I.e
void change(char **str)
{
*str = *str + 1;
}
Then
int main()
{
char *str = "ABC";
printf("before change %s \n",str);
change(&str);
printf("after change %s \n",str);
return 0;
}
See https://ideone.com/Ouo19v

Related

How do I return and print out the starting address of the first string (string1)?

I first copy the second string into the first string. Then I would return string1 pointer from the function. Then I use
%p and (void*)
to print out the starting address of the first string. Is this the right approach?
printf("address: %p \n", (void*)functionstrcpy(stringnumber1,stringnumber 2));
return 0;
}
char *functionstrcpy(char *stringnumber1,char *stringnumber2)
{
//calculation
return stringnumber1;
}
How do I return and print out the .... address of the ... string?
I use "%p" and (void*) to print out the starting address of the first string. Is this the right approach?
Yes. The return is correct and "%p" expects to match a void *. Yet since char * and void * are the same encoding and size, either will work.
printf("address: %p \n", (void*)functionstrcpy(str1,str2));
// or
printf("address: %p \n", functionstrcpy(str1,str2));
Thus the choice is best according to your group's style guide.
The function declaration should look like
char * functionstrcpy( char *str1, const char *str2 );
As you are using already the standard C function strlen then why not to use another string function strcpy? In this case the function can be just a wrapper for the function strcpy without any additional functionality.
char * functionstrcpy( char *str1, const char *str2 )
{
return strcpy( str1, str2 );
}
If you want to write the function yourself without using the standard C function strcpy then its definition can look like
char * functionstrcpy( char *str1, const char *str2 )
{
for ( char *p = str1; ( *p++ = *str2++ ); );
return str1;
}
You may use the returned pointer in the call of printf like
printf("address: %p \n", (void*)functionstrcpy(str1,str2));
because you are just outputting the value of a valid pointer.

Why isn't this function(char*) pass by ref?

Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void set(char* str){
str = malloc(10);
strcpy(str, "dog");
printf("\nstr = %s", str);
}
int main(){
char* s;
set(s);
printf("\n%s", s);
return 0;
}
Here's what I want to print out:
str = dog
dog
Here's what actuall gets printed out:
str = dog
(null)
Why is this? What I think I'm doing is passing an uninitalized pointer that then gets assigned a block of memory in set(), which then gets "dog" written into. What's actually going on?
There is no pass-by-reference in C. But pointers and indirection gives a facility to mimic that indirectly.
In your case, what is sent from main() to set() is the address in variable 's'. It
will have that value till malloc() statement executes. After that, str will have whatever address is returned by malloc().
When the same thing is expected in main, what should have been passed is the address
of 's' rather than what address it holds (like some of the examples above).
C is a pass-by-value language. There is no way to pass something by reference except explicitly. For your case that means expecting a pointer-to-a-pointer:
void set(char **str)
{
*str = malloc(10);
strcpy(*str, "dog");
printf("str = %s\n", *str);
}
And calling with the address of the pointer you want to 'fill in':
int main(void)
{
char *s;
set(&s);
printf("%s\n", s);
return 0;
}
Why isn't this function(char*) pass by ref?
C doesn’t have pass-by-reference. Everything is pass-by-value – it’s just that some values are also pointers to other values. Your uninitialized variable s is read when you call set(s) (which is undefined behaviour) in order to provide a value for its parameter str, then str = malloc(10) throws that value away to assign a new value to the local str.
You can pass a pointer to the pointer:
void set(char** str){
*str = malloc(10);
strcpy(*str, "dog");
printf("\nstr = %s", *str);
}
int main(){
char* s;
set(&s);
printf("\n%s", s);
return 0;
}
or return a pointer:
char* set(void) {
char* str = malloc(10);
strcpy(str, "dog");
printf("\nstr = %s", str);
return str;
}
int main(){
char* s = set();
printf("\n%s", s);
return 0;
}
You are passing an unasigned pointer to your set function, here a copy of the pointer is made and you use malloc on that copy. The original pointer in main is never updated with the new memory address.
To achieve what you want could be done this way:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void set(char** str){
*str = malloc(10);
strcpy(*str, "dog");
printf("\nstr = %s", *str);
}
int main(){
char* s;
set(&s);
printf("\n%s", s);
return 0;
}
I used a pointer to a pointer in set, and pass the memory address of the pointer s to it.

Make a function that reads (string) input

I'm new to programming and I have an assignment to make a function that reads a name. For some reason the following 'solution' does not work and the output is always something with weird chinese? characters. What went wrong?
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
I think the problem is in your
*a = buff;
statement because buff does not have a life outside of your function. so its memory will be lost.. so it is not safe to try and use buff in this way...
[ But as pointed out by #pablo what *a = buff; will do is copy the address of buff and put it into the memory allocated to a, which is really not what you want to do. ]
below should work and do include return from your function
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main()
{
char name[8];
input(&name);
printf("%s", name);
return 0;
}
void input(char* a)
{
// char buff[8];
scanf("%s", a);
// *a = buff;
return;
}
one other point is to check if you are sure the name will only be 8 characters long... why not have it as 50 characters?
First off, you should pass the array to the function input() not its address. Secondly, replace scanf("%s", buff) with scanf("%s", a). This will store the string directly in the array you pass to the function.
So, the fixed code should look like:
#include <stdio.h>
#include <stdlib.h>
void input(char* a);
int main(void)
{
char name[8];
input(name);
printf("%s\n", name);
return 0;
}
void input(char* a)
{
scanf("%s", a);
}
The reason why your code doesn't work is that, you try to assign address of the local array buff to the first element of the array that you pass to the function. This shouldn't even compile or the compiler must issue a warning! If your compiler allows it to pass without any of these, that's a disaster.
Finally, the main function should be declared as int main(void) or int main(int argc, char **argv).
*a = buff; doesn't copy buff to a. Use strcpy() as
strcpy(a,buff);
complete code :
void input(char* a);
int main()
{
char name[8];
//input(&name);/** no need to pass & bcz name itself represents address */
input(name);
printf("[%s]", name);
return 0;
}
void input(char* a) {
char buff[8];
scanf("%s", buff);
//*a = buff; /* not valid **/
strcpy(a,buff);
}
This function is a problem:
void input(char* a)
{
char buff[8];
scanf("%s", buff);
*a = buff;
}
buff is local variable that is only valid while input() is running, so
returning this variable is wrong.
*a = buff; is also wrong. *a is the same as a[0], that means it is a
char. buff is an array of char, so you are assigning a pointer to an array
of char to a char variable. That doesn't sound right, it's putting apples in
the oranges box. In fact what is happening is that you are assigning the address
pointed to by buff in the memory pointed to by a.
Your compiler should have warned you about that, don't ignore the
compiler warnings, they are there to help you, not annoy you,
void input(char *a)
{
scanf("%s", a);
}
would be the correct function.
Doing
char name[8];
input(&name);
is wrong, even though the address of name and &name will be the same, but
they will have different types. name decays into a pointer, so it is a
char*. However &name is a pointer to an array of char, a different type.
The compiler should give you a warning like this:
warning: passing argument 1 of bar from incompatible pointer type
note: expected char * but argument is of type char (*)[8]
The correct call is:
input(name);
In general there is one big problem, though: You only declare 8 spaces for the
buffer. If the name is longer than 7 characters, you will have a buffer
overflow. Instead of using scanf I recommend using fgets instead, because
here you have much more control of the input and the memory boundaries.
char name[30];
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = 0; // removing possible newline
scanf is not always easy to use. A name can be long and have spaces in it.
Specially for a beginner, this can be tricky. fgets is easier to use.
You don't need to pass the address of name since it's a char array. And when you do the copy in input(), you should use strcpy. The following code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void input(char* a);
int main()
{
char name[8];
input(name);
printf("%s", name);
return 0;
}
void input(char* a)
{
char buff[8];
scanf("%s", buff);
strcpy(a, buff);
}

Function not modyfing a character array

Im just starting to learn pointers and I'm trying to figure out why my code doesn't work. I get no compilation error yet the code doesn't what I want it to do. Why am I not passing the adress of an array? If I try to do so I get a compiilation error :(
#include <stdio.h>
void switch_name(char* name)
{
name= "testv2";
}
void main()
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name(name1);
printf("%s\n", name1);
}
Well because C is pass by value. You make changes to a local variable(name in function swicth_name()). To retain changes pass the address of the char* and assign the address of the string literal to the char* directly (By dereferencing the char**). For example this would work
#include <stdio.h>
void switch_name(char** name)
{
*name= "testv2";
}
int main(void)
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name(&name1);
printf("%s\n", name1);
return 0;
}
Here the function swicth_name got the address of the char* name1. Now when you dereference it using unary * in switch_name you assign the address of the string literal to the name variable of main(). That' swhy the change retains.
Function parameters are its local variables.
You can imagine the function call and its definition the following way
char *name1 = "test_name";
switch_name(name1);
//...
void switch_name( /* char* name */ )
{
char *name = name1;
name= "testv2";
}
As you can see the original variable name1 was not changed in the function. It is the variable name that is the parameter that was changed in the function.
You have to pass the original variable by reference if you are going to change it in the function.
For example
#include <stdio.h>
void switch_name( char ** name)
{
*name= "testv2";
}
int main( void )
{
char *name1 = "test_name";
printf("%s\n", name1);
switch_name( &name1 );
printf("%s\n", name1);
}
Compare the above program with the following program
#include <stdio.h>
#include <string.h>
void switch_name( char* name )
{
strcpy( name, "testv2" );
}
int main(void)
{
char s[] = "test_name";
char *name1 = s;
printf( "%s\n", name1 );
switch_name( name1 );
printf( "%s\n", name1 );
return 0;
}
In the first program you are going to reassign the original pointer itself using a function.
In the second program it is the data pointed to by the pointer that are reassigned using the standard C function strcpy.
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )

Pointers swap values in void function, but won't return swapped values

I'm trying to swap two strings passed in as char pointers.
In debugging, I get the right answers at the end of the called function, but returning the values after the function ends returns the same values as passed in. Here is the code
#include <stdio.h>
int main(int argc, char const *argv[]) {
char *s1, *s2;
s1 = "12345678";
s2 = "87654321";
printf("s1 is %s\n", s1);
printf("s2 is %s\n", s2);
strswap(s1, s2);
printf("s1 is now %s\n", s1);
printf("s2 is now %s\n", s2);
}
and the code for the function itself
#include <stdio.h>
void strswap(char *s1, char *s2){
char *temp;
temp = s1;
printf("temp: %s\n", temp);
s1 = s2;
printf("s1: %s\n", s1);
s2 = temp;
printf("s1: %s\n", s1);
printf("s2: %s\n", s2);
printf("temp: %s\n", temp);
}
I order to swap strings, first of all you can't just use constant string literals since they are immutable. Assigning string literal to char * is considered bad practice unless you properly know what you're trying to achieve. Read this link and this also. You should use statically/dynamically allocated strings.
As other people said, you're passing the character pointers by value, so any changes you make in strswap() would not be reflected in main function. Since some local variables are modified and they get destroyed when control goes out of those functions. You should either pass char ** like in one of the mentioned answers. I would recommend to use statically allocated strings and use strcpy for string copy operations like this:
#include <stdio.h>
#include <string.h>
#define MAX_SIZE 1000
void strswap(char *s1, char *s2){
char tempStr[MAX_SIZE];
strcpy(tempStr, s1);
strcpy(s1, s2);
strcpy(s2, tempStr);
}
int main(int argc, char const *argv[]) {
char aString1[MAX_SIZE] = "Rohan", aString2[MAX_SIZE] = "Rohit";
printf("s1 is %s\n", aString1);
printf("s2 is %s\n", aString2);
strswap(aString1, aString2);
printf("s1 is now %s\n", aString1);
printf("s2 is now %s\n", aString2);
return 0;
}
C uses pass-by-value for function argument passing.
Here, the pointers themselves are passed by value, so any changes made to the pointers (for example, assigning values to them), will not be reflected to the actual arguments in the caller. However, if any change is made to the value stored at the memory location pointed to by the pointers, that would be reflected to the actual arguments used to call the function from the caller.
So, to change a pointer value itself, you need to pass a pointer to the pointer.
You're using string literals to initialize the pointers, you can't swap those strings with the function prototype you showed.
Assuming the string initialization is a mistake, we can do the swap without changing the function's prototype, by copying the actual characters around. This requires that the strings have equal length, otherwise the longer one can't be copied to the space used by the shorter one.
Here's an attempt:
void swap_strings(char *a, char *b)
{
const size_t al = strlen(a);
const size_t bl = strlen(b);
if(al != bl)
return;
for(size_t i = 0; i < al; ++i)
{
const char t = a[i];
a[i] = b[i];
b[i] = t;
}
}
I changed the function's name, I have a vague recollection that you're not supposed to add functions with names beginning with str, that's reserved.
Note: this requires that the strings be writable, so you can't use it on string literals. You have to have proper buffers (or arrays) like this:
char a[] = "foo";
char b[] = "bar";
swap_strings(a, b);
printf("'%s' and '%s'\n", a, b);
This will print 'bar' and 'foo'.

Resources