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;
}
Related
I have to write a function to check for palindromes in sentences and words.
For sentences it looks like this (and works):
int checkSentencepalindrome(char * str)
{
size_t len = strlen(str);
char *pntr1 = str;
char *pntr2 = str + len - 1;
while(pntr2 >= pntr1)
{
if (!isalpha(*pntr2))
{
pntr2--;
continue;
}
if (!isalpha(*pntr1))
{
pntr1++;
continue;
}
if(tolower(*pntr1) != tolower(*pntr2))
{
return 0;
}
pntr1++;
pntr2--;
}
return 1;
}
for word palindromes it looks like this:
int checkWordpalindrome(char * str)
{
size_t len = strlen(str);
char *pntr1 = str;
char *pntr2 = str + len - 1;
while(pntr2 >= pntr1)
{
if(tolower(*pntr1) != tolower(*pntr2))
{
return 0;
}
pntr1++;
pntr2--;
}
return 1;
}
However, the function for word palindromes returns me 0 all the time. (I expect a 1 for palindrome and 0 for non-palindrome words)
I thought the if statements I deleted are just there to skip spaces, exclamation marks, etc. (everything not included in the alphabet) Why are they so crucial for my function to work properly then?
How can I solve this while using pointers only?
EDIT: The issue only occurs when passing the string as following:
int checkWpalindrome(char * str)
{
printf("%s ", str);
size_t len = strlen(str);
if(len == 0)
{
return 0;
}
char *pntr1 = str;
char *pntr2 = str + len - 1;
while(pntr2 >= pntr1)
{
if(tolower(*pntr1) != tolower(*pntr2))
{
return 0;
}
pntr1++;
pntr2--;
}
return 1;
}
void input(char * str)
{
printf("Input: ");
fgets(str, 101, stdin);
fflush(stdin);
}
int main()
{
char arr[10];
input(arr);
printf("%d", checkWpalindrome(arr));
return 0;
}
fgets() includes reading and saving a '\n' and causes checkWordpalindrome() to return 0 (unless maybe only "\n" was read). #Adrian Mole.
To lop off the potential '\n', use str[strcspn(str, "\n")] = 0; right after fgets().
Both functions risk undefined behavior (UB) as they can attempt to generate a pointer to before str. Consider check...("?").
In checkSentencepalindrome() the UB is is more so as code then attempts *pntr2 of an invalid pointer.
isalpha(ch) and tolower(ch) have (UB) when ch < 0 (and not EOF)
Calling code buffer too small: char arr[10]; ... fgets(str, 101, stdin);. Make them the same size like char arr[101]; ... fgets(str, 101, stdin);
fflush(stdin); is UB and not needed. #Adrian Mole
Repaired code:
int checkSentencepalindrome(const char * str) {
size_t len = strlen(str);
const unsigned char *left = (const unsigned char *) str;
const unsigned char *right = left + len; // point one-past
while(left < right) {
if (!isalpha(right[-1])) {
right--;
continue;
}
if (!isalpha(left[0])) {
left++;
continue;
}
right--;
if (tolower(left[0]) != tolower(right[0])) {
return 0;
}
left++;
}
return 1;
}
A bit tidier with
while(left < right) {
if (!isalpha(*left)) {
left++;
continue;
}
right--;
if (!isalpha(*right)) {
continue;
}
if (tolower(*left) != tolower(*right)) {
return 0;
}
left++;
}
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++;
}
}
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;
}
#include <stdio.h>
#include <string.h>
#define SIZE 40
int main(void)
{
char buffer1[SIZE] = "computer program";
char *ptr;
int ch = 'p', j = 0, i;
for (i = 0; i<strlen(buffer1); i++)
{
ptr = strchr(buffer1[i], ch);
if (ptr != 0) j++;
printf(" %d ", j);
}
}
I want to count how many times a character occurs in a string.
In my program I chose the character 'p'.
I know Pascal, I am learning C now. In pascal is a function called Pos(x,y) which is searching for x in y. Is something familiar to this? I think what I used here is not.
The function signature of strchr is
char *strchr(const char *s, int c);
You need to pass a char* but you have passed a char. This is wrong.
You have used the strlen in loop - making it inefficient. Just calculate the length of the string once and then iterate over it.
char *t = buffer;
while(t!= NULL)
{
t = strchr(t, ch);
if( t ) {
t++;
occurences++;
}
}
And without using standard library functions you can simply loop over the char array.
size_t len = strlen(buffer);
for(size_t i = 0; i < len; i++){
if( ch == buffer[i]) occurences++;
}
Or alternatively without using strlen
char *p = buffer;
while(*p){
if( *p == ch ){
occurences++;
}
p++;
}
Or
for(char *p = buffer; *p; occurences += *p++ == ch);
Try this example :
int main()
{
char buffer1[1000] = "computer program";
char ch = 'p';
int i, frequency = 0;
for(i = 0; buffer1[i] != '\0'; ++i)
{
if(ch == buffer1[i])
++frequency;
}
printf("Frequency of %c = %d", ch, frequency);
return 0;
}
I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}