pass char to function - c

i need to write a function that randomize length of string, allocate dynamic memory for it and than randomize small letters inside it.
the main program should print 15 words from the function.
the function by itself works for me, i just can't pass it from the main program.
my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 15
char randWord() {
int len;
srand(time(NULL));
len = (rand() % 10) + 1;
char * word = malloc(len);
for (int i = 0; i < len; i++) {
word[i] = ((rand() % 26) + 97);
}
return word;
}
int main() {
char* s;
int i;
for (i = 0; i < N; i++) {
randWord(s);
printf("%s\n", s);
free(s);
}
return 0;
}

You need to modify your function to accept parameters, and potentially return a char pointer.
char* randWord(char* s)
I think you might have a misunderstanding of functions in general. They can optionally take in parameters, and optionally return something.
A really simple example would be something like this:
int addOne(int x) {
return x + 1;
}
It may help to think of programming functions in terms of math functions. the above is equivalent to f(x)=x+1. So f(1) "returns" 2, f(2) is 3 and so on.

The function is declared without parameters
char randWord() {
but you are passing a pointer of the type char *.
randWord(s)
The function returns a pointer of the type char * but its return type is char.
char randWord() {
int len;
srand(time(NULL));
len = (rand() % 10) + 1;
char * word = malloc(len);
for (int i = 0; i < len; i++) {
word[i] = ((rand() % 26) + 97);
}
return word;
}
Also the function does not build a string because the dynamically allocated character array does not contain the terminating zero character '\0'.
And it is a bad style of programming to use magic numbers like 97.
Redefine the function at least like
char * randWord( void ) {
size_t len = (rand() % 10) + 1;
char * word = malloc(len);
if ( word != NULL )
{
size_t i = 0;
for (; i < len - 1; i++) {
word[i] = ((rand() % 26) + 'a');
}
word[i] = '\0';
}
return word;
}
and in main write
s = randWord();
if ( s != NULL ) puts( s );
free( s );
This statement
srand(time(NULL));
should be moved from the function to main before its for loop.

Here is your code annotated and altered to function correctly.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 15
char *randWord() { // Return ptr to word buffer (the string)
int len = rand() % 10 + 1; // knowing operator precedence avoids overuse of ( )
char *word = malloc( len + 1 ); // allow room for '\0'
if( word == NULL )
exit( EXIT_FAILURE ); // do not presume success
// Here "len" is the # of chars to generate (at least one)
for( int i = 0; i < len; i++ ) {
word[i] = rand() % 26 + 'a'; // use ASCII value, not magic number
}
word[i] = '\0'; // TERMINATE the string
return word;
}
int main() { // be consistent with braces
srand( time( NULL ) ); // Seed the random number generator only once
for( int i = 0; i < N; i++ ) { // Be consistent
char *s = randWord(); // declare variables proximate to use. Strive for clarity
puts( s ); // Simpler function than printf
free( s );
}
return 0;
}
It is a subtlety of your code that the returned string will always be at least one character long.

Related

String allocated with malloc is only returning the first character

I'm writing a function to rearrange a string's characters. I allocated the new string with malloc and initialize it, and then return it. But when I return it, it always only returns the first character.
I've tried printing the characters of the new string one by one and they print out correctly, but when I call the function, only the first character is returned. I can't figure out why. Any help would be appreciated!
Here's my code:
char * solution(char * s) {
int len = strlen(s);
int i;
int index = 0;
char *ans = (char *) malloc(sizeof(char) * (len + 1));
if (ans == NULL) {
fprintf(stderr, "Ran out of space in some function \n");
exit(1);
}
//char* ans = (char *) malloc(len + 1);
ans[len] = '\0';
for(i = 0; i < len/2; i++){
ans[index++] = s[i];
ans[index++] = s[len - i];
}
if(len % 2 == 1){
ans[index] = s[len/2];
}
return ans;
}
In the first iteration of this for loop
for(i = 0; i < len/2; i++){
ans[index++] = s[i];
ans[index++] = s[len - i];
}
the character ans[1] is set to s[len] (i is equal to 0 in the first iteration of the loop) that is to '\0'.
As a result you will get a string that contains only one character.
What you do is what you get.:)
It seems you mean
ans[index++] = s[len - i - 1];
Pay attention to that as the source string is not changed within the function then the function should be declared like
char * solution( const char * s );
The original declaration
char * solution(char * s);
means that the string will be changed in place.
If you want to change a string in place then the function can look the following way as shown in the demonstration program below.
#include <string.h>
#include <stdio.h>
char * solution( char *s )
{
size_t n = strlen( s );
for (size_t i = 1; i < n; i += 2)
{
char c = s[n - 1];
memmove( s + i + 1, s + i, n - i - 1);
s[i] = c;
}
return s;
}
int main( void )
{
char s[] = "0123456789";
puts( s );
puts( solution( s ) );
}
The program output is
0123456789
0918273645

