Returning a string from function - c

I'm trying to make a substring function on c. It must be return "cdef", but it returns nothing. How can i fix it? Thanks.
#include<stdio.h>
#include<conio.h>
#include<string.h>
char* substring( char *, int, int );
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));
getch();
return 0;
}
char* substring(char *text, int a, int b){
char nText[b-a];
char tmp[2];
strcpy(nText, "");
for(int i=a; i<b; i++){
tmp[0] = text[i];
tmp[1] = '\0';
strcat(nText, tmp);
}
return nText;
}

You are making the mistake of returning a pointer to a variable that may not exist after the function returns. You need to allocate the space in the calling function and just put the result in the space provided, or create permanent space in the function with static. Note - as pointed out by Jonathan Leffler - since the space is "permanent", you can't change the length of the block from one call to the next, and you would have to pick a "sensible" value and test that b-a+1 is not longer than the space allocated. Thus my second method is more robust.
char* substring(char *text, int a, int b){
static char nText[100];
if ((b-a+1)>100) // do something! you can't copy this!
// code
return nText;
}
As Employed Russian pointed out, using a static in this way is in any case quite dangerous since another piece of code might call this function while you're still using the result of the first call. This is NOT ADVISABLE if you do any kind of multi threading, but it's a quick fix if you have a single thread.
A better formulation is
void substring(char *text, int a, int b, char *nText) {
// code, nothing to return
}
In the latter case, you create space in the calling function and pass the pointer to substring. n your main program you would have
char shortString[100];
substring(stuff, 4, 6, shortString);
printf("%s\n", shortString);
As an aside, your method for copying the substring is terribly inefficient. Consider replacing it with
for(int i=a; i<b;i++) nText[i-a]=text[i];
nText[b-a] = '\0';
From this you can see that you actually need to allocate nText[b-a+1] elements, otherwise there is no space for the final '\0'.

Your bug is here:
char* substring(char *text, int a, int b){
char nText[b-a];
...
return nText;
}
The buffer you return becomes invalid as soon as you return from the function.
GCC nicely warns you about this:
t.c:24:5: warning: function returns address of local variable [enabled by default]
How can i fix it?
You have to allocate a new buffer (and the caller will have to free it), or have the caller provide output buffer (as Floris suggested).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* substring( char *, int, int );
char* substringb(char *substr, char *text, int a, int b);
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
char substr[5];
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));//Things to think to be able to release!
printf("%s\n", substringb(substr, stuff, 2, 6));
getch();
return 0;
}
//dynamic allocate
char* substring(char *text, int a, int b){
char *nText;
nText = (char*)malloc((b-a+1)*sizeof(char));
strncpy(nText, &text[a], b-a);
ntext[b-a] = 0;
return nText;
}
//copy to reserve area
char* substringb(char *substr, char *text, int a, int b){
substr[b-a]=0;
return strncpy(substr, &text[a], b-a);
}

Related

Use realloc() after malloc() to change the size of unsigned char array

In the main function, I use malloc() to create an unsigned char array:
int main()
{
int length = 64;
unsigned char *array = (unsigned char *)malloc(length * sizeof(unsigned char));
...
change_size(array, length);
}
change_size() defined in .h:
void change_size(unsigned char* arr, int len);
In the change_size function, I will use realloc() to increase the array size:
void change size(unsigned char* arr, int len)
{
printf("%d\n", len);
len = len + 16;
printf("%d\n", len);
arr = (unsigned char *)realloc(arr, len * sizeof(unsigned char));
int new_len = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", new_len);
}
The printf() show me:
64
80
8
The array size in the main() also needs to be updated.
Then how to change this array size correctly?
You need to pass your parameters as pointers if you want to change their value back in the caller. That also means you pass your array pointer as a pointer, because realloc might change it:
int change_size(unsigned char **arr, int *len)
{
int new_len = *len + 16;
unsigned char *new_arr = realloc(*arr, new_len);
if (new_arr) {
*len = new_len;
*arr = new_arr;
}
return new_arr != NULL;
}
Here I've modified change_size to suit, and also added a return value to indicate success, since realloc can fail to resize the memory. For clarity, I removed the printf calls. Oh, and I also removed the cast, since that is not valid in C.
Example usage:
if (!change_size(&array, &len))
{
perror("change_size failed");
}
One final note is that you can use your change_size function for the first allocation too, rather than calling malloc. If the first argument to realloc is NULL, it does the same thing as malloc.
First C is not babysitter language,
You only need basic things then you can do everything,
Just try hard to totally understand basic.
#include <stdio.h>
#include <stdlib.h>
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
free(G1);
return 0;
}
Okay I answer it. #Chipster
#include <stdio.h>
#include <stdlib.h>
int change_size(char** arr, int len)
{
char* nar=(char*)malloc(sizeof(char)*(len+16));
if(nar){
free(* arr);
*arr=nar;
nar[10]='K';//this will let you know its right
return len+16;
}
return len;
}
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
printf("%d\n",G1);
G1_Len=change_size(&G1,G1_Len);
printf("%c\n",G1[10]);
printf("%d\n",G1);
printf("%d\n",G1_Len);
free(G1);
return 0;
}

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);
}

How to declare array size with a parameter in c

