c remove the first character of an array - c

I have a string:
str1 = "abcabcabc";
How can I remove the first character? I would like the end result to be:
str1 = "bcabcabc";

If you have a character pointer to a string like:
char *s = "This is my string";
then you can just do s++.
If you have a character array, your best bet may be to have a pointer to that array as well:
char s[] = "This is my string";
char *ps = s;
then you can do ps++ and make sure you use ps rather than s.
If you don't want to have a separate pointer to your array then you can use memmove to copy the data:
memmove (s, s+1, strlen (s+1) + 1); // or just strlen (s)
though none of those will work for an initially empty string so you'll have to check that first. Also keep in mind it's not advisable to attempt modifying string literals in this way (or any way, really) since it's undefined as to whether that's allowed.
Another solution is to simply code up a loop:
for (char *ps = s; *ps != '\0'; ps++)
*ps = *(ps+1);
*ps = '\0';
This will work for all strings, empty or otherwise.

Pointer tricks (zero-cost):
char* s = "abcd";
char* substr = s + 1;
// substr == "bcd"
Or:
char s[] = "abcd";
char* substr = s + 1;
// substr == "bcd"
In-place via memmove:
char s[] = "abcd";
char* substr = s + 1;
memmove(s, substr, strlen(substr) + 1);
// s == "bcd"
Notice that we must use char[] rather than char*, which would refer to read-only memory, as described here. Furthermore, one should not use strcpy in-place because the src and dest must not overlap for strcpy.
Into a new string via strcpy:
char* src = "abcd";
char* substr = src + 1;
char dest[strlen(substr) + 1];
strcpy(dest, substr);
// dest == "bcd"
Into a new string via C++'s std::string::substr:
std::string src = "abcd";
std::string dest = src.substr(1);
// dest == "bcd"
Into a new string via C++'s std::copy:
std::string src = "abcd";
std::string dest;
std::copy(src.begin() + 1, src.end(), std::back_inserter(dest));
// dest == "bcd"
There's a couple dozen other ways (particularly when including C++), but I'll stop here. :)

If you really meant to say
char str1 [] = "abcabcabc";
Then the easiest thing is
str1 = &str1[1];
If you want to modify the actual data, then you have to just move everything up one position. You can use a loop for that or memmove(). A recursive function is overkill.
If you really meant C++ and you're using the string object then you can use
str1 = str1.substr(1);

Here is one way to do it:
int index = 0; //index to cull
memmove( &word[ index ] , &word[ index +1], strlen( word ) - index) ;

Well as far as i know if you are worried about memory allocation you have to copy (str1+1) into a new string that you personally allocate memory for, then free the first pointer.
The really simple way to do it would be to just increment str1 with str1++; That would make it point one character farther than it used to and give you the desired result with just a line of code.

#include <stdio.h>
#include <conio.h>
main(){
char a[10];
int i;
gets(a);
for (i = 0; a[i] != '\0'; i++) {
a[i] = a[i + 1];
}
printf("\n");
puts(a);
getch();
}

#include <stdio.h>
int main() {
char a[15] = "!Hello world!";
sprintf(a,"%s",a+1);
printf("%s",a);
}

Related

How to remove a single character from the beginning of a character array? [duplicate]