adding zeros before string

zfill algorithm is supposed to work as follows:
zfill function accepts two parameters, a string and a number,
if string length is >= the number, then it doesn't have to add anything, and it returns a copy to the string,
else, malloc enough space and add zeros before the string.
I'm trying to understand why is this solution not correct, it has two warnings:
1st warning:
for (i; i < zeros; i++) {
s[i] = "0";
}
"=": char differs in level of indirection from char[2]
2nd warning:
for (i; i < n; i++) {
s[i] = str[i];
}
buffer overrun while writing to s
char* zfill(const char* str, size_t n) {
if (str == NULL) {
return NULL;
}
char* s;
size_t length = strlen(str);
if (length >= n) {
//it doesn't have to add anything, just malloc and copy the string
size_t sum = length + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
for (size_t i = 0; i < length; i++) {
s[i] = str[i];
}
s[sum] = 0;
}
else {
// add zeros before strings
size_t zeros = n - length;
size_t sum = n + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
size_t i = 0;
for (i; i < zeros; i++) {
s[i] = "0";
}
for (i; i < n; i++) {
s[i] = str[i];
}
s[sum] = 0;
}
return s;
}
int main(void) {
char str[] = "hello, world!";
size_t n = 40;
char* s = zfill(str, n);
free(s);
return 0;
}
EDIT: I've solved the problem this way:
char* zfill(const char* str, size_t n) {
if (str == NULL) {
return NULL;
}
char* s;
size_t length = strlen(str);
if (length >= n) {
//it doesn't have to add anything, just malloc and copy the string
size_t sum = length + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
for (size_t i = 0; i < length; i++) {
s[i] = str[i];
}
s[sum-1] = 0;
}
else {
// add zeros before strings
size_t zeros = n - length;
size_t sum = n + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
size_t i = 0;
for (i; i < zeros; i++) {
s[i] = '0';
}
for (size_t j = 0; i < n; j++) {
s[i++] = str[j];
}
s[sum-1] = 0;
}
return s;
}
and it works, but I don't know why I have this warning:
for (i; i < zeros; i++) {}
statement with no effect
but when I've debugged I've noticed that this statement has an effect, because it correctly copies the correct number of zeros. I don't know why I have this warning
SO is a place of learning.
When first dealing with a coding challenge, it's best to take time to work out what's needed before starting to write code.
Below is a working version of zfill() (along with a main() that tests it.)
Read through the comments. The only thing new here is memset().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// A trivial "helper function" determines the max of two values
int max( int a, int b ) { return a > b ? a : b; }
char *zfill( char *str, int minLen ) {
// Determine length of arbitrary string
int len = strlen( str );
// Determine max of length v. minimum desired
int allocSize = max( minLen, len );
// allocate buffer to store resulting string (with '\0')
char *obuf = (char*)malloc( allocSize + 1 );
/* omitting test for failure */
// determine start location at which to copy str
int loc = len <= minLen ? minLen - len : 0;
if( loc > 0 )
// fill buffer with enough 'zeros'
memset( obuf, '0', allocSize ); // ASCII zero!
// copy str to that location in buffer
strcpy( obuf + loc, str );
// return buffer to calling function
return obuf;
}
int main() {
// collection of strings of arbitrary length
char *strs[] = { "abc", "abcdefghijkl", "abcde", "a", "" };
// pass each one to zfill, print, then free the alloc'd buffer.
for( int i = 0; i < sizeof strs/sizeof strs[0]; i++ ) {
char *cp = zfill( strs[i], 10 );
puts( cp );
free( cp );
}
return 0;
}
Output:
0000000abc
abcdefghijkl
00000abcde
000000000a
0000000000
Here's zfill() without the comments:
char *zfill( char *str, int minLen ) {
int len = strlen( str );
int allocSize = max( minLen, len );
char *obuf = (char*)malloc( allocSize + 1 );
/* omitting test for failure */
int loc = len <= minLen ? minLen - len : 0;
if( loc > 0 )
memset( obuf, '0', loc ); // ASCII zero!
strcpy( obuf + loc, str );
return obuf;
}
You don't want to spend your time staring at lines and lines of code.
Fill your quiver with arrows that are (proven!) standard library functions and use them.
I've omitted, too, the test for zfill being passed a NULL pointer.
This code snippet
size_t sum = length + 1u;
s = malloc(sum);
//...
s[sum] = 0;
accesses memory outside the allocated character array because the valid range of indices is [0, sum). You need to write at least like
s[length] = 0;
In this code snippet
for (i; i < zeros; ++) {
s[i] = "0";
}
the expression s[i] represents a single object of the type char while on the right-hand side there is a string literal that as an expression has the type char *. You need to write at least
s[i] = '0';
using the integer character constant instead of the string literal.
In this code snippet
size_t i = 0;
for (i; i < zeros; i++) {
s[i] = "0";
}
for (i; i < n; i++) {
s[i] = str[i];
}
as the length of the string str can be less than n then this for loop
for (i; i < n; i++) {
s[i] = str[i];
}
accesses memory outside the string str.
Pay attention to that your function has redundant code. It can be written simpler.
The function can look for example the following way as shown in the demonstration program below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * zfill( const char *s, size_t n )
{
char *result = NULL;
if ( s != NULL )
{
size_t len = strlen( s );
n = len < n ? n : len;
result = malloc( n + 1 );
if ( result )
{
size_t i = 0;
size_t m = len < n ? n - len : 0;
for ( ; i < m; i++ )
{
result[i] = '0';
}
for ( ; i < n; i++ )
{
result[i] = s[i - m];
}
result[i] = '\0';
}
}
return result;
}
int main( void )
{
const char *s = "Hello";
size_t n = 10;
char *result = zfill( s, n );
if ( result ) puts( result );
free( result );
}
The program output is
00000Hello
Or as #Some programmer dude pointed to in his comment you can use the standard C function snprintf that alone performs the task. For example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * zfill( const char *s, size_t n )
{
char *result = NULL;
if ( s != NULL )
{
size_t len = strlen( s );
n = len < n ? n : len;
result = malloc( n + 1 );
if ( result )
{
int m = len < n ? n - len : 0;
snprintf( result, n + 1, "%.*d%s", m, 0, s );
}
}
return result;
}
int main( void )
{
char *p = zfill( "Hello", 5 );
if ( p ) puts( p );
free( p );
p = zfill( "Hello", 10 );
if ( p ) puts( p );
free( p );
}
The program output is
Hello
00000Hello
so you have 3 major problems in your code :
it's s[i] = '0'; not s[i] = "0";
it's s[i] = str[i - zeros]; not s[i] = str[i]; as the value of the i will be 27 in your test case : so it make sense to say s[27] because its size is about 41 but it doesn't make sense to say str[27] as its size is only about 13 in your test case , so you had to map the value 27 of i to the value 0 to be convenient to use with str
i is deprecated in first part here for (i; i < zeros; i++) , so use for (; i < zeros; i++)instead of for (i; i < zeros; i++) , but it will not cause any problem if you keep it.
and here is the full edited code :
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* zfill(const char* str, size_t n) {
if (str == NULL) {
return NULL;
}
char* s;
size_t length = strlen(str);
if (length >= n) {
//it doesn't have to add anything, just malloc and copy the string
size_t sum = length + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
for (size_t i = 0; i < length; i++) {
s[i] = str[i];
}
s[sum] = 0;
}
else {
// add zeros before strings
size_t zeros = n - length;
size_t sum = n + 1u;
s = malloc(sum);
if (s == NULL) {
return NULL;
}
size_t i = 0;
for (; i < zeros; i++) {
s[i] = '0';
}
for (; i < n; i++) {
s[i] = str[i - zeros];
}
s[sum] = 0;
}
return s;
}
int main(void) {
char str[] = "hello, world!";
size_t n = 40;
char* s = zfill(str, n);
printf("%s\n", s);
free(s);
return 0;
}

