How to copy string without allocating memory - C - c

I just started in C and this is a beginner question. But is there any way to copy a string without allocating memory beforehand?
I want to reproduce the strcopy function inbuilt in C with the same structure (char *strcpy(char *src, char *dest);). I got it to work with declaring the char pointer in the function itself and then returning it. It works also with the original structure as strcpy if I allocate the memory beforehand.
#include <stdlib.h>
char *strcopy(char *src, char *dest)
{
int i = 0;
while (src[i] != '\0')
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (dest);
}
int str_size(char *str)
{
int i = 0;
while (str[i] != '\0')
i++;
return (i);
}
int main(int argc, char **argv)
{
char *src = argv[1];
char *dest = (char*)malloc(str_size(src));
dest = strcopy(src, dest);
return (0);
}
So is it somehow possible to copy a string without allocating memory beforehand and without changing my function-head?

If you want to avoid dynamic allocation, use static allocation:
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1024
char *strcopy(char *src, char *dest)
{
int i = 0;
while (src[i] != '\0')
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (dest);
}
int str_size(char *str)
{
int i = 0;
while (str[i] != '\0')
i++;
return (i);
}
int main(int argc, char **argv)
{
char *src = argv[1];
char dest[BUFFER_SIZE];
if(strlen(src) >= BUFFER_SIZE){
return -1;
}
else{
dest = strcopy(src, dest);
}
return 0;
}

Related

Argv doesnt work with char pointer on terminal

I want to write a program that when I am on terminal and write prog.exe -u word will transform word to uppercase otherwise skip the process. but when I compile the code below, I get nothing on screen and I couldn't figure out why the error occurs.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char u[] = "-u";
void upper(const char *src, char *dest);
int main(int argc, char const *argv[]) {
if (argc < 3) {
printf("Input at least 3 argument!\n");
} else
if (!(strcmp(argv[1], u))) {
char *output;
upper(argv[2], output);
printf("%s\n", output);
} else {
printf("No option\n");
}
return 0;
}
void upper(const char *src, char *dest) {
while (*src) {
if (*src >= 97 && *src <= 122) {
*dest = *src - 32;
} else {
*dest = *src;
}
src++;
dest++;
}
*dest = *src;
}
The pointer output declared like
char * output;
is uninitialized and has an indeterminate value.
So using it in the function upper invokes undefined behavior.
Instead of the pointer you should use a character array large enough to store the passed string to the function.
If the compiler supports variable length arrays then you can write
char output[ strlen( argv[2] ) + 1 ];
And this if statement
else if( strcmp(argv[1],u) == 0 ){
will be more readable than this if statement
else if(!(strcmp(argv[1],u))){
Within the function it will be at least better to use character symbols 'a' and 'z' instead of the magic numbers 97 and 122 in the if statement
if(*src >= 97 && *src <= 122){
*dest = *src - 32;
}
Though it is even better to use standard function islower and toupper declared in the header <ctype.h>.
The function can be declared and defined the following way
#include <ctype.h>
//...
char * upper( char *dest, const char *src )
{
char *result = dest;
do
{
if ( islower( ( unsigned char )*src ) )
{
*dest++ = toupper( ( unsigned char )*src );
}
else
{
*dest++ = *src;
}
} while ( *src++ );
return result;
}
void upper(const char *src, char *dest) {
char *tmp = dest; // hold pointer
while(*src) {
*dest = (*src >= 97 && *src <= 122) ? *src - 32 : src;
++src; ++dest;
}
*dest = '\0'; // end of string
dest = tmp;
}
The program has undefined behavior because you attempt to store the converted string to an uninitialized pointer output.
Note that using hard coded constants such as 97, 122 and 32 is both confusing and non portable to non-ASCII environments. You should use the macros and functions from <ctype.h> for readability and portability.
You could simply modify the argument string in place this way:
#include <ctype.h>
#include <stdio.h>
void upper(char *str);
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Input at least 3 arguments!\n");
} else
if (!(strcmp(argv[1], "-u"))) {
printf("%s\n", upper(argv[2]));
} else {
printf("No option\n");
}
return 0;
}
char *upper(char *str) {
for (char *p = str; *p; p++) {
*p = toupper((unsigned char)*p);
}
return str;
}

How we can replace space in string with some word(ex:- 'XXX') without using string library in C?

I am trying to write a program without using string library in C which can replace the spaces in string with 'XXX'.
I have done this much but did not getting idea after this.
char buff[100];
int i;
char *my_func(char *arr){
for( i=0;arr[i]!='\0';i++){
if(arr[i]==' '){
buff[i]='X';
break;
}
else{
buff[i]=arr[i];
}
}
buff[i+1]='X';
buff[i+2]='X';
return buff;
}
int main()
{
char arr[]="This is my string";
my_func(arr);
printf("%s",buff);
return 0;
}
You need to track the indices for your source and destination buffers separately, since encountering a space in the source string will cause the resulting string to grow disproportionately.
Those character assignments should be inside inside the loop.
Don't forget to NUL terminate your destination buffer.
Avoid global variables when possible.
#include <stdio.h>
char *replace(char *dest, char *src) {
size_t j = 0;
for (size_t i = 0; src[i]; i++) {
if (src[i] == ' ') {
dest[j++] = 'X';
dest[j++] = 'X';
dest[j++] = 'X';
} else
dest[j++] = src[i];
}
dest[j] = '\0';
return dest;
}
int main(void) {
char arr[] = "This is my string.";
char buffer[256];
replace(buffer, arr);
printf("[%s] --> [%s]\n", arr, buffer);
}
Output:
[This is my string.] --> [ThisXXXisXXXmyXXXstring.]

