Removing char from string C - arrays

I'm learning C now
I need to make a program that remove char that I'll input from string. I've seen an algorithm and I write this code
#define MAX_LEN 200
int main()
{
char str[MAX_LEN];
char rem;
int i = 0;
printf("Enter the setence:");
gets(str);
printf("\nEnter the char to remove");
rem = getchar();
char* pDest = str;
char* pS= str;
printf("sent:\n%s", str);
while (str[i]!='\0'){
if (*pDest != rem) {
*pDest = *pS;
pDest++;
pS++;
}
else if (*pDest == rem) {
pS++;
}
i++;
}
*pDest = '\0';
while (str[i] != '\0') {
printf("number%d", i);
putchar(str[i]);
printf("\n");
i++;
}
}
But it returns nothing, like the value str gets, i think \0 and retuns nothing.
May you help me to find the problem?

Use functions!!
If dest is NULL then this function will modify the string str otherwise, it will place the string with removed ch in dest.
It returns reference to the string with removed character.
char *removeChar(char *dest, char *str, const char ch)
{
char *head = dest ? dest : str, *tail = str;
if(str)
{
while(*tail)
{
if(*tail == ch) tail++;
else *head++ = *tail++;
}
*head = 0;
}
return dest ? dest : str;
}
int main(void)
{
char str[] = "ssHeslsslsos sWossrlssd!ss";
printf("Removal of 's' : `%s`\n", removeChar(NULL, str, 's'));
}

It would be easier to use array style indexing to go through the string. For example use str[i] = str[i + 1] instead of *pstr = *other_pstr. I leave this incomplete method, since this looks like homework.
int main()
{
char str[] = "0123456789";
char ch = '3';
for (int i = 0, len = strlen(str); i < len; i++)
if (str[i] == ch)
{
for (int k = i; k < len; k++)
{
//Todo: shift the characters to left
//Hint, it's one line
}
len--;
}
printf("%s\n", str);
return 0;
}

I just added new char array char dest[MAX_LEN] that store string with deleted symbols:
#define MAX_LEN 200
int main()
{
char str[MAX_LEN];
char rem;
int i = 0;
printf("Enter the setence:");
gets(str);
printf("\nEnter the char to remove");
rem = getchar();
char dest[MAX_LEN] = "\0";
char* pDest = dest;
char* pS = str;
printf("sent:\n%s", str);
while (str[i]!='\0')
{
if (*pS != rem)
{
*pDest = *pS;
pDest++;
pS++;
}
else if (*pS == rem)
{
pS++;
}
i++;
}
i = 0;
printf("\nres:\n %s \n", dest);
while (dest[i] != '\0') {
printf("number%d", i);
putchar(dest[i]);
printf("\n");
i++;
}
}

Related

Why does a question mark appears in the output of my function and how can I avoid it?

I've read some posts about the question mark but it didn't work.
Here's the code for the function : (i want to create one like "strcpy")
char *stringcopy(char *word1, char *word2)
{
int i = 0;
for (i = 0; word2[i] != '\0'; i++)
{
word1[i] = word2[i];
}
return word1;
}
if I call the function for example like this : printf("%s", stringcopy(word1, "hello"));
it gives me this : "hello?"
char *stringcopy(char *word1, char *word2)
{
int i = 0;
while( word2[i] != '\0')
{
word1[i] = word2[i];
i++;
}
word1[i]='\0';
return word1;
}
You can add NULL characters after the loop.
Your loop terminates when word2[i] == '\0' and the body of the loop is not executed word1 contains not terminated string. You can terminate it by writing '\0' after the loop or simply modifying the loop itself. You can also can use another types of loop:
char *stringcopy(char *word1, char *word2)
{
size_t i = 0;
for (i = 0; (word1[i] = word2[i]) != '\0'; i++);
return word1;
}
char *stringcopy1(char *word1, char *word2)
{
size_t i = 0;
for (i = 0; word2[i] != '\0'; i++)
{
word1[i] = word2[i];
}
word1[i] = '\0';
return word1;
}
char *stringcopy2(char *word1, const char *word2)
{
char *wrk = word1;
while((*wrk++ = *word2++) != '\0');
return word1;
}
char *stringcopy3(char *word1, const char *word2)
{
char *wrk = word1;
do
{
*wrk++ = *word2;
}
while(*word2++ != '\0');
return word1;
}
BTW the index variable should have size_t type.

