I'm trying to "translate" an array of uint8_t [uint8_t lets_try[16]] to a string of 16*8+1[null character] elements. For example:
lets_try[0] = 10101010
lets_try[1] = 01010101
...
and I would like to have a string like:
1010101001010101...[\0]
Here the questions: 1) is there a quick way to perform this operation?
I was trying to do it on my own; my idea was starting from translating a single uint8_t variable into a string and obtaining the full array with a loop [I haven't done this last part yet]. At the end I wrote this code:
int main()
{
uint8_t example = 0x14;
uint8_t *pointer;
char *final_string;
pointer = &example;
final_string = convert(pointer);
puts(final_string);
return(0);
}
char *convert (uint8_t *a)
{
int buffer1[9];
char buffer2[9];
int i;
char *buffer_pointer;
buffer1[8]='\0';
for(i=0; i<=7; i++)
buffer1[7-i]=( ((*a)>>i)&(0x01) );
for(i=0; i<=7; i++)
buffer2[i] = buffer1[i] + '0';
buffer2[8] = '\0';
puts(buffer2);
buffer_pointer = buffer2;
return buffer_pointer;
}
Here other few questions:
2) I'm not sure I fully understand the magic in this expression I found online:
buffer2[i] = buffer1[i] + '0'; can somebody explain to me why the following puts(buffer2) is not going to work correctly without the +'0'? is it the null character at the end of the newborn string which makes the puts() work? [because with the null character it knows it's printing a real string?]
3) in the code above puts(buffer2) gives the right output while the puts in main() gives nothing; I'm going mad in looking again and again the code, I can't find what's wrong with that
4) in my solution I manage to convert an uint8_t into a string passing from an array of int:
uint8_t->int array->string; is there a way to shorten this procedure, passing directly from the uint8_t into a string, or improve it? [in forums I found only solutions in C++] it works but I find it a little heavy and not so elegant
Thanks everybody for the support
1.) it's a little bit faster to eliminate the int array.
2.) adding '0' changes the integer values 0 and 1 to their ascii values '0' and '1'.
3.) it's undefined behaviour to return the address of a local variable. You have to malloc memory in the heap.
4.) yes, just cut it out and do the whole operation all in one
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
char *convert(uint8_t *a)
{
char* buffer2;
int i;
buffer2 = malloc(9);
if (!buffer2)
return NULL;
buffer2[8] = 0;
for (i = 0; i <= 7; i++)
buffer2[7 - i] = (((*a) >> i) & (0x01)) + '0';
puts(buffer2);
return buffer2;
}
int main()
{
uint8_t example = 0x14;
char *final_string;
final_string = convert(&example);
if (final_string)
{
puts(final_string);
free(final_string);
}
return 0;
}
Here's one way ...
char *uint8tob( uint8_t value ) {
static uint8_t base = 2;
static char buffer[8] = {0};
int i = 8;
for( ; i ; --i, value /= base ) {
buffer[i] = "01"[value % base];
}
return &buffer[i+1];
}
char *convert_bytes_to_binary_string( uint8_t *bytes, size_t count ) {
if ( count < 1 ) {
return NULL;
}
size_t buffer_size = 8 * count + 1;
char *buffer = calloc( 1, buffer_size );
if ( buffer == NULL ) {
return NULL;
}
char *output = buffer;
for ( int i = 0 ; i < count ; i++ ) {
memcpy( output, uint8tob( bytes[i] ), 8 );
output += 8;
}
return buffer;
};
int main(int argc, const char * argv[]) {
uint8_t bytes[4] = { 0b10000000, 0b11110000, 0b00001111, 0b11110001 };
char *string = convert_bytes_to_binary_string( bytes, 4 );
if ( string == NULL ) {
printf( "Ooops!\n" );
} else {
printf( "Result: %s\n", string );
free( string );
}
return 0;
}
... just extend for 16 bytes. There are many ways and it also depends on what do you mean with quick. Embedded systems, ...? You can make translation table to make it even faster, ...
UPDATE
char *convert_bytes_to_binary_string( uint8_t *bytes, size_t count ) {
if ( count < 1 ) {
return NULL;
}
const char *table[] = {
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
};
size_t buffer_size = 8 * count + 1;
char *buffer = malloc( buffer_size );
if ( buffer == NULL ) {
return NULL;
}
char *output = buffer;
for ( int i = 0 ; i < count ; i++ ) {
memcpy( output, table[ bytes[i] >> 4 ], 4 );
output += 4;
memcpy( output, table[ bytes[i] & 0x0F ], 4 );
output += 4;
}
*output = 0;
return buffer;
};
int main(int argc, const char * argv[]) {
uint8_t bytes[4] = { 0b10000000, 0b11110000, 0b00001111, 0b11110001 };
char *string = convert_bytes_to_binary_string( bytes, 4 );
if ( string == NULL ) {
printf( "Ooops!\n" );
} else {
printf( "Result: %s\n", string );
free( string );
}
return 0;
}
Related
I've been tried to place each character in the source string between characters in the destination string. It worked with equal length words but it didn't work other situations
For example:
It worked between apple and fruit, result is afprpuliet.
But it didn't work between plane and yes, the result should have been pyleasne.
or fly and train, the result should have been ftlryain.
Here is my code:
#include <stdio.h>
#include <string.h>
#define DESTSIZE 100
#define SOURCESIZE 20
int main(void)
{
char destination [DESTSIZE], source [SOURCESIZE];
printf("enter destinantion string for strinsert: ");
scanf("%s", destination);
printf("enter source string for strinsert: ");
scanf("%s", source);
strinsert(destination, source);
printf("after strinsert, destination string is %s\n", destination);
return 0;
}
void strinsert(char destination[], char source [])
{
int dest_len = strlen(destination);
for (int i = dest_len - 1; i >= 0; i--) {
destination[2 * i] = destination[i];
}
for (int i = 0; i < dest_len; i++) {
destination[2 * i + 1]= source[i];
}
}
To do this "in place" (using an adequately sized destination array) is not hard. The key is to determine the index of the destination element, then start copying, one by one, from the longest of the two strings, right to left.
Subtle is that when the two lengths yet to be copied are the same value, the second array is used as the source, not the first.
#include <stdio.h>
#include <string.h>
char *merge( char s1[], char s2[] ) {
int l1 = strlen( s1 );
int l2 = strlen( s2 );
s1[ l1 + l2 ] = '\0'; // ensure string will be terminated
while( l1 || l2 )
if( l1 > l2 )
l1--, s1[ l1 + l2 ] = s1[ l1 ];
else
l2--, s1[ l1 + l2 ] = s2[ l2 ];
return s1;
}
int main( void ) {
char dest[100];
char *test[] = { "apple", "fruit", "plane", "yes", "fly", "train", };
const int nTest = sizeof test/sizeof test[0];
for( int i = 0; i < nTest; i += 2 ) {
printf( "%s << %s = ", test[i], test[i+1] );
strcpy( dest, test[i] );
puts( merge( dest, test[i+1] ) );
}
return 0;
}
apple << fruit = afprpuliet
plane << yes = pyleasne
fly << train = ftlryain
A more compact version of main() so that it doesn't draw so much attention:
int main( void ) {
char d[100], *t[] = { "apple", "fruit", "plane", "yes", "fly", "train", };
for( int i = 0; i < sizeof t/sizeof t[0]; i += 2 )
printf("%s << %s = %s\n", t[i], t[i+1], merge(strcpy(d, t[i]), t[i+1]));
return 0;
}
EDIT
Although this is more difficult for a human to read, merge() could, likewise, be made more compact. It's up to the reader to decide if this appeals to their taste.
char *merge( char s1[], char s2[] ) {
int l1 = strlen( s1 ), l2 = strlen( s2 );
char *p = s1 + l1 + l2;
*p = '\0';
while( l1 || l2 )
*--p = ( l1 > l2 ) ? s1[ --l1 ] : s2[ --l2 ];
return p;
}
The problem is here
for (int i = 0; i < dest_len; i++) {
destination[2 * i + 1]= source[i];
}
Your source length is only 20 characters but your destination length is 100. So you are reading past the bounds of the source array. You should change the second loop to something like
int src_len = strlen(source);
for (int i = 0; i < src_len; i++) {
destination[2 * i + 1]= source[i];
}
I think you are messing yourself up by trying to do it in-place. Sure, it can be done in-place, but that just adds complexity.
Try doing it with a destination that is not either of the sources.
void interleave_strings( char * dest, const char * src1, const char * src2 )
{
// Interleaves src1 and src2 and stores the result in dest.
// dest must have space for strlen(src1) + strlen(src2) + 1 characters.
}
Usage:
int main(void)
{
char destination[SOURCE_SIZE*2+1] = {0};
char source1[SOURCE_SIZE] = {0};
char source2[SOURCE_SIZE] = {0};
...
interleave_strings( destination, source1, source2 );
printf( "interleaved = \"%s\"\n", destination );
return 0;
}
Once you make sense of doing it that way, then you can totally go back and do it the harder in-place way.
Oh, BTW, functions beginning with “str” are reserved. Hence you should not create them. So I renamed it.
You overwrite existing data in the destination. The easiest way is to use temporary array:
char *merge(char *dest, const char *src)
{
char temp[strlen(dest) + strlen(src) + 1];
char *wrk = dest;
size_t index = 0;
while(*src | *dest)
{
if(*dest) temp[index++] = *dest++;
if(*src) temp[index++] = *src++;
}
memcpy(dest, temp, index);
dest[index] = 0;
return dest;
}
int main(void)
{
char dest[256] = "1234567890";
char *src = "abcdefghijklmno";
puts(merge(dest, src));
}
https://godbolt.org/z/sqznjMf6r
or with your examples:
int main(void)
{
puts(merge((char[128]){"apple"}, "fruit"));
puts(merge((char[128]){"pen"}, "paper"));
puts(merge((char[128]){"plane"}, "yes"));
puts(merge((char[128]){"fly"}, "train"));
}
https://godbolt.org/z/6dc9Kv3dP
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;
}
I'm trying to split a string into chunks of 6 using C and I'm having a rough time of it. If you input a 12 character long string it just prints two unusual characters.
#include <stdio.h>
#include <string.h>
void stringSplit(char string[50])
{
int counter = 0;
char chunk[7];
for (unsigned int i = 0; i < strlen(string); i++)
{
if (string[i] == ' ')
{
continue;
}
int lastElement = strlen(chunk) - 1;
chunk[lastElement] = string[i];
counter++;
if (counter == 6)
{
printf(chunk);
memset(chunk, '\0', sizeof chunk);
counter = 0;
}
}
if (chunk != NULL)
{
printf(chunk);
}
}
int main()
{
char string[50];
printf("Input string. \n");
fgets(string, 50, stdin);
stringSplit(string);
return(0);
}
I appreciate any help.
Your problem is at
int lastElement = strlen(chunk) - 1;
Firstly, strlen counts the number of characters up to the NUL character. Your array is initially uninitialized, so this might cause problems.
Assuming your array is filled with NULs, and you have, let's say, 2 characters at the beginning and you are looking to place the third one. Remember that your 2 characters are at positions 0 and 1, respectively. So, strlen will return 2 (your string has 2 characters), you subtract one, so the lastElement variable has the value 1 now. And you place the third character at index 1, thus overwriting the second character you already had.
Also, this is extremely inefficient, since you compute the number of characters each time. But wait, you already know how many characters you have (you count them in counter, don't you?). So why not use counter to compute the index where the new character should be placed? (be careful not to do the same mistake and overwrite something else).
The function is wrong.
This statement
int lastElement = strlen(chunk) - 1;
can result in undefined behavior of the function because firstly the array chunk is not initially initialized
char chunk[7];
and secondly after this statement
memset(chunk, '\0', sizeof chunk);
the value of the variable lastElement will be equal to -1.
This if statement
if (chunk != NULL)
{
printf(chunk);
}
does not make sense because the address of the first character of the array chunk is always unequal to NULL.
It seems that what you mean is the following.
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[] )
{
const size_t N = 6;
char chunk[N + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == N )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
stringSplit( s );
}
The program output is
Youand
Iarebe
ginner
sinC
You can modify the function such a way that the length of the chunk was specified as a function parameter.
For example
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[], size_t n )
{
if ( n )
{
char chunk[n + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == n )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
for ( size_t i = 3; i < 10; i++ )
{
stringSplit( s, i );
puts( "" );
}
}
The program output will be
You
and
Iar
ebe
gin
ner
sin
C
Youa
ndIa
rebe
ginn
ersi
nC
Youan
dIare
begin
nersi
nC
Youand
Iarebe
ginner
sinC
YouandI
arebegi
nnersin
C
YouandIa
rebeginn
ersinC
YouandIar
ebeginner
sinC
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;
}
I'm trying to write code in C that will take a string, check each character for a specific character (call it 'x'), and if the character is 'x', change it to multiple characters (like "yz"). Here is my attempt, assuming buffer and replace are defined arrays of characters (i.e. char buffer[400] = jbxyfgextd...; char replace[250];)
int j = 0;
for (j = 0; j < 110; j++) {
if (buffer[j]=='x') {
int len = strlen(replace);
replace[len] = 'y';
replace[len+1] = 'z';
}
else {
replace[j]=buffer[j];
}
}
When I run this I get some y's and z's, but they are not back to back. Is there any procedure/function to do this easily?
Because index in buffer[] and replace[] arrays are not same. Use two indexes separately.
In your code expression: replace[j] = buffer[j]; is wrong. You can correct it like:
else {
int len = strlen(replace);
replace[len]=buffer[j];
}
But to use strlen(), array replace[] should be nul \0 terminated. (declare replace as char replace[250] = {0})
Edit:
To write better code use two septate indexes as I suggested above -- code will be efficient and simplified.
int bi = 0; // buffer index
int ri = 0; // replace index
for (bi = 0; bi < 110; bi++) {
if (buffer[bi] == 'x') {
replace[ri++] = 'y';
replace[ri] = 'z';
}
else {
replace[ri] = buffer[bi];
}
replace[++ri] = '\0'; // terminated with nul to make it string
}
#include <iostream>
#include <string>
#include <cstring>
int main ( int argc, char *argv[])
{
// Pass through the array once counting the number of chars the final string
// will need then allocate the new string
char buffer[] = "this x is a text test";
char replacement[] = "yz";
unsigned int replaceSize = strlen(replacement);
unsigned int bufferSize = 0;
unsigned int newSize = 0;
// calculate the current size and new size strings
// based on the replacement size
char *x = buffer;
while (*x)
{
if ( *x == 'x' )
{
newSize+=replaceSize;
}
else
{
++newSize;
}
++x;
++bufferSize;
}
// allocate the new string with the new size
// and assign the items to it
char *newString = new char[newSize];
unsigned int newIndex = 0;
for ( unsigned int i = 0; i < bufferSize; ++i )
{
if ( buffer[i] == 'x' )
{
for ( unsigned int j = 0; j < replaceSize ; ++j )
{
newString[newIndex++] = replacement[j];
}
}
else
{
newString[newIndex++] = buffer[i];
}
}
std::string originalS ( buffer );
std::string newS ( newString );
std::cout << "Original: " << originalS << std::endl;
std::cout << "New: " << newS << std::endl;
delete newString;
}