I have a string:
str1 = "abcabcabc";
How can I remove the first character? I would like the end result to be:
str1 = "bcabcabc";
If you have a character pointer to a string like:
char *s = "This is my string";
then you can just do s++.
If you have a character array, your best bet may be to have a pointer to that array as well:
char s[] = "This is my string";
char *ps = s;
then you can do ps++ and make sure you use ps rather than s.
If you don't want to have a separate pointer to your array then you can use memmove to copy the data:
memmove (s, s+1, strlen (s+1) + 1); // or just strlen (s)
though none of those will work for an initially empty string so you'll have to check that first. Also keep in mind it's not advisable to attempt modifying string literals in this way (or any way, really) since it's undefined as to whether that's allowed.
Another solution is to simply code up a loop:
for (char *ps = s; *ps != '\0'; ps++)
*ps = *(ps+1);
*ps = '\0';
This will work for all strings, empty or otherwise.
Pointer tricks (zero-cost):
char* s = "abcd";
char* substr = s + 1;
// substr == "bcd"
Or:
char s[] = "abcd";
char* substr = s + 1;
// substr == "bcd"
In-place via memmove:
char s[] = "abcd";
char* substr = s + 1;
memmove(s, substr, strlen(substr) + 1);
// s == "bcd"
Notice that we must use char[] rather than char*, which would refer to read-only memory, as described here. Furthermore, one should not use strcpy in-place because the src and dest must not overlap for strcpy.
Into a new string via strcpy:
char* src = "abcd";
char* substr = src + 1;
char dest[strlen(substr) + 1];
strcpy(dest, substr);
// dest == "bcd"
Into a new string via C++'s std::string::substr:
std::string src = "abcd";
std::string dest = src.substr(1);
// dest == "bcd"
Into a new string via C++'s std::copy:
std::string src = "abcd";
std::string dest;
std::copy(src.begin() + 1, src.end(), std::back_inserter(dest));
// dest == "bcd"
There's a couple dozen other ways (particularly when including C++), but I'll stop here. :)
If you really meant to say
char str1 [] = "abcabcabc";
Then the easiest thing is
str1 = &str1[1];
If you want to modify the actual data, then you have to just move everything up one position. You can use a loop for that or memmove(). A recursive function is overkill.
If you really meant C++ and you're using the string object then you can use
str1 = str1.substr(1);
Here is one way to do it:
int index = 0; //index to cull
memmove( &word[ index ] , &word[ index +1], strlen( word ) - index) ;
Well as far as i know if you are worried about memory allocation you have to copy (str1+1) into a new string that you personally allocate memory for, then free the first pointer.
The really simple way to do it would be to just increment str1 with str1++; That would make it point one character farther than it used to and give you the desired result with just a line of code.
#include <stdio.h>
#include <conio.h>
main(){
char a[10];
int i;
gets(a);
for (i = 0; a[i] != '\0'; i++) {
a[i] = a[i + 1];
}
printf("\n");
puts(a);
getch();
}
#include <stdio.h>
int main() {
char a[15] = "!Hello world!";
sprintf(a,"%s",a+1);
printf("%s",a);
}

Array is being modified