Returning a whole array in C

Hi I am pretty new to C and was wondering how to return an entire array. For example I have this function here.
char* foo(int x)
{
char *num = (char*)malloc(x*sizeof(int));
num[0] = '1';
num[1] = '2';
num[2] = '3';
num[3] = '4';
return num;
}
I realized that when I return num it only returns the first index of num. But is there any way to return the whole array, 1234? Any help will be greatly appreciated!
Since the foo() function returns a pointer, you can see that all values are printed when you use the %s format specifier. The display() function prints the data in the memory area pointed to by the pointer as characters.
#include <stdio.h>
#include <stdlib.h>
char* foo(int x)
{
char* num = (char*) malloc((x + 1) * sizeof(char));
for(size_t i = 0 ; i < x ; ++i)
num[i] = i + 1 + '0';
num[x] = '\0';
return num;
}
void display(char *array, size_t size)
{
for(size_t i = 0 ; i < size && array[i] != '\0' ; ++i)
printf("array[%ld]: %c\n", i, array[i]);
}
int main()
{
const size_t size = 4;
char *result = foo(size);
printf("%s\n", result);
display(result, size);
return 0;
}
Output:
1234
array[0]: 1
array[1]: 2
array[2]: 3
array[3]: 4
See if you are new to C, then learn it first do some googling and research. If you don't find anything then read some theory of a similar topic for examples (How to return an array in C?). After that some error is happening in your code then you can ask it on stackoverflow.
By the way your should be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *foo(int x); // fix prototype errors
char *foo(int x)
{
char *num = (char *)calloc(x + 1, sizeof(char)); // we added +1 to append the null terminating character in `num`
for (size_t i = 0; i < x; i++)
num[i] = (char)(i + 48);
return num;
}
/* #returns no. of character written on stdout */
int print_foo(const char *num); // fix prototype errors
int print_foo(const char *num)
{
if (num)
{
size_t z = 0;
for (size_t i = 0; i < num[i] != '\0'; i++)
z += fprintf(stdout, "num[%lu] = %c\n", i, num[i]);
return z;
}
return -1;
}
int main(void)
{
char *num = foo(10);
print_foo((const char *)num);
free(num); // free any heap allocated resources before exiting the application
return 0;
}