pointer string not returning expected output

#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;
}

Saving numbers (sequence of digits) from a string in an array of pointers to a char

I am supposed to save every sequence of digits from a string in an array of chars , this is what i tried:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int check_number(char *s) {
for (; *s; ++s) {
if (!isdigit(*s))
return 0;
}
return 1;
}
void int_in_string(char *s, char **ar, int MaxCap) {
char temp[100];
int index = 0;
int i = 0;
for (; *s; s++) {
if (index == MaxCap) {
break;
}
if (isdigit(*s)) {
temp[i++] = *s;
}
if (*s == ' ' && check_number(temp)) {
ar[index++] = temp;
memset(temp, '\0', i);
i = 0;
}
}
if (index == 0) {
printf("no numbers in string");
}
for (int i = 0; i < index; i++)
printf(" %s \n", ar[i]);
}
but this code only prints several newlines , can someone explain me what i do wrong?
Some issues:
ar[index++]=temp;
This is just storing the same value (the address of temp) over and over. What you need to do is copy the string into the array.
Also, you need to terminate the string temp with '\0'. You handle this in all but the first string with memset(temp, '\0', i); However, since local variables are not initialized, you need to do it:
char temp[100] = {0}
Or, you can remove the initialization and the memset by just adding the EOS:
temp[i] = '\0';
Lastly, since you declare the original array as
char * ar[10];
You are not allocating any space for the strings. The simplest way to handle that is with strdup.
void int_in_string(char *s, char **ar, int MaxCap)
{
char temp[100];
int index = 0;
int i = 0;
for (; *s; s++) {
if (isdigit(*s)) {
temp[i++] = *s;
// Need to avoid buffer overflow
if (i == sizeof(temp)) {
i = 0;
}
}
if (isspace(*s)) {
temp[i] = '\0';
// strdup will allocate memory for the string, then copy it
ar[index++] = strdup(temp);
// if (NULL == ar[index-1]) TODO: Handle no memory error
i = 0;
if (index == MaxCap) {
break;
}
}
}
if (index == 0) {
printf("no numbers in string");
}
for (int i = 0; i < index; i++) {
printf(" %s \n", ar[i]);
// free the mem from strdup
free(ar[i]);
}
}
I believe some systems may not have strdup(). If not, it can be easily replicated:
char * my_strdup(const char *src)
{
if (src == NULL) return NULL;
char *dest = malloc(strlen(src) + 1);
if (dest == NULL) return NULL;
strcpy(dest, src);
return dest;
}

If a string is rotation of other. All test cases Not running