I'm trying to replicate the function strcat. The problem is that my array src is being modified even though I'm just use it to copy.
#include <stdio.h>
char *ft_strcat(char *dest, char *src)
{
int i = 0;
int c = 0;
while (dest[i] != '\0')
i++;
while (src[c] != '\0')
{
dest[i] = src[c];
c++;
i++;
}
dest[i] = '\0';
return dest;
}
int main(void)
{
char src[] = "_And Good Bye";
char dest[] = "Hello World";
char *ptr;
printf("\nString 1: %s\nString 2: %s\n", src, dest);
ptr = ft_strcat(dest, src);
printf("\nAfter strcat function.\nString 1: %s\nString 2: %s\n", src, dest);
return 0;
}
Output:
String 1: _And Good Bye
String 2: Hello World
After strcat function.
String 1: And Good Bye
String 2: Hello World_And Good Bye
After I run ft_strcat(dest, src), my char src looses the character, "_". I don't understand why if I only use it to be copied.
I expect that src is not modified.
dest has exactly enough memory to store "Hello World". When you append src to it you're overwriting adjacent memory. That adjacent memory happens to contain src. There's no guarantee that it will, but stack memory is often allocated this way.
For example, if I print out the memory address of src and dest I see...
printf("src: %p\ndest: %p\n", &src, &dest);
src: 0x7ffeea74e31a
dest: 0x7ffeea74e30e
The memory looks like this.
001111111111111111
ef0123456789abcdef
Hello World0_And Good Bye0
^ ^
dest src
When you concatenate src onto dest you overwrite the adjacent memory resulting in...
001111111111111111
ef0123456789abcdef
Hello World_And Good Bye00
^ ^
dest src
You need to allocate dest to have enough space.
// "Hello World" + "_And Good Bye" + null byte
char dest[25] = "Hello World";
In a real program you'd allocate dest as dynamic memory and reallocate it to have enough space.
char *dest = malloc(12);
strcpy(dest, "Hello world");
dest = realloc(dest, strlen(dest) + strlen(src) + 1);
The actual type of a string literal in C is char [N], wherein N is the minimum amount of space required to store the characters of the string, including the null terminating byte.
In the case where you use a string literal to initialize an array of an unknown size (char foo[] = ...), the resulting array is given the same typing as the string literal.
So in,
char src[] = "_And Good Bye";
char dest[] = "Hello World";
src will have the type char [14], and dest the type char [12].
Knowing this, it becomes obvious that dest does not have enough room to append the contents of src (zero excess memory, in fact). Care must always be taken to guarantee that there is enough room, otherwise you risk Undefined Behavior.
At a minimum, you would need char dest[25], though it may be prudent to drastically oversize your destination buffer.
char dest[512] = "Hello World";
const char *src = "_And Good Bye";
Initializing dest in this way fills the rest of its memory with zeroes.
For starters the function should be declared at least like
char *ft_strcat(char *dest, const char *src);
because the source string is not changed within the function.
Within the function you are trying to append the source string to the end of the destination string but the array that contains the destination string has no enough memory to accommodate also the source string, See the declarations of the arrays
char src[] = "_And Good Bye";
char dest[] = "Hello World";
You need to enlarge the array dest.
For example you could write
char src[] = "_And Good Bye";
char dest[ 2 * sizeof( src )] = "Hello World";
Objects of the type int in general are unable to store all possible lengths of strings. For example the function strlen or the operator sizeof return values of the type size_t
In fact the declarations of the variables i and c
int i = 0;
int c = 0;
are redundant within the function.
The function can look the following way
char * ft_strcat( char *dest, const char *src )
{
char *p = dest;
while ( *p ) ++p;
while ( ( *p++ = *src++ ) != '\0' );
return dest;
}
Try to use Const modifier in source parameter. that's my first point.
char *strcat(char *destination, const char *source)

How can I predetermine the size of a malloc to concatenate an array of strings?

Implement the append function that has the prototype below. The function returns a string that represents the concatenation of all the strings present in an array of strings. For this problem, you can assume the end of the parameter array is marked by NULL. You need to allocate memory for the resulting string. You may not modify the array parameter.
char* append(char *data[]);
I don't understand how to determine the size to malloc the pointer.
First of all, to know the size of one string, you can use strlen from the library string.h. If you want to calculate the sum of all the sizes you can just use a loop and sum up all the strlens, and add 1 for the terminal NUL character, like this:
char* append(char *data[]) {
char **cur, *res;
size_t len = 0;
for (cur = data; *cur != NULL; *cur++)
len += strlen(*cur);
res = malloc(len + 1);
// Now you can concatenate the strings...
}
Oh, and don't forget to check that the pointer returned by malloc is valid (i.e. not NULL).
An approach that goes through the strings twice seems good.
The first pass counts the sum of the lengths:
size_t len = 0;
for (char** pstr = data; *pstr; pstr++)
len += strlen(*pstr);
The second pass concatenates all the strings:
char *str = malloc(len + 1);
str[0] = '\0';
for (char** pstr = data; *pstr; pstr++)
strcat(str, *pstr);
return str;
You can optimize the concatenation part by storing the end point of the last concatenation:
char *str = malloc(len + 1);
str[0] = '\0';
char *p = str;
for (char** pstr = data; *pstr; pstr++) {
strcat(p, *pstr);
p += strlen(*pstr);
}

Function to reverse a string in C - What if is a string literal?

