I have tried so many ways of doing this and I cannot get it to work. My setup says to use char[] but everything I've researched has no information on using that. Here is my code below
#include <stdio.h>
#include <string.h>
char[] makeString(char character,int count)
{
char finalString[count];
strcpy(finalString,character);
for(int i=1;i<=count;i++)
{
strcat(finalString,character);
}
return finalString;
}
int main() {
printf("%s\n",makeString("*",5)); }
I'm trying to create a function that returns a string of the given character count amount of times. Any help is greatly appreciated.
My apologies if this is a very simple error, I mostly code in python so C is very new to me.
There are a couple of issues, mainly on char finalString[count];
finalString is a variable created within the function, it is called a local variable. It would be destroyed after the function returns.
count as the value of the count variable is dynamically changed. Its value could not be determined during the compile stage, thus the compiler could not allocate memory space for this array. The compiling would fail.
To fix this issue.
either create this variable outside and pass it into the function. Or create the variable on the HEAP space. As the Heap space are shared across the entire program and it would not be affected by function ending.
either using a constant number or dynamically allocating a chunk of memory with malloc, calloc and etc.
Here is one demo with the full code:
// main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* makeString(char character,int count) {
char* finalString = malloc(count+1); //dynamic allocate a chunk of space. +1 for mimic string end with an extra termination sign 0.
for(int i=0; i<count; i++) {
finalString[i] = character;
}
finalString[count] = 0; // string end signal 0
return finalString; // the memory finalString pointed to is in the HEAP space.
}
int main() {
char * p = makeString('*',5);
printf("%s\n",p);
free(p); // free up the HEAP space
return 0;
}
To compile and run the code.
gcc -Wall main.c
./a.out
The output
*****
Arrays are not a first-class type in C -- there are a lot of things you can do with other types that you can't do with arrays. In particular you cannot pass an array as a parameter to a function or return one as the return value.
Because of this restriction, if you ever declare a function with an array type for a parameter or return type, the compiler will (silently) change it into a pointer, and you'll actually be passing or returning a pointer. That is what is happening here -- the return type gets changed to char *, and you return a pointer to your local array that is going out of scope, so the pointer you end up with is dangling.
Your code doesn't compile. If you want to return an array you do char * not char []. Local variables like finalString are out of scope after the function returns.
Here are 3 ways of doing it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *initString(char *a, char c, int n) {
memset(a, c, n);
a[n] = '\0';
return a;
}
char *makeString(char c, int n) {
char *a = malloc(n + 1);
memset(a, c, n);
a[n] = '\0';
return a;
}
int main(void) {
printf("%s\n", memset((char [6]) { 0 }, '*', 5));
char s[6];
initString(s, '*', (sizeof s / sizeof *s) - 1);
printf("%s\n", s);
char *s2 = makeString('*', 5);
printf("%s\n", s2);
free(s2);
}
Related
I am struggling to write a char* passed as an argument. I want to write some string to char* from the function write_char(). With the below code, I am getting a segmentation fault.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
int main(){
char* test_char;
write_char(test_char);
printf("%s", test_char);
return 0;
}
You have two problems (related to what you try to do, there are other problems as well):
Arguments in C are passed by value, which means that the argument variable (c in your write_char function) is a copy of the value from test_char in the main function. Modifying this copy (like assigning to it) will only change the local variables value and not the original variables value.
Assigning to a variable a second time overwrites the current value in the variable. If you do e.g.
int a;
a = 5;
a = 10;
you would (hopefully) not wonder why the value of a was changed to 10 in the second assignment. That a variable is a pointer doesn't change that semantic.
Now how to solve your problem... The first problem could be easily solved by making the function return a pointer instead. And the second problem could be solved by copying the string into the memory instead of reassigning the pointer.
So my suggestion is that you write the function something like
char *get_string(void)
{
char *ptr = malloc(strlen("some string") + 1); // Allocate memory, +1 for terminator
strcpy(ptr, "some string"); // Copy some data into the allocated memory
return ptr; // Return the pointer
}
This could then be used as
char *test_string = get_string();
printf("My string is %s\n", test_string);
free(test_string); // Remember to free the memory we have allocated
Within the function
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
the parameter c is a local variable of the function. Changing it within the function does not influence on the original argument because it is passed by value. That is the function deals with a copy of the original argument.
You have to pass the argument by reference through pointer to it.
Also the function has a memory leak because at first the pointer was assigned with the address of the allocated memory and then reassigned with the address of the first character of the string literal "some string".
If you want to create a copy of a string literal then what you need is the following
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char( char **s )
{
const char *literal = "some string";
*s = malloc( strlen( literal ) + 1 );
if ( *s ) strcpy( *s, literal );
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
if ( test_char ) puts( test_char );
free( test_char );
}
The program output is
some string
Do not forget to allocate dynamically a character array that is large enough to store also the terminating zero of the string literal.
And you should free the allocated memory when the allocated array is not needed any more.
If you want just to initialize a pointer with the address of a string literal then there is no need to allocate dynamically memory.
You can write
#include <stdio.h>
void write_char( char **s )
{
*s = "some string";
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
puts( test_char );
}
In C, you'll need to pass a pointer to a pointer. Your malloc call is trying to change the value of the variable that's being passed in, but it's actually only a copy. The real variable you pass in will not be changed.
Also, the way that you copy a string into a char* is not using assignment... Here's some revised code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void write_char(char** c){
size_t len = strlen("some string");
*c = (char*)malloc(len + 1); // + 1 for null termination
strncpy(*c, "some string", len);
}
int main(){
char* test_char;
write_char(&test_char);
printf("%s", test_char);
return 0;
}
String assignment in C is very different from most modern languages. If you declare a char * and assign a string in the same statement, e.g.,
char *c = "some string";
that works fine, as the compiler can decide how much memory to allocate for that string. After that, though, you mostly shouldn't change the value of the string with =, as this use is mostly for a constant string. If you want to make that especially clear, declare it with const. You'll need to use strcpy. Even then, you'll want to stay away from declaring most strings with a set string, like I have above, if you're planning on changing it. Here is an example of this:
char *c;
c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
If you're passing a pointer to a function that will reallocate it, or even malloc in the first place, you'll need a pointer to a pointer, otherwise the string in main will not get changed.
void myfunc(char **c) {
char *tmp = realloc(*c, 32 * sizeof(char));
if(tmp != NULL) {
*c = tmp;
}
}
char *c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
myfunc(&c);
char* test_char="string"; // initialize string at the time of declaration
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
}
int main(){
char* test_char="strin";
write_char(test_char);
printf("%s", test_char);
return 0;
}
I am doing a bit of studying about C pointers and how to transfer them to functions, so I made this program
#include <stdio.h>
char* my_copy(pnt);
void main()
{
int i;
char a[30];
char* p,*pnt;
printf("Please enter a string\n");
gets(a);
pnt = a;
p = my_copy(pnt);
for (i = 0; i < 2; i++)
printf("%c", p[i]);
}
char* my_copy(char* pnt)
{
char b[3];
char* g;
g = pnt;
b[0] = *pnt;
for (; *pnt != 0; pnt++);
pnt--;
b[1] = *pnt;
b[2] = NULL;
return b;
}
It's supposed to take a string using only pointers and send a pointer of the string to the function my_copy and return a pointer to a new string which contains the first and the last letter of the new string. Now the problem is that the p value does receive the 2 letters but I can't seem to print them. Does anyone have an idea why?
I see five issues with your code:
char* my_copy(pnt); is wrong. A function prototype specifies the types of the parameters, not their names. It should be char *my_copy(char *).
void main() is wrong. main should return int (and a parameterless function is specified as (void) in C): int main(void).
gets(a); is wrong. Any use of gets is a bug (buffer overflow) and gets itself has been removed from the standard library. Use fgets instead.
b[2] = NULL; is a type error. NULL is a pointer, but b[2] is a char. You want b[2] = '\0'; instead.
my_copy returns the address of a local variable (b). By the time the function returns, the variable is gone and the pointer is invalid. To fix this, you can have the caller specify another pointer (which tells my_copy where to store the result, like strcpy or fgets). You can also make the function return dynamically allocated memory, which the caller then has to free after it is done using it (like fopen / fclose).
You're returning an array from my_copy that you declared within the function. This was allocated on the stack and so is invalid when the function returns.
You need to allocate the new string on the heap:
#include <stdlib.h>
b = malloc(3);
if (b) {
/* Do your funny copy here */
}
Don't forget to free() the returned string when you've finished with it.
I'm trying to concat two strings, supposing the "dest" string hasn't enough space to add another one, so I'm using dynamic arrays to solve it.
The problem is a mremap_chunk error when trying to compile the code.
I don't know what I'm missing since the realloc call has all the right params place in.
Error:
malloc.c:2869: mremap_chunk: Assertion `((size + offset) & (GLRO (dl_pagesize) - 1)) == 0' failed.
Aborted (core dumped)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strcatt(char *s1, char *s2)
{
int a = strlen(s1);
int b = strlen(s2);
int i, size_ab = a+b;
s1 = (char *) realloc (s1, size_ab*sizeof(char));
for(i=0; i<b; i++) {
s1[i+a]=s2[i];
}
s1[size_ab]='\0';
return s1;
}
int main()
{
char s1[]="12345";
char s2[]="qwerty";
strcatt(s1,s2);
printf("%s\n", s1);
return 0;
}
First, you are treating non-heap memory as heap memory, don't do that.
Second you're not including space for the terminator in the calculation.
Here are some more points:
Don't name functions starting with str, that's a reserved name space.
Buffer sizes should be size_t, not int.
Don't cast the return value of malloc() in C.
Use memcpy() to copy blocks of memory when you know the size.
The "right hand side" strings should be const.
Deal with the possibility of allocation error.
I consider it bad practice to scale by sizeof (char), that's always 1.
Here's how I would write it, assuming the same logic:
char * my_strcatt(char *s1, const char *s2)
{
const size_t a = strlen(s1);
const size_t b = strlen(s2);
const size_t size_ab = a + b + 1;
s1 = realloc(s1, size_ab);
memcpy(s1 + a, s2, b + 1);
return s1;
}
You can not realloc or free a memory that is not allocated with a call to malloc or is not NULL.
From section 7.22.3.5. The realloc function in C11 draft
The realloc function deallocates the old object pointed to by ptr and
returns a pointer to a new object that has the size specified by size.
The contents of the new object shall be the same as that of the old
object prior to deallocation, up to the lesser of the new and old
sizes. Any bytes in the new object beyond the size of the old object
have indeterminate values.
So, s1 = (char *) realloc (s1, size_ab*sizeof(char)); is plainly wrong for your inputs (automatic arrays), never do that.
And then there are many more problems which can be fixed with some help from a debugger.
The clang debugger gives a very clear error description:
malloc: error for object 0x7fff6fbb16d6: pointer being realloc'd was not allocated
set a breakpoint in malloc_error_break to debug
Both of your arrays are initialized as string literals. Further on, your function tries to modify a string literal by reallocing it, which is wrong by C standard because you can't reallocate what you haven't allocated, and then copying the members of the second string literal to the "object" you intended to modify by misusing realloc() on a string literal.
The code would work if you had dynamically defined a third string in which you would have summed the contents of both:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *mystrcatt(char *s1, char *s2)
{
int a = strlen(s1);
int b = strlen(s2);
int i, size_ab = a+b;
char *s3 = malloc (size_ab*sizeof(char)); //sizeof(char) is always 1
for(i=0; i<a; i++) { //inefficient
(s3[i])=s1[i];
}
for(i=0; i<b; i++) { //inefficient
(s3[i+a])=s2[i];
}
s3[size_ab]='\0';
return s3;
}
int main()
{
char s1[]="12345";
char s2[]="qwerty";
char *s3 = mystrcatt(s1,s2);
printf("%s\n", s3);
free(s3);
return 0;
}
Please, also note that you don't cast the return of malloc() in C.
This question already has answers here:
pass strings by reference in C
(8 answers)
Closed 7 years ago.
I'm trying to Initialize a string in Initialize then pass it to int main() for screen output, but it seems that the strings that are initialized have become corrupted.
Headers
#include<stdio.h>
#include<stdlib.h>
Initialize
void
Initialize(char* STRINGs)
{
STRINGs = malloc(sizeof(char)*5);
STRINGs = "hello" ;
printf("1: %s\n",STRING);
}
Main
int
main (char* STRINGs)
{
Initialize(STRINGs);
//The program stops working when it reaches this section
printf("2: %s",STRINGs);
return 0;
}
You can use this code to initialize the string variable
char * Initialize()
{
char* STRINGs="HELLO";
printf("1: %s\n",STRINGs);
return STRINGs;
}
int main ()
{
char *strings =Initialize();
//The program stops working when it reaches this section
printf("2: %s",strings);
return 0;
}
First, you have wrong prototype for int main (char* STRINGs), which must be either:
int main(), or
int main( int argc, char *argv[] )
How do I pass a string array from a function to main
As it stands, you can create a string inside your Initialize() then return a pointer to that string.
There are several issues in your Initialize() though.
Here's a suggestion to change:
char *
Initialize()
{
char *STRINGs = malloc(strlen("hello") + 1); // <-- malloc must include an additional space for the NULL terminator.
strcpy( STRINGs, "hello" ); // <-- NEVER use assignment for string type.
printf("1: %s\n",STRINGs);
return STRINGs;
}
Then your main() can be like this:
int main()
{
char *str = Initialize();
printf( "str = %s\n", str );
return 0;
}
NOTE: do not forget to add #include <string.h>
Here's an answer. First, when allocating memory for any variable, it must be freed or you'll get some nasty system errors at some point or at the very least, a memory leak.
In the int main(), the declaration should ideally be int main(int argc, char* argv[]).
I also recommend allocating at least one more byte of memory just in case you create a string and a function you use later on requires a null character appended to it.
I fixed your code to make it work at its bare minimum.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* Initialize(){
char* string = malloc(sizeof(char)*6);
strcpy(string,"hello");
printf("1: %s\n",string);
return string;
}
int main (int argc, char* argv[]){
char *strings=Initialize();
printf("2: %s\n",strings);
free(strings);
return 0;
}
For a shorter version of your code, I suggest this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[]){
char* strings=malloc(6);
strcpy(string,"hello");
printf("2: %s\n",strings);
free(strings);
return 0;
}
For the sake of understanding, let us suppose STRINGs of main function is a.
And STRINGs of initialize function is b.
At first, in main a is pointing to some unknown location say u. When you pass this to the initialize function then b also starts pointing to the location u.
But, after the allocation of memory, b starts pointing to some other memory that was allocated by malloc say m.
Now you change the contents of memory m by use of b. But a is still pointing to the unknown location u.
So both the pointers are now pointing towards two different memory locations. So when you print contents where b is pointing it works perfectly and then you printf contents of a which has no specific location or may be null.
So, because of this your problem came.
And also, there is another error in your program that is in the printf of initialize function, it has given a parameter STRING which is undeclared....make it STRINGs.
Hope you will like the explanation. Its a little bit tricky.
Thanks :-)
You can use:
void Initialize(char** STRING)
Instead:
void Initialize(char* STRINGs)
because you want to change the the address to which STRING points
Also you have wrong prototype of main
Try:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Initialize(char** STRING)
{
*STRING = malloc(6);
strcpy(*STRING, "hello");
printf("1: %s\n",*STRING);
}
int main (int argc, char *argv[])
{
char* STRING;
Initialize(&STRING);
printf("2: %s\n",STRING);
free(STRING);
return 0;
}
I'm learning the concept of prototyping in C, however I'm struggling with the correct syntax. I'm writing a function to strip all non-alphbetic characters from a c-string
#include <stdio.h>
#include <string.h>
char[30] clean(char[30] );
int main()
{
char word[30] = "hello";
char cleanWord[30];
cleanWord = clean(word);
return 0;
}
char[30] clean(char word[30])
{
char cleanWord[30];
int i;
for(i=0;i<strlen(word);i++)
if ( isalpha(word[i]) )
cleanWord[i]=word[i];
cleanWord[i]='\0';
return cleanWord;
}
How do I correctly prototype the function? What are the other syntax errors that are preventing my program from compiling?
Your problem is not with function prototyping (aka forward declaration). You just can't return an array from a function in C. Nor can you assign to an array variable. You need to make a couple of changes to get things working. One option:
change char cleanWord[30] in main to be char * cleanWord.
change the signature of clean to char *clean(char word[30])
use malloc to allocate a destnation buffer inside clean
return a pointer to that new buffer
free the buffer in main
And another:
change the signature of clean to void clean(char word[30], char cleanWord[30])
operate on the passed-in pointer rather than a local array in clean
change the call in main to be clean(word, cleanWord).
As Carl Norum said, you can't return an array. Instead, what you tend to do is supply the output:
void clean( const char word[30], char cleanWord[30] )
{
}
And you should remove the locally-scoped array from that function.
You will find that the function does not work correctly, because you only have one iterator i. That means if a character is not an alpha, you will skip over a position in the output array. You will need a second iterator that is incremented only when you add a character to cleanWord.
A couple of notes (was a bit late with writing up an answer, seems I've been beaten to them by the others )
C cannot return local (stack) objects, if you want to return an array from a function you have to malloc it
Even if you declare an array argument as (char arr[30]), (char* arr) is just as valid as arrays decay to pointers when passed as arguments to functions. Also, you won't be able to get the size correctly of such arrays by using sizeof. Even though it's 30, on my machine it returns 4 for word in clean, which is the size of the pointer for it.
You are missing an include, isalpha is part of ctype.h
I've updated your code, hopefully I've guessed your intentions correctly:
#include <stdlib.h> /* for malloc and free */
#include <string.h> /* for strlen */
#include <ctype.h> /* for isalpha */
#include <stdio.h> /* for printf */
/* Function declaration */
char* clean(char word[30]);
/* your 'main()' would now look like this: */
int main()
{
char word[30] = "hel1lo1";
char* cleanWord;
cleanWord = clean(word);
printf("%s\n", cleanWord);
free(cleanWord);
return 0;
}
/* Function definition */
char* clean(char word[30])
{
char* cleanWord = malloc(30); /* allocating dynamically an array of 30 chars,
* no need to use sizeof here as char is
* guaranteed to be 1 by the standard
*/
unsigned int i, j = 0; /* let's fix the problem with non-alpha chars already pointed out */
for (i = 0; i < (strlen(word)); i++)
if (isalpha(word[i]))
cleanWord[j++] = word[i];
cleanWord[j] = '\0';
return cleanWord;
/* return a pointer to the malloc`ed array, don't forget to free it after you're done with it */
}