Using prototype replace one character with another in c

#include "stdafx.h"
#include "stdio.h"
void repl(char *string, char oldc, char newc);
char text[60] = { "I am going to replace the character a with the character i";
char newc = 'b';
char oldc = 'a';
int main()
{
void repl(char *string, char oldc, char newc);
return 0;
}
void repl(char *string, char oldc, char newc)
{
int i = 0;
for (i = 0; i < *string; i++)
{
if (*(string + i) == oldc)
{
*(string + i) == newc;
}
}
printf("%s", string);
}
I am trying to replace the character a with the character b.
I know how to do this without using pointers but I am not too sure when it comes to pointers.
The prototype I was given was:
void repl(char *string, char oldc, char newc);
This does what you're after. I seriously recommend reading up on some basic C programming topics, such as calling functions and declaring char arrays. In the meantime...
#include "stdafx.h"
#include "stdio.h"
void repl(char *string, char oldc, char newc);
char text[60] = "I am going to replace the character a with the character i";
char newc = 'i';
char oldc = 'a';
int main()
{
repl(text, oldc, newc);
return 0;
}
void repl(char *string, char oldc, char newc)
{
int i = 0;
for (i = 0; string[i]; i++)
{
if (string[i] == oldc)
{
string[i] = newc;
}
}
printf("%s", string);
}

Error in reversing string

I know this question is extremely common and the solution is well-known. But for a long time, I am getting an error I cannot figure out. I am trying to reverse a string in C. My code is given below:
#include <stdio.h>
char *reverse(char *);
int main(void) {
char str[] = "Hello";
char *rev;
rev = reverse(str);
printf("The reversed string is %s", rev);
return 0;
}
char *reverse(char *str){
char *end = str;
char tmp;
if(str){
while(*end){
++end;
}
--end;
while(str < end){
tmp = *str;
*str++ = *end;
*end-- = tmp;
}
}
return str;
}
As result, I am getting "leH", not "olleH". Can anyone point out why?
The pointer str you return in reverse() does not point to the beginning of the string, but somewhere in the middle at the end of the loop.
Another problem with your function is in case you pass an empty string: end is decremented from the end of the string and points outside the string. This invokes undefined behaviour.
You should use 2 temporary pointers to perform the task:
char *reverse(char *str) {
if (str && *str) {
char *p = str;
char *end = p + strlen(p) - 1;
while (p < end) {
char tmp = *p;
*p++ = *end;
*end-- = tmp;
}
}
return str;
}
Or if you prefer to use index variables:
char *reverse(char *str) {
if (str && *str) {
for (size_t i = 0, j = strlen(str); i < --j; i++) {
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
return str;
}
Because you return the incremented pointer, use another pointer or index notation and it will work, like this
char *reverse(char *str)
{
char *end;
char tmp;
int i;
end = str;
if ((str == NULL) || (*str == '\0'))
return str;
while (*end != 0)
++end;
--end;
i = 0;
while (str + i < end)
{
tmp = str[i];
str[i++] = *end;
*end-- = tmp;
}
return str;
}
When you return str, it's no longer pointing at the beginning of the string.
Another way of achieving reversing string is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse(const char *);
int main(void){
char *s = "hello world";
char *s_rev = reverse(s);
printf("%s => %s", s, s_rev);
free(s_rev);
return 0;
}
char *reverse(const char *s){
char *s_new = strdup(s);
char *s_begptr = &s[0];
char *s_endptr = &s[strlen(s) - 1];
char *ptr = NULL;
for (ptr = s_endptr; ptr >= s_begptr; ptr--, s_new++){
*s_new = *ptr;
}
*s_new = '\0';
s_new -= strlen(s);
return s_new;
}
Notice we are not using any temporary variables to store the value, rather, using both start and end pointers of the same string and using the loop to work backwards from the end of string in reverse.

How to delete special char in C?

There is a string
char *message = "hello#world#####.......";
How to delete all the "#" and return "helloworld" ?
In Ruby I can use gsub to deal with it
In C, you have to do it yourself. For example:
#include <string.h>
char *remove_all(const char *source, char c)
{
char *result = (char *) malloc(strlen(source) + 1);
char *r = result;
while (*source != '\0')
{
if (*source != c)
*r++ = *source;
source++;
}
*r = '\0';
return result;
}
Note that in that implementation, the caller would have to free the result string.
I believe there is a better algorithm to do this....no freeing is necessary - it's in-place.
char *remove_all(char *string, char c)
{
int idx = 0;
char *beg = string;
while(*string) {
if (*string != c)
beg[idx++] = *string;
++string;
}
beg[idx] = 0;
return beg;
}

Resources