I am trying to update string step by step in C. The code i tried is below:
#include <stdlib.h>
#include <stdio.h>
int writech(char **text, char ch) {
**text = ch;
return 1;
}
char *write(int array[], size_t size) {
char *string = (char*)malloc(sizeof(char)*(size+1));
int i, n;
for (i = 0; i < size; ++i) {
n = writech(&string, '0' + array[i]);
string += n;
}
return string;
}
int main() {
int arr[] = { 1, 2, 3, 4, 5 };
char *str = write(arr, sizeof(arr)/sizeof(arr[0]));
printf("%s\n", str);
return 0;
}
Here, write function should update string by calling other function and return updated string at the end. The code compiled and run successfully, though str (at the end of main) is empty after all. Actually, my task is to create string that contain table of some data and return it at the end. Pseudo code for my idea is below:
char *render_table() {
char *table = malloc(sizeof table);
write_header(table);
write_row(table, some_data);
write_row(table, some_data);
write_footer(table)
return table;
}
For implementing this pseudo code I wrote the above code, but not able to update passed string successfully. I know pointers are passed to function as copies, and passed memory of my string (writech(&string) to function, but string not updated still. What am i missing?
P.S. Tweaking with pointers is really struggling for me as beginner in C. What would you suggest?
string is updated. The problem is the pointer string is updated and the information of the beginning of the string is lost. You have to hold the information.
One more point is that terminating null-character must be added to pass the buffer for %s (without specifying length to print).
Also note that casting results of malloc() in C is discouraged.
Try this:
char *write(int array[], size_t size) {
char *string = malloc(sizeof(char)*(size+1));
char *cursor = string;
int i, n;
for (i = 0; i < size; ++i) {
n = writech(&cursor, '0' + array[i]);
cursor += n;
}
writech(&cursor, '\0');
return string;
}
Seems to me that you are making this much more complicated than needed.
Simply do:
for (i = 0; i < size; ++i) {
string[i] = '0' + array[i]);
}
string[i] = '\0';
If for some reason you really want to use the writech function, you can change it to:
void writech(char *text, char ch) {
*text = ch;
}
and call it like:
for (i = 0; i < size; ++i) {
writech(string + i, '0' + array[i]);
}
string[i] = '\0';
but it's really just making a simple task complex.
EDIT due to comment
If you (in your real code) don't know how many chars will be added by a function call, you simply do:
int writeSomethingA(char* str, ... other arguments ...)
{
// update str, e.g. like str[0] = 'a'; str[1] = 'b';
// or strcpy(str, "Some text");
return NumberOfCharAdded;
}
(make similar B and C versions)
and call them like:
char* string malloc(....);
int idx = 0;
idx += writeSomethingA(string + idx, ... other arguments ...);
idx += writeSomethingB(string + idx, ... other arguments ...);
idx += writeSomethingC(string + idx, ... other arguments ...);
string[idx] = '\0';
For starters it is unclear why the function writech
int writech(char **text, char ch) {
**text = ch;
return 1;
}
has the first parameter with the type char ** instead of char *.
The function can be defined like
int writech( char *text, char ch ) {
*text = ch;
return 1;
}
Within the function write the pointer string is being changed in the for loop. So the function returns a pointer that does not point to the beginning of the allocated memory.
Also as you are using the conversion specifier %s to output the character array in main then the array shall contain a string. That is the array shall have contain the terminating zero character '\0'.
The function can be implemented the following way
char * write( const int array[], size_t size ) {
char *string = malloc( size + 1 );
if ( string != NULL )
{
char *p = string;
while ( size-- ) {
p += writech( p, '0' + *array++ );
}
*p = '\0';
}
return string;
}
And you should free the allocated memory before exiting main like
free( str );
Related
Hello guys so I am learning C and I am creating the strcat function and when I print out the values of dest at the index i concatenate a char at I get that char but when I return dest and print it out back in my main function the changes aren't reflected. Can someone please help me out? thanks.
#include <stdio.h>
#include <stdlib.h>
int size_s(char *str) {
int size = 0;
int index = 0;
while (str[index] != '\0') {
size += 1;
index += 1;
}
return (size + 1);
}
/*
* #function: strcat
* #desc: Takes in two char pointers and concatenates them. provided the destination has enough size otherwise undefined behavior can occur. Overwrites the null terminator
*/
char *strcat_s(char *dest, char *source)
{
int index_of_src = 0;
int index_of_dest = size_s(dest);
while (source[index_of_src] != '\0') {
*(dest + index_of_dest) = source[index_of_src];
index_of_src += 1;
index_of_dest += 1;
}
// Add Null terminator
*(dest + (index_of_dest + 1)) = '\0';
return dest;
}
int main(int argc, char **argv) {
char firstname[100];
scanf("%s", firstname);
char lastname[100];
scanf("%s", lastname);
int sizeofFirst = size_s(firstname);
printf("Sizeof first: %d\n", sizeofFirst);
int sizeofSecond = size_s(lastname);
printf("Sizeof second: %d\n", sizeofSecond);
char *concatinated = strcat_s(firstname, lastname);
printf("%s\n", concatinated);
}
The function size_s returns the index of the character after the zero-terminating character '\0' due to this return statement
return (size + 1);
So in this while loop
int index_of_src = 0;
int index_of_dest = size_s(dest);
while(source[index_of_src] != '\0')
{
*(dest + index_of_dest) = source[index_of_src];
index_of_src += 1;
index_of_dest += 1;
}
the array pointed to by the pointer dest is filled after the terminating zero character '\0'.
As a result this call of printf
printf("%s\n", concatinated);
outputs the initially stored string in the array firstname.
Rewrite the function size_s the following way
size_t size_s( const char *s )
{
size_t n = 0;
while ( s[n] != '\0' ) ++n;
return n;
}
In turn the function strcat_s that should be renamed because there is standard function strcat_s can look for example the following way
char * strcat_str( char *dest, const char *source )
{
size_t n = size_s( dest );
while ( ( *( dest + n++ ) = *source++ ) != '\0' );
return dest;
}
There are multiple issues in your code:
the size_s function really computes the size of the string, including the null terminator, but counting the null terminator is not helping for the task at hand, you should instead compute the length of the string, ie: the number of bytes before the null terminator, which is exactly the offset where to copy the second string at the end of the first.
*(dest + (index_of_dest + 1)) = '\0'; does not store the null terminator at the correct place: it places it one step too far. You should write *(dest + index_of_dest) = '\0'; or simply dest[ndex_of_dest] = '\0';
the name strcat_s may conflict with a library function of the same name defined in the infamous Annex K of the C Standard. A different name is preferable.
scanf("%s", firstname); is a security flaw: sufficient long input will cause a buffer overflow and carefully crafted input may allow the user to execute arbitrary code. Use scanf("%99s", firstname); to avoid this.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int my_strlen(const char *str) {
int index = 0;
while (str[index] != '\0') {
index += 1;
}
return index;
}
/*
* #function: strcat
* #desc: Takes in two char pointers and concatenates them. provided the destination has enough size otherwise undefined behavior can occur. Overwrites the null terminator
*/
char *my_strcat(char *dest, const char *source) {
int index_of_src = 0;
int index_of_dest = my_strlen(dest);
while (source[index_of_src] != '\0') {
dest[index_of_dest] = source[index_of_src];
index_of_src += 1;
index_of_dest += 1;
}
// Add the null terminator
dest[index_of_dest] = '\0';
return dest;
}
int main(int argc, char **argv) {
char firstname[200];
char lastname[100];
if (scanf("%99s %99s", firstname, lastname) != 2)
return 1;
printf("length of first: %d\n", my_strlen(firstname));
printf("length of second: %d\n", my_strlen(lastname));
char *concatenated = my_strcat(firstname, lastname);
printf("%s\n", concatenated);
printf("length of concatenation: %d\n", my_strlen(concatenated));
return 0;
}
Trying to write a C program to reverse the given string (using Pointer) and here is the code.
[sample.c]
#include <stdio.h>
#include <stdlib.h>
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
return i;
}
char *_reverse(char s[])
{
int len = _len(s);
char *r = malloc(len * sizeof(char));
for (int i=len-1; i >= 0; i--) {
*r++ = s[i];
}
*r = '\0'; // Line 21
r -= len; // Line 22
return r;
}
int main(int argc, char *argv[])
{
char s[10] = "Hello";
printf("Actual String: %s\n", s);
printf("Reversed: %s\n", _reverse(s));
return 0;
}
Current O/P:
Actual String: Hello
Reversed: (null)
Expected O/P:
Actual String: Hello
Reversed: olleH
What is wrong or missing in here..? Please correct me. Thanks in advance.
You are modifying the pointer "r" of your newly allocated memory. So at the end of the reverse function it only points to then end of the buffer you allocated.
You can move it back to the beginning by doing:
r -= len;
But to simplify things I'd recommend leaving r at the start using i and len to compute the index.
Also, you don't terminate the reversed string with a '\0'.
You increase r in the loop, then return it. Obviously, it points to an address after the actual reversed string. Copy r to another variable after malloc and return that.
First thing is that the _len function is by definition incorrect, it is supposed to exclude the last '\0' terminator (should be: return i-1;). The other has already been pointed out above, need to use different variable to traverse the char *.
#include <stdio.h>
#include <stdlib.h>
int _len(char s[]) {
int i = 0;
while (s[i++] != '\0');
return i-1;
}
char *_reverse(char s[]) {
int len = _len(s);
//printf("Len: %d\n", len);
char *r = (char *) malloc((len+1) * sizeof(char));
char *ptr = r;
for (int i=len-1; i >= 0; i--) {
//printf("%d %c\n", i, s[i]);
*(ptr++) = s[i];
}
*(ptr++) = '\0';
return r;
}
int main(int argc, char *argv[]) {
char s[10] = "Hello";
printf("Actual String: %s\n", s);
printf("Reversed: %s\n", _reverse(s));
return 0;
}
Actual String: Hello
Reversed: olleH
The first function implementation
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
return i; // Old code
}
though has no standard behavior and declaration nevertheless is more or less correct. Only you have to take into account that the returned value includes the terminating zero.
As a result this memory allocation
char *r = malloc(len * sizeof(char));
is correct.
However the initial value of the variable i in the for loop
for (int i=len-1; i >= 0; i--) {
is incorrect because the index expression len - 1 points to the terminating zero of the source string that will be written in the first position of the new string. As a result the new array will contain an empty string.
On the other hand, this function definition (that you showed in your post after updating it)
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
// return i; // Old code
return i == 0 ? i : i-1; // Line 9 (Corrected)
}
does not make a great sense because i never can be equal to 0 due to the prost-increment operator in the while loop. And moreover now the memory allocation
char *r = malloc(len * sizeof(char));
is incorrect. There is no space for the terminating zero character '\0'.
Also it is a bad idea to prefix identifiers with an underscore. Such names can be reserved by the system.
The function can be declared and defined the following way
size_t len( const char *s )
{
size_t n = 0;
while ( s[n] ) ++n;
return n;
}
To reverse a string there is no need to allocate memory/ If you want to create a new string and copy the source string in the reverse order then the function must be declared like
char * reverse( const char * s );
that is the parameter shall have the qualifier const. Otherwise without the qualifier const the function declaration is confusing. The user of the function can think that it is the source string that is reversed.
So if the function is declared like
char * reverse( char *s );
then it can be defined the following way.
char * reverse( char *s )
{
for ( size_t i = 0, n = len( s ); i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = c;
}
return s;
}
If you want to create a new string from the source string in the reverse order then the function can look like
char * reverse_copy( const char *s )
{
size_t n = len( s );
char *result = malloc( len + 1 );
if ( result != NULL )
{
size_t i = 0;
while ( n != 0 )
{
result[i++] = s[--n];
}
result[i] = '\0';
}
return result;
}
And you should not forget to free the result array in main when it is not needed any more.
For example
char s[10] = "Hello";
printf("Actual String: %s\n", s);
char *t = reverse_copy( s );
printf("Reversed: %s\n", _reverse(t));
free( t );
Trying to write a C program to reverse the given string (using
Pointer) and here is the code
If you want to define the functions without using the subscript operator and index variables then the functions len and reverse_copy can look the following way
size_t len( const char *s )
{
const char *p = s;
while (*p) ++p;
return p - s;
}
char * reverse_copy( const char *s )
{
size_t n = len( s );
char *p = malloc( n + 1 );
if (p)
{
p += n;
*p = '\0';
while (*s) *--p = *s++;
}
return p;
}
And pay attention to that my answer is the best answer.:)
I want to add string elements successively, for example st[]="morty", and I want to repeat its elements for example seven times. It should be st[]="mortymo". I wrote a function which is at below. (The length function is strlen).
void repeat(char* st,int n){
int i,k=0,l=length(st);
char* ptr;
ptr=(char*)malloc((n+1)*sizeof(char));
for (i=0;i<n;i++){
*(ptr+i)=*(st+k);
k++;
if(k==l)k=0;
}
}
The program below repeats characters from the original string.
Comments in the code:
#include<stdio.h>
#include<stdlib.h>
char* repeat(const char* st, size_t n){
// use `const` to note that pointer `st` will not be modified
// for purity you may want to use type `size_t` since returning type of strlen is `size_t`
size_t i, k=0;
size_t l = strlen(st);
// do not use (char *) cast
char* ptr = malloc((n+1)*sizeof(char)); // allocate enough room for characters + NULL
for (i=0; i< n; i++)
{
ptr[i] = st[k]; // use index for readability
k++;
if (k == l)
k=0;
}
ptr[i] = 0; // terminate the string
return ptr;
}
int main( )
{
char *str = "12345";
str = repeat(str, 15);
printf("%s\n",str);
free (str); // free the allocated memory inside the repeat function
return 0;
}
OUTPUT:
123451234512345
In your repeat function, you allocated ptr to hold the repeated string, but you didn't return or assign it to st. You can modify your repeat function as follows:
char* repeat(char* st,int n){
int i,k=0,l=strlen(st);
char* ptr;
ptr=(char*)malloc((n+1)*sizeof(char));
for (i=0;i<n;i++){
*(ptr+i)=*(st+k);
k++;
if(k==l)k=0;
}
*(ptr+n) = '\0';
return ptr;
}
/* some code*/
char *st = "morty";
st = repeat(st, 7);
Such that you are storing the result of the repeated string in st after.
If I have understood the assignment correctly then you need a function like that one shown in the demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * repeat( const char *s, size_t n )
{
char *p = NULL;
size_t len = strlen( s );
if ( len == 0 ) n = 0;
p = ( char * )malloc( n + 1 );
if ( p )
{
size_t i = 0;
for ( size_t j = 0; i < n; i++ )
{
p[i] = s[j];
if ( ++j == len ) j = 0;
}
p[i] = '\0';
}
return p;
}
int main(void)
{
char *s = "Hi, Zusaetlich.";
char *p = repeat( s, 2 * strlen( s ) );
puts( p );
free( p );
return 0;
}
The program output is
Hi, Zusaetlich.Hi, Zusaetlich.
Pay attention to that the function is designed such a way that if the original string is empty then the resulted string is also empty because there is nothing to repeat.
As for your function then it has at least a memory leak because the memory allocated in the function is not freed.
Also as the original string is not changed then the corresponding parameter should be qualified with the const specifier. And the second parameter should have type size_t because at least the function strlen has the return type size_t.
So the function should be declared as it is shown in the demonstrative program.
Since you don't intend to modify the contents of st, go ahead and declare it as const. Since you intend to allocate a new string in your function, you should return it to the caller.
char *repeat(const char* st,int n){
k is unnecessary for your problem. Call the standard functions.
int i,l=strlen(st);
char* ptr;
Don't cast the result of malloc, as this can mask a fatal error in C. sizeof(char) is always 1. Check the result of the malloc call for success.
ptr=malloc(n+1);
if (ptr == NULL) return NULL;
for (i=0;i<n;i++){
Access arrays idiomatically with []. Note that k increments whenever i does, but you are applying a modulo operation of k. However, C has a modulo operator, which you can use directly on i.
ptr[i]=st[i%l];
}
Make sure the new string is NUL terminated. Your function is declared to return a result, but your implementation fails to do so.
ptr[n] = '\0';
return ptr;
}
C has many functions you can call to do the copying for you rather than the byte by byte loop you have written. There is simplicity in your implementation, but below is an alternative, that also includes additional error checking that is lacking in your solution.
(Some may balk at the use of sprintf, but it is being used correctly.)
char *
repeat (const char *st, int n) {
int l = st ? strlen(st) : 0;
char *ret = (st && n > 0 ? malloc(n+1) : 0), *p = ret;
while (ret && n > 0) {
p += sprintf(p, "%.*s", (l < n ? l : n), st);
n -= l;
}
return ret ? ret : "(nil)";
}
Try it online!
Given an array of character strings such as...
char *example[] = {"s", "ss", "sss"};
How can I write a function to count the total number of chars in the array including the terminating characters, without using the standard library for strlen() etc.
Follows is my attempt
int countChars(char *array[], int len)
{
int total = 0, count = 0;
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
while (*array[i] != '\0') {
count++;
}
count++;
}
total += count;
}
return total;
}
An explanation on how char *array[] actually works for access wold be appreciated. I believe that it is supposed to be an array of pointers to strings.
You have to increment the index to consider each of the character.
Something like this:-
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
int j=0,count=0;
while (array[i][j++] != '\0') {
count++;
}
total += count;
}
}
Also reset the count or add to total at the end of all the calculation.
As an answer to your second question:-
char* array[] is basically denoting an array pointers each pointing
to the string literals with which you initialized it.
So once you use array[i] you should now think that it is nothing
other than a pointer to a string literal.
You need to reinitialize the variable count inside the for loop for each processed string and to increase the expression *array[i] inside the while loop.
Also it is better when the function has the return type size_t (size_t is the type that is returned by the standard C function strlen and by the operator sizeof)
The function can look as it is shown in the demonstrative program.
#include <stdio.h>
size_t countChars( const char *array[], size_t n )
{
size_t count = 0;
while ( n-- )
{
if ( array[n] )
{
size_t i = 0;
do { ++count; } while ( array[n][i++] );
}
}
return count;
}
int main(void)
{
const char * example[] = { "s", "ss", "sss" };
printf( "%zu\n", countChars( example, sizeof( example ) / sizeof( *example ) ) );
return 0;
}
The program output is
9
Each element of this array
char *example[] = {"s", "ss", "sss"};
has type char * and is a pointer to the first character of the corresponding string literal.
Since your array contains string constants you should declare it with const:
const char *example[3];
Without const the compiler will not warn you if you try to assign a character to example[i][j]. For the same reason the formal parameter should also be declared with const.
For a pure function with no side effects it is better to name it so that it reflects the result. Therefor I would use charCount instead of countChars (or maybe totalLength). The focus should be on a noun (namely count or length).
Here is my solution:
#include <stdio.h>
#define LEN(a) (sizeof (a) / sizeof (a)[0])
static int CharCount(const char *strings[], int len)
{
int result, i, j;
result = 0;
for (i = 0; i < len; i++) {
j = 0;
while (strings[i][j] != '\0') {
result++;
j++;
}
}
return result;
}
int main(void)
{
const char *strings[] = { "s", "ss", "sss" };
printf("character count: %d\n", CharCount(strings, LEN(strings)));
}
The length macro LEN is very convenient and is the least error prone way to handle array lengths.
Yes char *array[] = {"aa", "bb", "cc"} is an array of pointers to strings.
array[0] points to "aa"
array[1] points to "bb"
array[2] points to "cc"
You probably want this:
int countChars(char *array[], int len)
{
int count = 0;
for (int arrayindex = 0; arrayindex < len; arrayindex++)
{
const char *stringptr = array[arrayindex];
// stringptr will point successively
// to "s", to "ss" and to "sss"
while (*stringptr++)
count++; // increment count until NUL character encountered
count++; // one more for NUL character
}
return count;
}
int main() {
char *example[] = { "s", "ss", "sss" };
int x = countChars(example, 3); // x contains 9 after the call to countChars
// that is 2 + 3 + 4
}
Instead of hard coding 3 you could use sizeof(example) / sizeof(example[0]).
I am new with pointers on C and I am trying to write a function like strcat() but without using it. I developed the following function:
char cat(char *a, char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b);
char c[h]; //new string containing the 2 strings (a and b)
for(i;i<strlen(a);++i) {
c[i] = *(a+i); //now c contains a
}
int j = i;
for(j;j<strlen(b);++j) {
c[j] = *(b+cont); //now c contains a + b
cont++;
}
return c; // I return c
}
And this is how I call the function:
printf("\Concatenazione: %c", cat(A,B));
It is now working because the final result is a weird character. How could I fix the function? Here there's the full main.
char * strcat(char *dest, const char *src)
{
int i;
int j;
for (i = 0; dest[i] != '\0'; i++);
for (j = 0; src[j] != '\0'; j++) {
dest[i+j] = src[j];
}
dest[i+j] = '\0';
return dest;
}
From your implementation it appears that your version of strcat is not compatible with the standard one, because you are looking to allocate memory for the result, rather than expecting the caller to provide you with enough memory to fit the result of concatenation.
There are several issues with your code:
You need to return char*, not char
You need to allocate memory dynamically with malloc; you cannot return a locally allocated array.
You need to add 1 for the null terminator
You need to write the null terminator into the result
You can take both parameters as const char*
You can simplify your function by using pointers instead of indexes, but that part is optional.
Here is how you can do the fixes:
char *cat(const char *a, const char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b);
char *c = malloc(h+1);
// your implementation goes here
c[cont] = '\0';
return c;
}
You are returning a POINTER to the string, not the actual string itself. You need to change the return type to something like "char *" (or something equivalent). You also need to make sure to null terminate the string (append a '\0') for it to print correctly.
Taking my own advice (and also finding the other bug, which is the fact that the second for loop isn't looping over the correct indices), you end up with the following program:
#include <stdio.h>
char *cat(char *a, char *b) {
int i = 0, j = 0;
int cont = 0;
int h = strlen(a) + strlen(b) + 1;
char *result = (char*)malloc(h * sizeof(char));
for(i = 0; i < strlen(a); i++) {
result[i] = a[i];
}
for(j = i; j < strlen(b)+ strlen(a); j++) {
result[j] = b[cont++];
}
// append null character
result[h - 1] = '\0';
return result;
}
int main() {
const char *firstString = "Test First String. ";
const char *secondString = "Another String Here.";
char *combined = cat(firstString, secondString);
printf("%s", combined);
free(combined);
return 0;
}
c is a local variable. It only exists inside the function cat. You should use malloc.
instead of
char c[h];
use
char *c = malloc(h);
Also, you should add the null byte at the end. Remember, the strings in C are null-ended.
h = strlen(a) + strlen(b) + 1;
and at the end:
c[h - 1] = '\0';
The signature of cat should be char *cat(char *a, char *b);
You will get an error of
expected constant expression
for the code line char c[h];. Instead you should be using malloc to allocate any dynamic memory at run-time like::
char* c ;
c = malloc( h + 1 ) ; // +1 for the terminating null char
// do stuff
free( c ) ;
Your corrected code::
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include <stdlib.h>
char* cat(char *a, char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b), j;
char *c;
c = malloc( h+1 ) ;
for(i;i<strlen(a);++i) {
c[i] = *(a+i);
}
j = 0 ;
for(j;j<strlen(b);++j) {
c[i] = *(b+cont);
i++ ;
cont++;
}
c[i] = 0 ;
return c;
}
int main() {
char A[1000],B[1000];
char * a ;
printf("Inserisci la stringa 1: \n");
gets(A);
printf("Inserisci la stringa 2: \n");
gets(B);
a = cat(A,B) ;
printf("\nConcatenazione: %s", a);
free(a) ;
getch();
return 0;
}