I'm new to pointers and I can already see how confusing they can be.
I have tried to look this up in several threads and google but they don't quite return what I'm looking for maybe out of my inexperience.
I'm being passed an array of strings and I have to pass it again to another function however I'm extremely confused on how to do this and don't know what * or & to use or where.
My code:
#include <stdlib.h>
#include <stdio.h>
char *ft_strcat(char *dest, char *src)
{
unsigned int c;
unsigned int count;
count = 0;
while (dest[count] != 0)
{
count++;
}
c = 0;
while (src[c] != '\0')
{
dest[c + count] = src[c];
c++;
}
dest[c + count] = 0;
return (dest);
}
int size_str(char *str)
{
int c;
c = 0;
while (str[c] != '\0')
{
c++;
}
return (c - 1);
}
int size_all(int size, char *strs[], char *sep)
{
int i;
int counter;
i = 0;
counter = 0;
counter += size_str(sep) * (size - 1);
while (i < size)
{
counter += size_str(strs[i]);
i++;
}
return (counter);
}
char *ft_strjoin(int size, char **strs, char *sep)
{
int i;
char *str;
str = malloc(sizeof(char) * size_all(size, strs, sep));
str = strs[0];
i = 1;
while (i < size)
{
str = ft_strcat(str, strs[i]);
}
return (str);
}
int main(void)
{
char *sep = " ";
char a1[] = "Batata";
char a2[] = "frita";
char a3[] = "\'e";
char a4[] = "melhor";
char a5[] = "que";
char a6[] = "Banana";
char *strs[] = {a1, a2, a3, a4, a5, a6};
char *final = ft_strjoin(6, strs, sep);
printf("%s", final);
}
I thought that size all would have to have an extra dereference operator on the declaration of the function and an reference operator when I call it, but this works just fine. Am I doing something wrong or am I just misunderstanding how pointers work? Don't I have to add an extra * each time I pass it?
Finally why doesn't while (src[c] != '\0') work?
In size_str:
There's nothing wrong with while (src[c] != '\0'), but return (c - 1); is causing an off-by-one error with your string lengths. The NUL byte wasn't counted in the loop, there's no need to subtract 1.
In ft_strcat:
The first loop is repeating work that could be handled by a call to size_str.
In ft_strjoin:
str = malloc(sizeof(char) * sizeall(size, strs, sep)));
sizeof (char) is uneccessary, as it is always 1. You need an additional 1 byte added to the length passed to malloc to make room for the NUL byte in your final string.
Remember that pointers are values too. str = strs[0]; assigns the pointer held in strs[0] to the the variable str. It does not copy the contents of strs[0]. You are overwriting the value returned by malloc with a pointer to a different piece of memory.
Instead, given this set of functions, initialize the memory returned by malloc to be the empty string, by setting the first byte to NUL, and use ft_strcat to concatenate the first string.
There's no need to continually reassign the result of ft_strcat, as you are already altering str, and the return value will never change.
A complete example. One must not forget to free the resulting string when it is no longer needed.
#include <stdlib.h>
#include <stdio.h>
int size_str(char *str)
{
int i = 0;
while (str[i])
i++;
return i;
}
char *ft_strcat(char *dest, char *src)
{
int i = 0,
length = size_str(dest);
do
dest[length++] = src[i];
while (src[i++]);
return dest;
}
int size_all(int size, char **strs, char *sep)
{
int total_length = size_str(sep) * (size - 1);
for (int i = 0; i < size; i++)
total_length += size_str(strs[i]);
return total_length;
}
char *ft_strjoin(int size, char **strs, char *sep)
{
char *result = malloc(1 + size_all(size, strs, sep));
result[0] = '\0';
ft_strcat(result, strs[0]);
for (int i = 1; i < size; i++) {
ft_strcat(result, sep);
ft_strcat(result, strs[i]);
}
return result;
}
int main(void)
{
char *sep = " ";
char a1[] = "Batata";
char a2[] = "frita";
char a3[] = "\'e";
char a4[] = "melhor";
char a5[] = "que";
char a6[] = "Banana";
char *strs[] = {a1, a2, a3, a4, a5, a6};
char *final = ft_strjoin(6, strs, sep);
printf("%s\n", final);
free(final);
}
Output:
Batata frita 'e melhor que Banana
I have worked lately about this problematic, string joint. I noticed that you forgot to add an if condition where the size would be 0. Moreover, the while loop need an iteration, which means that it will give you an infinite loop.
You can find as follows some adjustment to your code:
int i;
char *str;
int j;
int k;
i = 0;
k = 0;
str = (char *)malloc(sizeof(char) * sizeall(size, strs, sep) + 1));
if (size == 0)
return (0);
while (i < size)
{
j = 0;
while (strs[i][j])
str[k++] = strs[i][j++];
j = 0;
if (i < size - 1)
while (sep[j])
str[k++] = sep[j++];
i++;
}
str[k] = '\0';
return (str);
Feel free to ask me if there is something you did not understand, and good luck.
I want to chain 2 strings in C. The function I use called concat()
First I defined something like this and it worked
char* concat(const char *s1, const char *s2)
{
char* result = malloc (15);
int lengh1 = simple_strlen (s1);
int lengh2 = simple_strlen (s2);
int i=0,j;
for ( i = 0 ;i < lengh1;i++){
if (i!=lengh1-1)
result[i]=s1[i];
else{
result[i]=s1[i];
for ( j=i+1 ; j< lengh1+lengh2;j++){
result[j] = s2[j-i-1];
}
}
}
return result;
}
But then I was asked to do it without malloc() so I defined something like this:
char* concat( char *result, const char *s2)
{
int lengh1 = simple_strlen (result);
int lengh2 = simple_strlen (s2);
int i=0;
for ( i = 0 ;i < lengh2;i++){
result[i+lengh1]=s2[i];
}
return result;
}
but it has segmentation fault
example:
int main(int argc , char* argv[], char* envp[])
{
printf(concat( "hello", "world"));/*output expected "helloworld"*/
return 0;
}
There are multiple problems in your code:
in the malloc version, the space allocated for the destination string is hard coded at 15 instead of computing it as lengh1 + lengh2 + 1, enough space for both strings and the trailing null byte.
you do not set the null terminator at the end of the destination string in both versions.
in your version without malloc, you must provide a large enough array as the destination for concat(). A string constant cannot be modified. A simple solution is to pass the destination buffer and the source strings as separate arguments.
Here are modified versions:
char *concat(const char *s1, const char *s2) {
int length1 = simple_strlen(s1);
int length2 = simple_strlen(s2);
char *result = malloc(length1 + length2 + 1);
int i, j;
for (i = 0; i < length1; i++) {
result[i] = s1[i];
}
for (i = 0; i < length2; i++) {
result[length1 + i] = s2[1];
}
result[length1 + length2] = '\0';
return result;
}
Without malloc():
#include <string.h>
char *concat(char *dest, const char *s1, const char *s2) {
char *p = dest;
while (*s1)
*p++ = *s1++;
while (*s2)
*p++ = *s2++;
*p = '\0';
return dest;
}
int main() {
char buf[100];
/* output expected "helloworld" */
printf("%s\n", concat(buf, "hello", "world"));
return 0;
}
As mentioned by the prior commenters, you need to allocate memory somewhere to store the concatenated string. If you are not allowed to allocate on the heap via malloc, then you can do something like this:
#include "stdafx.h"
# include <string.h>
char* concat( char * result , const char *s1, const char *s2)
{
int lengh1 = strlen(s1);
int lengh2 = strlen(s2);
int i = 0;
for (i = 0; i < lengh1; i++) {
result[i] = s1[i];
}
for (i = 0; i < lengh2; i++) {
result[i+ lengh1] = s2[i];
}
return result;
}
int main()
{
char mybuffer[100];
memset(mybuffer, 0, sizeof(mybuffer));
printf(concat( mybuffer,"hello", "world"));/*output expected "helloworld"*/
return 0;
}
for exemple i need to invers "Paris" to "siraP"...
My main:
int main(void)
{
char w1[] = "Paris";
ReverseWord(w1);
printf("The new word is: %s",w1);
return0;
}
and my function:
void ReverseWord(char *Str)
{
int counter=0;
for(int i=0; *(Str+i)!='\0'; i++)
counter++;
int length = counter-1;
char temp[length];
for(int j=0; temp[j]=='\0'; j++)
temp[j]=Str[length-j];
}
Now I have my renverse word in temp[].
I need to put it in my pointer *Str.
How can I do it??
Thanks
If you want use temp must then your function like this
void ReverseWord(char *Str)
{
int i,j;
if(str)
{
int length=strlen(Str);
char temp[length+1];
for( j=0; j<length; j++)
temp[j]=Str[length-1-j];
temp[j]='\0';
strcpy(Str,temp);
}
}
Without using temp as follows
void ReverseWord(char *Str)
{
int end= strlen(Str)-1;
int start = 0;
while( start<end )
{
Str[start] ^= Str[end];
Str[end] ^= Str[start];
Str[start]^= Str[end];
++start;
--end;
}
}
void ReverseWord(char *Str)
{
size_t len;
char temp, *end;
len = strlen(Str);
if (len < 2)
return;
end = Str + len - 1;
while (end > Str)
{
temp = *end;
*end-- = *Str;
*Str++ = temp;
}
}
One more option, this time with dangerous malloc(3).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *rev(char s[]) {
char *buf = (char *)malloc(sizeof(char) * strlen(s));
int i, j;
if(buf != NULL)
for(i = 0, j = strlen(s) - 1; j >= 0; i++, j--)
buf[i] = s[j];
return buf;
}
int main(int argc, char **argv) {
printf("%s\n", rev(argv[1]));
return 0;
}
Run with "foo bar foobar baz" and get zab raboof rab oof back:
~/tmp$ ./a.out "foo bar foobar baz"
zab raboof rab oof
Here I think you can study two algorithms:
C string length calculate: the end of the c string is '\0'
How to reverse a c string in place
And if you need to test the code, you should alloc testing strings in heap or strack. If you write a literal string, you may meet a bus error because of the literal string being saved in text-area which is a read only memory.
And the following is the demo:
#include <stdio.h>
#include <stdlib.h>
void reverse_string(char* str)
{
size_t len;
char tmp, *s;
//Get the length of string, in C the last char of one string is \0
for(s=str;*s;++s) ;
len = s - str;
//Here we use the algorithm for reverse the char inplace.
//We only need a char tmp place for swap each char
s = str + len - 1;
while(s>str){
tmp = *s;
*s = *str;
*str = tmp;
s--;
str++;
}
}
int main()
{
char* a = "abcd";
//Here "abcd" will be saved in READ Only Memory. If you test code, you will get a bus error.
char* b = (char*)calloc(1,10);
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
a = "abcde";
strcpy(b,a);
reverse_string(b);
printf("%s\n",b);
}
you can do it simply by following code
for(int k=0;k<strlen(temp);k++)
{
Str[k]=temp[k];
}
I wanted to implement a reverse function for a null-terminated char* string (null-terminated char string, is that redundant?) and came up with the following solution.
The final swap swap(&tmp, &str) in the reverse function does not have any effect. What's the reason, how is it done probably?
Remark: I have already reimplemented the reverse function by using only the string itself, a temporary char and indices only, but I am so interested in why this does not work. What haven't I considered in this pointer matter?
#include <stdlib.h>
#include <stdio.h>
int strlen(char* str)
{
int len = 0;
char* ptr = str;
while (ptr[0] != '\0')
{
len++;
ptr++;
}
return len;
}
void swap(char **a, char **b)
{
char* c = *a;
*a = *b;
*b = c;
}
void reverse(char* str)
{
int len = strlen(str);
char* tmp = malloc(sizeof(char) * (len + 1));
int i;
for (i = 0; i < len; i++)
{
tmp[i] = str[len - 1 - i];
}
tmp[len] = '\0';
// printf(tmp); => "wolfrevOkcatS olleH"
swap(&tmp, &str);
}
int main(int argc, char** argv)
{
char* str = "Hello Stackoverflow\0";
reverse(str);
printf("%s", str);
return 0;
}
You can just do an in place reverse, and you won't need that pointer swap you're doing:
void reverse(char* str, int len)
{
int i;
for (i = 0; i < len; i++)
{
char tmp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = tmp;
}
}
To answer your question, you need to pass a char** to your reverse function, because you're changing what it will point to, and pointers are copied by value, so if you want to reflect the change of pointee you need a double pointer.
How do I remove a character from a string?
If I have the string "abcdef" and I want to remove "b" how do I do that?
Removing the first character is easy with this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[] = "abcdef";
char word2[10];
strcpy(word2, &word[1]);
printf("%s\n", word2);
return 0;
}
and
strncpy(word2, word, strlen(word) - 1);
will give me the string without the last character, but I still didn't figure out how to remove a char in the middle of a string.
memmove can handle overlapping areas, I would try something like that (not tested, maybe +-1 issue)
char word[] = "abcdef";
int idxToDel = 2;
memmove(&word[idxToDel], &word[idxToDel + 1], strlen(word) - idxToDel);
Before: "abcdef"
After: "abdef"
Try this :
void removeChar(char *str, char garbage) {
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != garbage) dst++;
}
*dst = '\0';
}
Test program:
int main(void) {
char* str = malloc(strlen("abcdef")+1);
strcpy(str, "abcdef");
removeChar(str, 'b');
printf("%s", str);
free(str);
return 0;
}
Result:
>>acdef
My way to remove all specified chars:
void RemoveChars(char *s, char c)
{
int writer = 0, reader = 0;
while (s[reader])
{
if (s[reader]!=c)
{
s[writer++] = s[reader];
}
reader++;
}
s[writer]=0;
}
char a[]="string";
int toBeRemoved=2;
memmove(&a[toBeRemoved],&a[toBeRemoved+1],strlen(a)-toBeRemoved);
puts(a);
Try this . memmove will overlap it.
Tested.
Really surprised this hasn't been posted before.
strcpy(&str[idx_to_delete], &str[idx_to_delete + 1]);
Pretty efficient and simple. strcpy uses memmove on most implementations.
int chartoremove = 1;
strncpy(word2, word, chartoremove);
strncpy(((char*)word2)+chartoremove, ((char*)word)+chartoremove+1,
strlen(word)-1-chartoremove);
Ugly as hell
The following will extends the problem a bit by removing from the first string argument any character that occurs in the second string argument.
/*
* delete one character from a string
*/
static void
_strdelchr( char *s, size_t i, size_t *a, size_t *b)
{
size_t j;
if( *a == *b)
*a = i - 1;
else
for( j = *b + 1; j < i; j++)
s[++(*a)] = s[j];
*b = i;
}
/*
* delete all occurrences of characters in search from s
* returns nr. of deleted characters
*/
size_t
strdelstr( char *s, const char *search)
{
size_t l = strlen(s);
size_t n = strlen(search);
size_t i;
size_t a = 0;
size_t b = 0;
for( i = 0; i < l; i++)
if( memchr( search, s[i], n))
_strdelchr( s, i, &a, &b);
_strdelchr( s, l, &a, &b);
s[++a] = '\0';
return l - a;
}
This is an example of removing vowels from a string
#include <stdio.h>
#include <string.h>
void lower_str_and_remove_vowel(int sz, char str[])
{
for(int i = 0; i < sz; i++)
{
str[i] = tolower(str[i]);
if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u')
{
for(int j = i; j < sz; j++)
{
str[j] = str[j + 1];
}
sz--;
i--;
}
}
}
int main(void)
{
char str[101];
gets(str);
int sz = strlen(str);// size of string
lower_str_and_remove_vowel(sz, str);
puts(str);
}
Input:
tour
Output:
tr
Use strcat() to concatenate strings.
But strcat() doesn't allow overlapping so you'd need to create a new string to hold the output.
I tried with strncpy() and snprintf().
int ridx = 1;
strncpy(word2,word,ridx);
snprintf(word2+ridx,10-ridx,"%s",&word[ridx+1]);
Another solution, using memmove() along with index() and sizeof():
char buf[100] = "abcdef";
char remove = 'b';
char* c;
if ((c = index(buf, remove)) != NULL) {
size_t len_left = sizeof(buf) - (c+1-buf);
memmove(c, c+1, len_left);
}
buf[] now contains "acdef"
This might be one of the fastest ones, if you pass the index:
void removeChar(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '\0'; *src = *(src+1),++src) ;
*src = '\0';
}
This code will delete all characters that you enter from string
#include <stdio.h>
#include <string.h>
#define SIZE 1000
char *erase_c(char *p, int ch)
{
char *ptr;
while (ptr = strchr(p, ch))
strcpy(ptr, ptr + 1);
return p;
}
int main()
{
char str[SIZE];
int ch;
printf("Enter a string\n");
gets(str);
printf("Enter the character to delete\n");
ch = getchar();
erase_c(str, ch);
puts(str);
return 0;
}
input
a man, a plan, a canal Panama
output
A mn, pln, cnl, Pnm!
Edit : Updated the code zstring_remove_chr() according to the latest version of the library.
From a BSD licensed string processing library for C, called zString
https://github.com/fnoyanisi/zString
Function to remove a character
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
/* validate input */
if (!(str && bad))
return NULL;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
Exmaple Usage
char s[]="this is a trial string to test the function.";
char *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
void dele_char(char s[],char ch)
{
int i,j;
for(i=0;s[i]!='\0';i++)
{
if(s[i]==ch)
{
for(j=i;s[j]!='\0';j++)
s[j]=s[j+1];
i--;
}
}
}
int main()
{
char s[MAX],ch;
printf("Enter the string\n");
gets(s);
printf("Enter The char to be deleted\n");
scanf("%c",&ch);
dele_char(s,ch);
printf("After Deletion:= %s\n",s);
return 0;
}
#include <stdio.h>
#include <string.h>
int main(){
char ch[15],ch1[15];
int i;
gets(ch); // the original string
for (i=0;i<strlen(ch);i++){
while (ch[i]==ch[i+1]){
strncpy(ch1,ch,i+1); //ch1 contains all the characters up to and including x
ch1[i]='\0'; //removing x from ch1
strcpy(ch,&ch[i+1]); //(shrinking ch) removing all the characters up to and including x from ch
strcat(ch1,ch); //rejoining both parts
strcpy(ch,ch1); //just wanna stay classy
}
}
puts(ch);
}
Let's suppose that x is the "symbol" of the character you want to remove
,my idea was to divide the string into 2 parts:
1st part will countain all the characters from the index 0 till (and including) the target character x.
2nd part countains all the characters after x (not including x)
Now all you have to do is to rejoin both parts.
This is what you may be looking for while counter is the index.
#include <stdio.h>
int main(){
char str[20];
int i,counter;
gets(str);
scanf("%d", &counter);
for (i= counter+1; str[i]!='\0'; i++){
str[i-1]=str[i];
}
str[i-1]=0;
puts(str);
return 0;
}
I know that the question is very old, but I will leave my implementation here:
char *ft_strdelchr(const char *str,char c)
{
int i;
int j;
char *s;
char *newstr;
i = 0;
j = 0;
// cast to char* to be able to modify, bc the param is const
// you guys can remove this and change the param too
s = (char*)str;
// malloc the new string with the necessary length.
// obs: strcountchr returns int number of c(haracters) inside s(tring)
if (!(newstr = malloc(ft_strlen(s) - ft_strcountchr(s, c) + 1 * sizeof(char))))
return (NULL);
while (s[i])
{
if (s[i] != c)
{
newstr[j] = s[i];
j++;
}
i++;
}
return (newstr);
}
just throw to a new string the characters that are not equal to the character you want to remove.
Following should do it :
#include <stdio.h>
#include <string.h>
int main (int argc, char const* argv[])
{
char word[] = "abcde";
int i;
int len = strlen(word);
int rem = 1;
/* remove rem'th char from word */
for (i = rem; i < len - 1; i++) word[i] = word[i + 1];
if (i < len) word[i] = '\0';
printf("%s\n", word);
return 0;
}
This is a pretty basic way to do it:
void remove_character(char *string, int index) {
for (index; *(string + index) != '\0'; index++) {
*(string + index) = *(string + index + 1);
}
}
I am amazed none of the answers posted in more than 10 years mention this:
copying the string without the last byte with strncpy(word2, word, strlen(word)-1); is incorrect: the null terminator will not be set at word2[strlen(word) - 1]. Furthermore, this code would cause a crash if word is an empty string (which does not have a last character).
The function strncpy is not a good candidate for this problem. As a matter of fact, it is not recommended for any problem because it does not set a null terminator in the destination array if the n argument is less of equal to the source string length.
Here is a simple generic solution to copy a string while removing the character at offset pos, that does not assume pos to be a valid offset inside the string:
#include <stddef.h>
char *removeat_copy(char *dest, const char *src, size_t pos) {
size_t i;
for (i = 0; i < pos && src[i] != '\0'; i++) {
dest[i] = src[i];
}
for (; src[i] != '\0'; i++) {
dest[i] = src[i + 1];
}
dest[i] = '\0';
return dest;
}
This function also works if dest == src, but for removing the character in place in a modifiable string, use this more efficient version:
#include <stddef.h>
char *removeat_in_place(char *str, size_t pos) {
size_t i;
for (i = 0; i < pos && str[i] != '\0'; i++)
continue;
for (; str[i] != '\0'; i++)
str[i] = str[i + 1];
return str;
}
Finally, here are solutions using library functions:
#include <string.h>
char *removeat_copy(char *dest, const char *src, size_t pos) {
size_t len = strlen(src);
if (pos < len) {
memmove(dest, src, pos);
memmove(dest + pos, src + pos + 1, len - pos);
} else {
memmove(dest, src, len + 1);
}
return dest;
}
char *removeat_in_place(char *str, size_t pos) {
size_t len = strlen(str);
if (pos < len) {
memmove(str + pos, str + pos + 1, len - pos);
}
return str;
}
A convenient, simple and fast way to get rid of \0 is to copy the string without the last char (\0) with the help of strncpy instead of strcpy:
strncpy(newStrg,oldStrg,(strlen(oldStrg)-1));