Function that convert int to array of char, some questions

This code need to get an int number and convert it to array of char that present the number:
for example :
The number 324
convert to this:
like:
char newstr [6] = {'3','2','4','\0','\0','\0'};
I think that '\0' is null, right?
What is wrong with my code ?
also how can I change this to a function that get an int number and return array of char that present it?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void main ()
{
int value = 324;
char str [6];
char newstr [6];
int pointer, i = 0;
for(i=0; value>0; i++)
{
str[i] = value%10 + '0';
value /=10;
}
str[i] = '\0';
for(i=5; i>-1; i--)
{
if(str[i]!='\0')
{
newstr[pointer] = str[i];
pointer++;
}
}
for (i = 0; i < 6; i++)
{
printf("%d %c\n", i, newstr[i] );
}
printf ("shalom");
}
An easy way should be calling sprintf().
char newstr[6] = {0};
sprintf(newstr, "%d", value);
In your existing code, str looks lile {'4', '2', '3', '\0', SomethingRandom, SomethingRandom}. Reversing it and assign to newstr makes it {SomethingRandom, SomethingRandom, '\0', '3', '2', '4'}, which is definitely not what you want. And indeed you don't assign newstr when str[i] == '\0', which means newstr[2] == SomethingRandom.
Try the following
#include <stdio.h>
#include <stdlib.h>
char * itoa( int x )
{
const unsigned int BASE = 10;
unsigned int u = abs( x );
size_t n = 0;
unsigned int tmp = u;
char *s;
do { ++n; } while ( tmp /= BASE );
n += x < 0;
s = malloc( ( n + 1 ) * sizeof( char ) );
s[n] = '\0';
do
{
s[--n] = u % BASE + '0';
} while ( u /= BASE );
if ( x < 0 ) s[--n] = '-';
return s;
}
int main(void)
{
char *s = itoa( -1234567890 );
printf( "%s\n", s );
free( s );
return 0;
}
The output is
-1234567890
As for your question what is wrong with your code then it is entirely wrong.:)
For example the code ignores numbers that are equal to zero. Variable pointer was not initialized
int pointer, i = 0;
each loop deals with some garbage and so on.
It will be more helpful for you if you will investigate my code.
OP's code looks very close to being correct for limited usage.
Do not start with value>0 test, otherwise when value == 0, the result will be "". Be sure to limit the number of iterations to not exceed the array size.
do {
str[i] = value%10 + '0';
value /=10;
i++;
} while (value>0 && i < (6-1));
Set '\0' in a loop. #timra points out random unset elements.
do {
str[i] = '\0';
i++;
} while (i < (6-1));
OP still has 2 remaining issues which OP has yet to specify what to do:
Values greater than 99999
Values < 0
BTW: "I think that '\0' is null, right?" '\0' is the "null character". This differs from NULL, the "null pointer".
"how can I change this to a function that get an int number and return array of char that present it"
OP's code has a number of corner problems. Suggest a new approach.
Perform conversion into local array and then return a copy of it.
Calling code should eventually free() it.
#include <limits.h>
// max size needed for int. Note 10/33 just greater than log(2)
#define INTSIZE_MAX (sizeof int * CHAR_BIT * 10 / 33 + 3)
char *intoa_alloc(int x) {
char buf[INTSIZE_MAX];
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value to cope with INT_MIN
// This avoids portability problems with abs(x) approach.
int x_negative = x < 0 ? x : -x;
// Form string
*p = '\0';
do {
*--p = '0' - x_negative % 10;
x_negative /= 10;
} while (x_negative);
if (x < 0) {
*--p = '-';
}
char *dest = malloc(strlen(p) + 1);
if (dest) {
strcpy(dest, p);
}
return dest;
}
In this simple way you can do that.
int main()
{
char str [6] = "324";
printf ("%c",str[1]);
return 0;
}