I have coded the following function that will reverse a String in C:
void reverse(char *str) {
int length = strlen(str) - 1;
for (int i=0; i < length/2; i++) {
char tmp = str[i];
str[i] = str[length - i];
str[length - i] = tmp;
}
}
This works if I do this:
char a[]="Hello";
reverse(a);
But if I call it passing a string literal, such as:
char *a = "Hello";
It won't work.
So, how would I modify my function so that it can accept string literals and reverse them?
You can not do that, string literals are constants in C
Perhaps, you need to copy the string, much like you do it in your first example, where you initialize a char array using a string literal.
You better of copying string to some other temp string.
Use another char* to copy original string. Allocate sufficient memory.
Copy sources string to this one. Don't forget to null terminate it.
reverse..
Dont forget to free this memory after use.
char *a1 = "Hello";
char* copy_a1 = malloc(sizeof(char)*(strlen(a1)+1));
strncpy(copy_a1, a1, strlen(a1));
copy_a1[strlen(a1)] = '\0';
reverse(copy_a1);
//free memory used.
The problem is C history.
char *a = "Hello"; should be const char *a = "Hello";. But const came in after C was successful so char *a = "Hello"; was allowed to remain OK syntax.
Had code been const char *a = "Hello";, reverse(a); would generate a warning (or error).
To modify create something like:
char *reverse(char *dest, const char *src);

What is a safe way to join strings in C?

I need to construct a path to a file from two strings. I could use this (not tested, though):
/* DON'T USE THIS CODE! */
/* cmp means component */
char *path_cmp1 = "/Users/john/";
char *path_cmp2 = "foo/bar.txt";
unsigned len = strlen(path_cmp1);
char *path = path_cmp1;
for (int i = 0; i < strlen(path_cmp2); i++) {
path[len + i] = path_cmp2[i];
}
but this could lead to memory corruption I guess. Is there a better way to do this, or is there a function for this in the standard library?
#include <stdlib.h>
#include <string.h>
char *join(const char* s1, const char* s2)
{
char* result = malloc(strlen(s1) + strlen(s2) + 1);
if (result) // thanks #pmg
{
strcpy(result, s1);
strcat(result, s2);
}
return result;
}
This is simple enough to be written in place, especially when you have multiple strings to concatenate.
Note that these functions return their destination argument, so you can write
char* result = malloc(strlen(s1) + strlen(s2) + 1);
assert(result);
strcat(strcpy(result, s1), s2);
but this is less readable.
#include <stdio.h>
char *a = "hello ";
char *b = "goodbye";
char *joined;
asprintf(&joined, "%s%s", a, b)
There are several problems in this code:
1 - calling strlen on the for loop is a bad idea, it will calculate the string length every iteration, so it is better to call it once before the loop and keep the result in a variable.
2 - The same strlen problem applies to strlen(path_cmp1) inside the loop, call it before the loop and increments its size.
In the end, it is better to simple copy both strings and store those on a dynamic allocated string, like:
char *join_strings(const char* s1, const char* s2)
{
size_t lens1 = strlen(s1);
size_t lens2 = strlen(s2);
//plus 1 for \0
char *result = malloc(lens1 + lens2 + 1);
if(result)
{
memcpy(result, s1, lens1);
memcpy(result+lens1, s2, lens2+1);
}
//do not forget to call free when do not need it anymore
return result;
}
There are strcat and strncat for that.
char *path_cmp1 = "/Users/john/";
char *path_cmp2 = "foo/bar.txt";
int firstLength = strlen(path_cmp1);
int secondLength = strlen(path_cmp2);
char *both = malloc(firstLength+secondLength+1);
memcpy(both, path_cmp1, firstLength);
memcpy(both+firstLength, path_cmp2, secondLength+1);
// this +1 copyes the second string's null-terminator too.
create a new string with the length of both inputs and strcpy/strcat the inputs and don't forget the null terminator.
Use strcat. (You are right that your code will lead to memory corruption.)
How about strcat in string.h?
path is just a pointer to path_cmp1 and you are trying to access beyond the end of the array. Very occasionally this will work, but in the vast majority of cases you will cause memory corruption.
As others have pointed out use strcat to concatenate strings.

Resources