I am using the logic of concatenation the 2nd string and then searching first string in it.
But for some reason, the code does not run for all test cases.
example
s1 = rahul , s2 = hulra
s2.s2 = hulrahulra
and then search s1 in s2.s2 using strstr() function.
#include <stdio.h>
#include <string.h>
int ifRotation(char *s1, char *s2)
{
int l1 = strlen(s1);
int l2 = strlen(s2);
char str1[l1], str2[l2+ l2];
int i;
i = 0;
while(*s1 != '\0')
{
str1[i] = *s1;
i++;
s1++;
}
i = 0;
while(*s2 != '\0')
{
str2[i] = *s2;
i++;
s2++;
}
strcat(s2, s2);
if(strstr(s2, s1))
{
return 1;
}
return 0;
}
int main() {
//code
int queries;
scanf("%d", &queries);
int array[queries];
char str1[100];
char str2[100];
int i = 0;
while(i < queries)
{
scanf("%s", &str1);
scanf("%s", &str2);
array[i] = ifRotation(str1, str2);
i++;
}
i = 0;
while(i < queries)
{
printf("%d\n", array[i]);
i++;
}
return 0;
}
Please tell me what's wrong with the code?
You are just copying from one string to another, and the copy routine has several problems.
char str1[l1] is not large enough. It should be char str1[l1 + 1]. The extra 1 is for the null character.
The string should always end with null character '\0'.
s1 and s2 are incremented until they reach the null character, so by that time s1 and s2 are empty.
Try the following code for copying the strings, you will see s1/s2 will be empty, str1/str2 are just copies of the original s1/s2.
You can fix the copying as follows:
char str1[l1 + 1], str2[l2 + 1];
int i;
i = 0;
while(*s1 != '\0')
{
str1[i] = *s1;
i++;
s1++;
}
str1[i] = '\0';
i = 0;
while(*s2 != '\0')
{
str2[i] = *s2;
i++;
s2++;
}
str2[i] = '\0';
printf("s1=%s, s2=%s, str1=%s, str2=%s\n", s1, s2, str1, str2);
//output: s1=, s2=, str1=old_s1, str2=old_s2
But this doesn't really achieve anything. If you just want to check "rahul" is the reverse of "hulra", keep s1 as it is, copy s2 to reverse_s2 in reverse order, and compare the two strings as follows:
#include <stdio.h>
#include <string.h>
int ifRotation(const char *s1, const char *s2)
{
if(!s1 || !s2)
return 0;
int len2 = strlen(s2);
char reverse_s2[len2 + 1];
//copy s2 to reverse_s2 in reverse order:
int i = 0;
for(i = 0; i < len2; i++)
reverse_s2[i] = s2[len2 - i - 1];
reverse_s2[i] = '\0'; //add null character
int result = strcmp(s1, reverse_s2) == 0;
return result;
}
int main(void)
{
printf("%d\n", ifRotation("rahul", "hulra"));
printf("%d\n", ifRotation("rahul", "luhar"));
return 0;
}

removing all repeated characters from string in c

I want to remove all the repeated characters from a string. For example, if I have:
"abcdabef"
I want the result to be
"cdef"
I have tried with loops, but it's getting me confusing. Can anyone just tell me how to do this?
Here's what I've tried so far:
#include<stdio.h>
#include<string.h>
main()
{
char s[20],ch,*p;
int i,j,k,cnt;
puts("enter string:");
gets(s);
for(i=0;s[i];i++)
{
ch=s[i];
for(cnt=0,j=0;s[j];j++)
{
if(ch==s[j])
cnt++;
if(cnt>1)
{
for(k=0;s[k]==ch;k++)
{
strcpy(s+k,s+k+1);
if(s[k]==ch)
{k--;}
}
if(s[j-1]==ch)
j--;
}
}
}
puts(s);
}
If I were you, I would just count the characters in the string and print out those which appear exactly once in the string.
char buf[BUFSIZE]; // whatever the size is
// get user input
if (!fgets(buf, sizeof buf, stdin))
exit(EXIT_FAILURE); // couldn't fgets()
size_t len = strlen(buf);
int counts[1 << CHAR_BIT] = { 0 };
// count each character
for (size_t i = 0; i < len; i++) {
unsigned char ch = buf[i];
counts[ch]++;
}
// print those which are present exactly once
for (size_t i = 0; i < 1 << CHAR_BIT; i++) {
if (counts[i] == 1) {
printf("%c", (unsigned char)(i));
}
}
char* remRepeatedChars(char *str)
{
char arr[128] = {0};
char *tmp = str;
while((*str) != '\0')
{
char *p = str;
while(arr[*p] != 0 && *p != '\0')
p++; // found repetition
if(str != p) // the previous while was entered
*str = *p; //Copy the content of p to str.
arr[*str]++;
str++;
}
return tmp;
}

Resources