I was making a split function in C to use its return value in some programs. But when I checked its value using printf, I discovered that there are some errors but I was unable to fix them myself. I fixed most of the errors I could.
The code I wrote is:
#include <stdio.h>
#include <string.h>
char **split(char *token, char *delimiter, int *a[], int *size_of_a) {
int i = 0;
char **final_result;
char *str = strtok(token, delimiter);
while (str != NULL) {
*a[i] = strlen(str); //maybe one of the errors but I don't know how to fix it
//even after removing a[i] by backslash and changing it in loop and main, there is still no output received in main
getch();
for (int j = 0; j < *a[i]; j++) {
final_result[i][j] = str[j];
}
str = strtok(NULL, delimiter);
i++;
}
*size_of_a = i;
return final_result;
}
int main() {
char *parameter_1;
char *parameter_2;
int *size_1;
int size_2;
printf("Enter the token: ");
scanf("%s", ¶meter_1);
printf("\nEnter the delimiter: ");
scanf("%s", ¶meter_2);
char **result_2 = split(parameter_1, parameter_2, &size_1, &size_2);
printf("\nThe result is:");
for (int x = 0; x < size_2; x++) {
printf('\n');
for (int y = 0; y < size_1[x]; y++) {
printf("%c", result_2[x][y]);
}
}
getch();
return 0;
}
How can I fix the output error?
There are multiple problems in the code:
You do not allocate space for the array of pointers: final_result is uninitialized, storing anything via dereferencing it has undefined behavior, most likely a segmentation fault.
You should use strcpn() and strspn() to compute the number of tokens, allocate the array with or without an extra slot for a NULL terminator and perform a second phase splitting the tokens and storing the pointers to the array. You might want to store copies of the tokens to avoid modifying the original string that may be constant or go out of scope.
printf('\n'); is invalid: you must pass a string, not a character constant.
scanf("%s", ¶meter_1); also has undefined behavior: you pass the address of a pointer instead of a pointer to an array of char.
Here is a modified version:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
// define POSIX function strndup if not available
char *strndup(const char *s, size_t n) {
size_t len;
for (len = 0; len < n && s[len]; len++)
continue;
char *ptr = malloc(len + 1);
if (ptr) {
memcpy(ptr, s, len);
ptr[len] = '\0';
}
return ptr;
}
#endif
char **split(const char *str, const char *delimiters, int **a, int *size_of_a) {
int i, count, len;
char **final_result;
const char *p;
// phase 1: count the number of tokens
p = str + strspn(str, delimiters);
for (count = 0; *p; count++) {
p += strcspn(p, delimiters);
p += strspn(p, delimiters);
}
// phase 2: allocate the arrays
final_result = calloc(sizeof(*final_result), count + 1);
if (a) {
*a = calloc(sizeof(**a), count);
}
if (size_of_a) {
*size_of_a = count;
}
// phase 3: copy the tokens
p = str;
for (i = 0; i < count; i++) {
p += strspn(p, delimiters); // skip the delimiters
len = strcspn(p, delimiters); // count the token length
if (a) {
(*a)[i] = len;
}
final_result[i] = strndup(p, len); // duplicate the token
p += len;
}
final_result[count] = 0;
return final_result;
}
// read and discard the rest of the user input line
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int main() {
char buf[256];
char delimiters[20];
printf("Enter the string: ");
if (scanf("%255[^\n]", buf) != 1)
return 1;
flush_input();
printf("\nEnter the delimiters: ");
if (scanf("%19[^\n]", delimiters) != 1)
return 1;
flush_input();
int *sizes;
int count;
char **array = split(buf, delimiters, &sizes, &count);
printf("\nThe result is:\n");
for (int x = 0; x < count; x++) {
for (int y = 0; y < sizes[x]; y++) {
putchar(array[x][y]);
}
printf("\n");
}
getchar();
return 0;
}
#include <stdio.h>
void revstr(char str[])
{
char temp;
int size = 0;
while(*str != '\0'){
size++;
str++;
}
for (int i = 0; i < size/2; i++)
{
temp = str[i];
str[i] = str[size-1-i];
str[size-1-i] = temp;
}
for(int i = 0; i < size; i++)
{
printf("%c\n", *(str+i));
}
}
int main()
{
char str[20];
printf("enter a string: \n");
scanf("%s", &str);
revstr(str);
return 0;
}
why is my rev string not printing the reverse of the string it is printing out some garbage value.
can you point out why?
After this while loop
while(*str != '\0'){
size++;
str++;
}
the pointer str does not point to the beginning of the string.
Instead you could write for example
while( str[size] != '\0'){
size++;
}
Nevertheless such a function should do only one thing: to reverse a string. It is the caller of the function that decides whether to output the reversed string.
So the function can look like
char * revstr( char s[] )
{
size_t n = 0;
while ( s[n] ) ++n;
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = c;
}
return s;
}
and in main you could write
puts( revstr( str ) );
Here is a demonstrative program.
#include <stdio.h>
char * revstr( char s[] )
{
size_t n = 0;
while ( s[n] ) ++n;
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = c;
}
return s;
}
int main(void)
{
char s[] = "Hello";
puts( s );
puts( revstr( s ) );
return 0;
}
The program output is
Hello
olleH
Of course instead of the while loop you could use the standard string function strlen.
size_t n = strlen( s );
Pay attention to that in the call of scanf
scanf("%s", &str);
the second argument shall be the expression str
scanf("%s", str);
I would implement it another way:
char *reverse(char *str)
{
char *wrk = str, *end = str;
if(str && *str)
{
while(*(end + 1)) end++;
while(end > wrk)
{
char tmp = *end;
*end-- = *wrk;
*wrk++ = tmp;
}
}
return str;
}
It is good to check if the parameter is correct.
I would return the value. It allows you to use the reversed string in expressions and as a function parameter. Example below:
int main(void)
{
char s[] = "Hello world";
printf("%s\n", reverse(s));
}
https://godbolt.org/z/fbo4nsn38
In your code you advance the pointer str to calculate its length but you forgot to reset it to the start after that. Also, your call to scanf should pass str, not its address. Moreover scanf will write beyond the end of str if the user enters a string longer than 19 characters. Try this instead:
#include <stdio.h>
#include <string.h>
void revstr(char str[])
{
char temp;
int size = strlen(str);
for (int i = 0; i < size / 2; i++) {
temp = str[i];
str[i] = str[size - 1 - i];
str[size - 1 - i] = temp;
}
}
int main()
{
char str[20];
printf("enter a string: \n");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0';
revstr(str);
printf("%s\n", str);
return 0;
}
What I need to write:
1.Get a main string from user.
2.Get a subString from a user.
Every match of the subString in the main string, change its letters to uppercase.
Do not use string's functions like strstr.
For example:
main string: abcdeffghfhkfff
sub string: ff
outut: abcdeFFghfhkFFf
Problem: Well, I'm having troubles to continue writing the code after I found one match. for example after I found the first 'f' in the main string, how can I continue check if the second 'f' is adjacent to the found 'f', if not, then try to find another 'f' and check subsequent matches of the subarray until we've found that the length of the substring matches the number of subsequent matches in the string? Here's what I've tried, and in writing the logic of the for loop in 'replaceSubstring' function
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
#include <string.h>
#define N 101
void replaceSubstring(char *str, char *subStr);
void main()
{
char str[N], subStr[N];
while (strlen(str) != 0 || strlen(subStr) != 0)
{
str[0] = 0;
printf("Enter text: ");
gets(str);
printf("Enter substring: ");
scanf("%s", subStr);
replaceSubstring(str, subStr);
}
}
void replaceSubstring(char *str, char *SubStr)
{
int i, count = 0, j = 0, k = 0;
for (i = 0; i <= strlen(str); i++)
{
if (str[i] == SubStr[k])
{
k++;
count++;
if (count == strlen(SubStr))
{
str[i] -= 32;
}
}
}
puts(str);
getchar();
}
You can use strstr() function to do this more easly, like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 101
void replaceSubstring(char *str, char *subStr);
void main()
{
char str[N], subStr[N];
while (strlen(str) != 0 || strlen(subStr) != 0)
{
str[0] = 0;
printf("Enter text: ");
gets(str);
printf("Enter substring: ");
scanf("%s", subStr);
replaceSubstring(str, subStr);
}
}
void replaceSubstring(char *str, char *SubStr)
{
int i;
char *tmp;
while((tmp = strstr(str, SubStr)) != NULL)
{
for (i = 0; i < strlen(SubStr); i++)
{
tmp[i] -= 32;
}
}
puts(str);
getchar();
}
Here another version of replaceSubstring() function without using strstr() function:
void replaceSubstring(char *str, char *SubStr)
{
int i = 0, found = 1, j = 0, k = 0;
while (i < strlen(str))
{
if (str[i] == SubStr[0])
{
found = 1;
for(k = 0; k < strlen(SubStr); k++)
{
if(str[i+k] != SubStr[k])
{
found = 0;
break;
}
}
if(found)
{
for(k = 0; k < strlen(SubStr); k++)
{
str[i+k] -= 32;
}
i += strlen(SubStr);
}
else
i++;
}
else
i++;
}
puts(str);
getchar();
}
To solve this without using strstr(), i would do something like this:
void replaceSubstring(char *str, char *SubStr)
{
int i = 0, equals = 0, j = 0, k = 0;
for(i=0;i<strlen(str);i++){
j = i;
equals = 1;
k=0;
while(k<strlen(SubStr)&&(equals == 1)){
if(SubStr[k] != str[j]){
equals = 0;
}
k++;
j++;
}
if(equals == 1){
for(j=i;j<i+k;j++){
str[j] -= 32;
}
}
}
puts(str);
getchar();
}
I'm pretty sure this works correctly.
input: abcdeffghfhkfff
substring: ff
output: abcdeFFghfhkFFf
Here is a demonstrative program that shows how the function can be written
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char * replaceSubstring( char *s1, const char *s2 )
{
char *p = s1;
size_t n = strlen( s2 );
while ( ( p = strstr( p, s2 ) ) != NULL )
{
for ( size_t i = 0; i < n; ++i, ++p ) *p = toupper( ( unsigned char )*p );
}
return s1;
}
int main( void )
{
char s[] = "abcdeffghfhkfff";
puts( s );
puts( replaceSubstring( s, "ff" ) );
}
Its output is
abcdeffghfhkfff
abcdeFFghfhkFFf
Take into account that according to the C Standard function main without parameters shall be declared like`
int main( void )
Also it is a bad idea to use "magic" numbers like 32 like in this statement
tmp[i] -= 32;
For example if in the environment there are used EBCDIC characters then this statement will be simply wrong.
Moreover even for ASCII characters this statement is invalid because it is not necessary that original characters are in lower case.
A friend of mine needed help counting the occurrences of a substring in a string, and I came up with the following code. Does anyone know a better method to do this?
#include "stdio.h"
#include "string.h"
int main(int argc, char *argv[])
{
char str1[50], str2[50];
int i, j, l1, l2, match, count;
printf("String 1:\n");
gets(str2);
printf("String 2:\n");
gets(str1);
l1 = strlen(str1);
l2 = strlen(str2);
count = 0;
for(i = 0; i < l1; i++)
{
match = 0;
for(j = 0; j < l2; j++)
{
if(str1[i + j] == str2[j])
{
match++;
}
}
if(match == l2)
{
count++;
}
}
printf("Substrings: %d\n", count);
}
how about this: (using the strstr function, reference here)
int count = 0;
char str1[50], str2[50];
char* tmp = str1;
int count;
printf("String 1:\n");
gets(str2);
printf("String 2:\n");
gets(str1);
while(*tmp != '\0' && (tmp = strstr(tmp, str2))) {
++count;
++tmp;
}
Please do not use or encourage the use of gets. Beyond the fact that it will introduce a point of failure in your code, it has been deprecated as of C99 and will be gone completely from C1X.
As others have said, strstr is your friend here:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s1[50], s2[50];
char *p;
size_t count = 0;
size_t len1;
printf("Gimme a string: ");
fflush(stdout);
fgets(s1, sizeof s1, stdin);
p = strchr(s1, '\n'); // get rid of the trailing newline
if (p)
*p = 0;
printf("Gimme another string: ");
fflush(stdout);
fgets(s2, sizeof s2, stdin);
p = strchr(s2, '\n'); // get rid of the trailing newline
if (p)
*p = 0;
p = s2;
len1 = strlen(s1);
while ((p = strstr(p, s1)) != NULL && p != s1)
{
count++;
p += len1;
}
printf("Found %lu occurrences of %s in %s\n", count, s1, s2);
return 0;
}
You might want to take a look at the strstr function (if you're not already familiar with it).
int main()
{
char *str = "This is demo";
char *sub = "is";
int i,j,count;
i=j=count=0;
while(str[i]!='\0')
{
if (str[i] == sub[j] && str[i+1] == sub[j+1])
{
count++;
}
i++;
}
cout<<count;
return 0;
}
Above code works but this is static.
You can use QString in QT library
QString t = "yourstring";
t.count("yoursubstring");
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));