Im writing a function in c and here is my code:
char* makeMoves(char oldBoard[], int moveType, int empties, char player){
int oldBoardLength;
oldBoardLength = sizeof(oldBoard) / sizeof(oldBoard[0]);
char result[oldBoardLength];
copyBoard(oldBoard, result);
}
I think that this line has a problem:
char result[oldBoardLength];
how can i create this array with length=oldBoardLength?
In java is something like this:
char[] result = new char[oldBoard.length];
but in c i don;t know how to create this. Can anyone help me?
In C, you have to allocate dynamic storage in such cases.
char *result = malloc(oldBoardLength);
copyBoard(oldBoard, result);
free(result);
However, you have to pass oldBoardLength into the function, because an argument like arr[] or arr[8] will always decay to a pointer. Taking sizeof on a pointer is not what you have intended. Have a look at the output of this example:
#include <stdio.h>
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
long int test(char array[16]) {
return COUNT_OF(array);
}
void main(void) {
char a[16];
printf("%ld\n", COUNT_OF(a)); // prints 16
printf("%ld\n", test(a)); // prints 8 or 4 for 64bit or 32bit systems
}
First I would use char *oldBoard instead of char oldBoard[] There the same but I think char *oldBoard is clearer. Second you don't wan't to use sizeof as that will not return the correct length, you would just get the size of a pointer. sizeof(oldBoard) / sizeof(oldBoard[0]); only works on statically allocated arrays or at least that is what this says How do I find the length/number of items present for an array? . Use a another variable to keep track of the array length. Finally use dynamic allocation aka malloc() so that the values don't become garbage when you pass them between functions. I'm not quite sure what you are trying to do but here is a example of what I think your trying to do.
char *makeMoves(char *oldBoard, int len, int moveType, int empties, char player)
{
char *result;
result = malloc(len);
if(result == NULL)
{
return NULL;
}
copyBoard(oldBoard, result);
return result;
}
int main(void)
{
char *board, *result;
int len = 10;
int moveType, empties;
char player;
board = malloc(len);
if(board == NULL)
{
return -1;
}
result = makeMoves(board, len, moveType, empties, player);
if(result == NULL)
{
return -1;
}
free(board);
free(result);
return 0;
}
In C, the most often used idiom is passing the expected number of elements your pointer parameter points to as a separate parameter. Should be something like this:
char* makeMoves(char *oldBoard, int oldBoardLength, int moveType, int empties, char player) {
/* ... */
}
This way, the caller of your function is repsonsible for passing in the correct length.

simple strcat implementation with pointers

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.

c pointers in string array

I'm trying to copy a char array into another char array using pointer arithmetic. It seems to be correct within the copy() but then I don't understand what happens after it gets to main. char a[] does not get the value of char b[] even if I called the function. Am I missing something? Hehehe
#include <stdio.h>
void copy(char a[], char b[]){
int *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}
That's really not very meaningful C. I suspect it didn't even compile without warnings?
First you take the address of array a, then you take the address of array b, convert it to an integer (without a cast!), and then write that integer into the array a. Then, at the end of main, you try to print the char array as an integer.
Pointer arithmetic doesn't quite work like that. :)
I think you really mean to do something like this:
void copy(char a[], char b[]){
char *ptr_a = a;
char *ptr_b = b;
while (*ptr_b != '\0') {
*ptr_a = *ptr_b;
ptr_a++;
ptr_b++;
}
*ptr_a = '\0';
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%s\n", a);
}
Of course, the proper way to do it is like this:
#include <string.h>
int main(void){
char a[100];
char b[] = "bluhbluh";
strncpy(a, b, 100);
printf("%s\n", a);
}
As ams points out in his/her answer, if you want a copy of the array, you need to duplicate each entry. Assuming you don't want to duplicate the array, but instead want a to point at b:
apoint doesn't do anything - it can't change the pointers of a or b. If you wanted to modify the address that a or b pointed to, you'd have to pass the address of them to your function. This won't work, however, as arrays are not pointers - it's why you can't reassign arrays in C. You can modify pointers though - the following is an example of modifying a pointer to a to point at b:
#include <stdio.h>
void redirect(char** a, char* b){
*a = b;
}
int main(void){
char a[100];
char b[] = "bluhbluh";
char* apt = a;
redirect(&apt,b);
printf("a=%s, b=%s", apt,b);
}
apoint should be a char*, don't you have a warning about this pointer assignment?
Moreover you're not iterating on all chars of the string...
Maybe the line int *apoint = &a is wrong, &a is pointer to pointer to char, while apoint is int *. Don't you have compile errors?
You have some major errors in your code specially this line is incorrect int *apoint = &a; it should be char* *apoint = &a;
//Corrected Code:
#include <stdio.h>
void copy(char a[], char b[]){
char* *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}
This will solve the major code issues though I don’t think your copy function would still give your desire results as approach doesn’t seem very right.
Method of copying the char is not good if you enable -Wall or -Werror in gcc you will see so many errors.
The thing you want, which is possible just by copying the pointers in main no need to call copy (a,b);
char *a;
char b[]="bluhbluh"
a=b;
now a started pointing to string "bluhbluh"
But I think that you dont want you want each and every character of array b to be copied into array a
you will have to do like this
void copy(char *a,char *b)
{
while(*b!='\0')
*a++=*b++;
}
int main()
{
char a[100];
char b[]="bluhbluh";
copy(a,b);
printf("%s\n",a);
}

Resources