How to write a getline function in C?

I know that getline is C++ standard but I need to read a line of digits:
123856
and save it to an array. But how to do this without spaces between given (as input) digits? I want a user input to be:
123856 (with no spaces) and then save it to an array (n element array) and after that, I want my array to look like this:
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 8;
array[4] = 5;
array[5] = 6;
But how to make it in C, without a getline?
This is NOT what I want:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
int main(int argc, char **argv)
{
int t[4];
int i;
for(i=0; i<4; i++)
scanf("%d", &t[i]);
for(i=0; i<4; i++)
printf("%d\n", t[i]);
return 0;
}
If I understood you correct, the following should do it:
read the whole line
loop through the string as long as you get digits or the string ends
for every digit, place it's value in your array and increase the index by 1
while( ( c = getchar()) != EOF && c != '\n' && i < max ) {
/* If desired, add check for value outside of 0-9 */
array[ i++ ] = c - '0';
...
}
char arr[] = "1234567";
int intarr[10];
int count = 0;
for (char* ptr = arr; *ptr; ptr++) {
intarr[count] = *ptr - '0';
count++;
}
try this
#include <stdio.h>
#include <string.h>
main (int argc, char *argv[])
{
FILE *f;
int i=0;
int j=0;
char output[100];
char* output1[100];
char string[100];
char delims1[] = " ";
char delims2[] = "*";
char* result = NULL;
char* result3 = NULL;
int num;
//for (j=0; j<2; j++)
//{
//printf("%s",delims9[6]);
//}
f = fopen("text.txt","r");
//
while( fgets(string,sizeof(string),f) )
{
result = strtok( string, delims1 );
while( result != NULL )
{
output1[i]=result;
printf("%s\n",output1[i]);
result = strtok( NULL, delims1 );
i++;
}
for (num = 0; num < 100; i++ ) //
{ // Error On this array
printf("%s\n", output1[i]); //
} //
}
printf("\n%d",i/3+1);
return 0 ;
}
Ok, without using any string.
int digits = 123856;
int numofdigits = 1 + floor(log10(digits));
int digits_arr[numofdigits];
int i;
for(i = numofdigits-1; i >= 0; i--) {
digits_arr[i] = (int)floor(digits / pow(10, i)) % 10;
}
Try the below link... Same question asked here and get solution....
convert an integer number into an array
char * convertNumberIntoArray(unsigned int number) {
unsigned int length = (int)(log10((float)number)) + 1;
char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
do {
*curr++ = number % 10;
number /= 10;
} while (number != 0);
return arr;
}

Resources