I am writing a code to remove the repeated occurrence of a character in the string.
Description:- Remove the repeated characters from the string
Example:-
Sample Input = abcdeabd
Sample Output =abcde
I have written the code and it is working and when I tested by running sample test cases ,It is passing most of the test cases but is failing some e.g. when I Use the input string as "abcdabcdabcdabcd" It is giving me abcdd as the output instead of "abcd"
Here is my code
#include<stdio.h>
int main(void)
{
char a[60]="abcdeabd";
int n=0;
for(int l=0;a[l]!='\0';++l)
++n;
printf("%d\n",--n);
for(int i=0;i<=n;++i)
{
for(int j=i+1;j<=n;++j)
{
if(a[i]==a[j])
{
for(int k=j;k<=n;++k)
a[k]=a[k+1];
--n;
}
}
}
puts(a);
return 0;
}
Please tell me where I am going wrong with this code...?
The logic error is in the block
if(a[i]==a[j])
{
for(int k=j;k<=n;++k)
a[k]=a[k+1];
--n;
}
It doesn't work when you have the same character more than twice in succession. It doesn't work for `"addd" or "adddbc".
Change that to a while loop to fix the problem.
while (a[i] == a[j])
{
for(int k=j;k<=n;++k)
a[k]=a[k+1];
--n;
}
As for me I would write a corresponding function using pointers. For example
#include <stdio.h>
char * unique( char *s )
{
char *last = s, *current = s;
do
{
char *t = s;
while ( t != last && *t != *current ) ++t;
if ( t == last )
{
if ( last != current ) *last = *current;
++last;
}
} while ( *current++ );
return s;
}
int main(void)
{
char s[]="abcdeabd";
puts( s );
puts( unique( s ) );
return 0;
}
The output is
abcdeabd
abcde
As for your code then I would rewrite it the following way Take into account that you have to copy also the terminating zero.
#include <stdio.h>
char *unique( char *s )
{
int n = 0;
while ( s[n++] != '\0' );
printf( "%d\n", n );
for ( int i = 0; i < n; ++i )
{
for ( int j = i + 1; j < n; ++j )
{
if ( s[i] == s[j] )
{
--n;
for ( int k = j; k < n; ++k ) s[k] = s[k+1];
}
}
}
return s;
}
int main(void)
{
char s[]="abcdeabd";
puts( s );
puts( unique( s ) );
return 0;
}
#include<stdio.h>
int main(void)
{
char a[10]="abcdeabd";
for(int i=0;a[i]!='\0';++i)
printf("\n %c", a[i]);
for(i=0;a[i]!='\0';++i)
for(int j=i+1;a[j]!='\0';++j)
if(a[i]==a[j])
for(int k=j;a[k]!='\0';++k)
a[k]=a[k+1];
puts(a);
return 0;
}
#Patel: Your program is correct.
You missed only one single thing.
When You used printf(), you decrement the value of n.
So put a line to increment it after printf()
++i;
Related
I'm recently practicing looping. I learned how to print: for example home to h ho hom home. by using
#include <stdio.h>
#include <string.h>
int main (){
char s[100];
printf("Input string = ");
scanf("%[^\n]", s);
for (int i=1; i<=strlen(s); i++){
for(int j = 0; j<i; j++)
printf("%c", s[j]);
printf("\n");
}
return 0;
How can i reverse it so it can be
home
hom
ho
h
instead? thank you.
It is easy to do. For example
for ( size_t i = strlen( s ); i != 0; i-- )
{
for ( size_t j = 0; j < i; j++ )
{
putchar( s[j] );
}
putchar( '\n' );
}
Another way is the following
for ( size_t i = strlen( s ); i != 0; i-- )
{
printf( ".*s\n", ( int )i, s );
}
provided that an object of the type int is able to store the length of the passed string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
const char *s = "home";
for (size_t i = strlen( s ); i != 0; i--)
{
printf( "%.*s\n", ( int )i, s );
}
}
The program output is
home
hom
ho
h
You could loop over the string using putc, but it might also be helpful to understand the destructive approach that shortens the string and uses %s to print strings. eg:
#include <stdio.h>
#include <string.h>
int
main(int argc, char **argv)
{
char *s = argc > 1 ? argv[1] : strdup("home");
for( char *e = s + strlen(s); e > s; e -= 1 ){
*e = '\0';
printf("%s\n", s);
}
return 0;
}
Note that this approach is destructive. When complete, the string is null. As an exercise, it might be helpful to fix that.
You'll basically go backwards in your loop.
Instead of:
for (int i=1; i<=strlen(s); i++){
You'd have
for (int i=strlen(s); i>0; i--){
I need to delete all letters from s1 which are in s2.
I can't understand what is wrong with my code:
#include <stdio.h>
#include <stdlib.h>
void squeeze(char s1[], char s2[])
{
int i,j;
i=j=0;
for(i; s2[i]!='\0'; i++) {
for (j; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
s1[j] = s1[j + 1];
--j;
}
}
}
}
int main()
{
char w1[] = "abcde";
char w2[] = "fghaj";
squeeze(w1,w2);
puts(w1);
return 0;
}
but the output is:
abcde
What should I repair?
For starters the variable j is not reset to 0 in the inner loop for each iteration of the outer loop.
Secondly if a character has to be removed then all characters after it are not being moved to the left one position. You are simply replacing the removed character with the next character in the string.
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
char * squeeze( char s1[], const char s2[] )
{
for ( char *p = s1, *q = s1; *q; ++p )
{
if ( !*p || !strchr( s2, *p ) )
{
if ( q != p )
{
*q = *p;
}
if ( *p ) ++q;
}
}
return s1;
}
int main( void )
{
char w1[] = "abcde";
char w2[] = "fghaj";
puts( squeeze( w1, w2 ) );
return 0;
}
The program output is
bcde
If you are not allowed to use standard string functions and pointers then the program can look the following way.
#include <stdio.h>
char * squeeze( char s1[], const char s2[] )
{
for ( size_t i = 0, j = 0; s1[j] != '\0'; ++i )
{
size_t k = 0;
while ( s2[k] != '\0' && s2[k] != s1[i] ) ++k;
if ( s2[k] == '\0' )
{
if ( j != i )
{
s1[j] = s1[i];
}
if ( s1[i] != '\0' ) ++j;
}
}
return s1;
}
int main( void )
{
char w1[] = "abcde";
char w2[] = "fghaj";
puts( squeeze( w1, w2 ) );
return 0;
}
The program output is the same as shown for the previous demonstrative program
bcde
Two problems in squeeze:
You need to reinitialize j to zero on every pass through the loop.
You need to copy the entire remained of the string one character to the left, not just the character following the one you want to remove.
I suggest you rewrite squeeze as:
void squeeze(char s1[], char s2[])
{
int i,j;
i=j=0;
for( ; s2[i]!='\0'; i++) {
for (j = 0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]) {
strcpy(s1+j, s1+j+1);
--j;
}
}
}
}
I see an issue here , your code is not entering this statement for some reason :
if (s1[j] == s2[i]) {
s1[j] = s1[j + 1];
--j;
}
your question might be why ? cause i and j are not set to 0 , try printing them and you will see that j will move to 4 but i is staying forever as 0
so as a start you can fix it by doing this
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
then you didn't copy the whole string and moved it back one step to rewrite over the found caracter , you only moved one caracter and left it blank
Exemple
input : abcde
output :b_cde
to fix this you have two methods :
use strcpy in order to move back one step the code
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]){
strcpy(s1+j, s1+j+1);
--j;
}
}
or you can simply create the same function using a boucle for
for(i=0; s2[i]!='\0'; i++) {
for (j=0; s1[j] != '\0'; j++) {
if (s1[j] == s2[i]){
for (k=j;s1[k] != '\0';k++)
s1[k] = s1[k + 1];
--j;
}
}
#include <stdio.h>
#include <string.h>
int rem_str(char * porgstr, char * pdel) {
if (!porgstr || !pdel) {
return 0;
}
int i = 0;
int j = 0;
char tmp[256] = {0};
int len = strlen(pdel);
for (i = 0; i < len; i++) {
tmp[pdel[i]]++;
}
len = strlen(porgstr);
for (i = 0, j=0; i < len; i++) {
if(tmp[porgstr[i]] == 0) {
porgstr[j] = porgstr[i];
j++;
}
}
porgstr[j] = 0;
return 0;
}
int main () {
char * input1 = strdup("origional string passed to program");
char * input2 = strdup("sdel");
printf("Input before del : %s\n", input1);
rem_str(input1, input2);
printf("String after del : %s\n", input1);
return 0;
}
Output:
./a.out
Input before del : origional string passed to program
string after del : origiona tring pa to program
To put it bluntly, as it stands, I am not very good at coding at this current time. I am really trying to get these functions completed, I am just having trouble with the execution on some of them.
Basically, there are 10 functions ( 6 of which I have finished? ) that need to be created.
There is an int main() but, besides a string that needs to be fixed, the int main() does not need to be touched.
I will post the program (mostly so you can see my work) in addition to the int main() so that if someone wants to check the intent, they can see it. Even though I have posted the whole program, the only ones that I really want to focus on are the makeUpper, and the functions that have nothing in them because I really don't understand how to copy and edit a string into another array.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
void makeUpper( char orig[], char result[] )
{
/*
int i = 0;
while ( str[i] != '\0' )
{
if ( str[i] >= 'a' && str[i] <= 'z' )
str[i] = str[i] - 32;
k++;
}
*/
}
int countDigit( char str[] )
{
int i;
int count = 0;
int len;
len = strlen(str);
for ( i = 0; i < len; i++ )
{
if ( i >= '0' && i <= '9' )
count++;
}
return count;
}
int onlyLetters( char orig[], char letters[] )
{
}
int countOdd( int A[], int N )
{
int i;
int odd = 0;
for ( i = 0; i < N; i++ );
{
if ( A[i] % 2 != 0 )
odd++;
}
return odd;
}
int sumList( int A[], int N )
{
int i;
int sum = 0;
for ( i = 0; i < N; i++ );
sum = sum + A[i];
return sum;
}
void addToEach( int A[], int N, int val )
{
int i;
for ( i = 0; i < N; i++ )
A[i] + val;
printf("%d", A[i]);
}
void copyNumList( int orig[], int N, int result[] )
{
}
// populate list A with N items, random in range L to H
void fillNumList( int A[], int N, int L, int H )
{
}
// print the list, 10 items per line
void printList( int A[], int N )
{
int i;
for ( i = 0; i < N; i++ )
printf("%d ", A[i]);
printf("\n");
}
void rept( int n, char c )
{
int i;
for ( i = 0; i < n; i++ )
printf("%c", c);
printf("\n");
}
int main()
{
char line[100], other[100];
int i, len;
printf("Phrase: ");
fgets( line, 100, stdin );
// fix the string....
// ...
// really, do this
// ...
rept(10,'-');
printf("Orig: ##%s##\n", line);
rept(10,'-');
makeUpper( line, other );
printf("toupper: %s\n", other);
rept(10,'-');
i = countDigit( line );
printf("%d digits\n", i);
rept(10,'-');
len = onlyLetters( line, other );
printf("only letters: %s\n", other );
printf(" new len %d\n", len);
int nums[30], vals[30];
int many = 19;
rept(5, '-');
fillNumList( nums, many, 3, 11 );
printList( nums, many );
rept(5, '-');
i = countOdd( nums, many );
printf("%d odd values\n", i);
rept(5, '-');
i = sumList( nums, many );
printf("%d is sum\n", i);
rept(5, '-');
copyNumList( nums, many, vals );
printf("Copy\n");
printList( vals, many );
rept(5, '-');
addToEach( vals, many, 4 );
printf("Add 4\n");
printList( vals, many );
rept(5, '-');
printf("Orig\n");
printList( nums, many );
rept(5, '-');
return 0;
}
To answer the one almost-well-defined question (regarding makeUpper):
First, str is not a variable. You have orig and result, and haven't declared str anywhere.
Now, if str were orig, you'd be correctly uppercasing the characters in the original string. However, the task is to leave the original string alone and make an uppercased copy. The former is called "destructive operation" (as the original contents are not preserved); the latter, a "non-destructive operation" (for obvious reasons). Here are the changes needed to make your function non-destructive:
void makeUpper( char orig[], char result[] )
{
int k = 0;
do
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
} while ( orig[k++] != '\0' );
}
Notice that I iterate and test on orig, but assign to result.
onlyLetters should be similar; but you will need two index variables, not just k, since you will want to progress through orig and result at different pace (you'll only want to copy a character when it's a letter, and you'll only want to progress through result when you do a copy - as opposed to orig, which you'll always consume one character per loop).
As you have not stated what your misunderstanding is about copyNumList and fillNumList, I cannot give you any help there.
EDIT: I forgot about the terminator (and didn't test it); thanks Tom Karzes! Because the zero also needs to be copied, your loop is changed from while (condition) { ... } to do { ... } while (condition) - instead of testing whether we're at end and then doing things if we're not, we'll do the thing first, and only afterwards ask if we're done. This also requires the increment to be done after the test, so k++ got moved. If this is too weird for you, you can get the same effect like this, by explicitly adding the terminator after the loop is done:
void makeUpper( char orig[], char result[] )
{
int k = 0;
while ( orig[k] != '\0' )
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
k++;
}
result[k] = '\0';
}
I need to build a program that receives up to 30 chars from the user, and then to play with it.
For example, I need to reverses the sentence and then print it, or to rotate it.
I have been trying to copy the words of the sentence one by one to a matrix of [30][31], but it does not working... any ideas?
I cannot use pointers...
thanks for the help :)
#include <stdio.h>
#include <string.h>
void main(){
int i=0,
j=0,
wrongData=0,
charCounter=0,
word=0,
letter=0;
char st[100],
arr[100]={0},
mat[30][31]={0};
printf("Please, enter your sentence >");
gets(st);
while(i<strlen(st)){
if('A'<=st[i] && st[i]<='Z'){
charCounter++;
arr[j] = st[i];
i++;
j++;
} else if(st[i]==' '){
arr[j] = ' ';
i++;
j++;
while(st[i] == ' '){
i++;
}
} else if(st[i]=='\0'){
arr[j] = '\0';
break;
} else {
puts("ERROR: Incorrect data, try again.");
wrongData=1;
break;
}
if(wrongData==0){
if(charCounter>30){
puts("ERROR: Incorrect data, try again.");
}
}
}
puts(st);
puts(arr);
if(arr[j]==' '){
word++;
}
while(arr[j]!=' ' && letter<32){
strcpy(mat[word],arr);
}
if(arr[j]=='\0'){
mat[word][letter]=arr[j];
}
puts(mat[word]);
}
Taking into account your comment
the problem is that i need to reverse the words not the letters... for
example: if the string is cats hates dogs, i need to get at the end
dogs hates cats
then I think you mean something as the following
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char * reverse_words( char s[] )
{
for ( char *p = s, *q = s; *p; p = q )
{
while ( isspace( ( unsigned char )*p ) ) ++p;
q = p;
while ( *q && !isspace( ( unsigned char )*q ) ) ++q;
for ( size_t i = 0; i < ( q - p ) / 2; i++ )
{
char c = p[i];
p[i] = q[-i-1];
q[-i-1] = c;
}
}
for ( size_t i = 0, n = strlen( s ); 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[] = "cats hates dogs";
puts( s );
puts( reverse_words( s ) );
return 0;
}
The program output is
cats hates dogs
dogs hates cats
Here is another approach. The idea is to go through the string and record the index where each word starts and ends. Then the words can be printed in reverse order afterwards. (btw - it will also be easy to rotate the words).
#include<stdio.h>
#include <string.h>
int main() {
char st[100] = "here we go again";
int start[30] = { 0 };
int end[30] = { 0 };
int count = 0;
int len = strlen(st);
int i, j;
// Find start and end index of each word
start[0] = 0;
for(i = 0; i < len; ++i)
{
if (st[i] == ' ')
{
end[count] = i;
++count;
start[count] = i + 1;
}
}
end[count] = len;
// Print the words in reverse order
for(i=count; i >= 0; --i)
{
for (j = start[i]; j < end[i]; ++j)
{
printf("%c", st[j]);
}
printf(" ");
}
printf("\n");
return 0;
}
output:
again go we here
fix your approach like this:
#include <stdio.h>
//#include <string.h>
#define MAX_LEN 30
int main(void){
int i, j, n, word;
char st[100], arr[100], mat[MAX_LEN / 2][MAX_LEN + 1];
printf("Please, enter your sentence (up to %d chars and A-Z or space)\n>", MAX_LEN);fflush(stdout);
scanf("%99[^\n]%*c", st);
//validate and reduce of spaces
for(j = i = 0; st[i]; ++i){
if(i > MAX_LEN){
fputs("ERROR: Incorrect data, try again.\n", stderr);
return 1;
}
if('A'<=st[i] && st[i]<='Z'){
arr[j++] = st[i];
} else if(st[i]==' '){
arr[j++] = ' ';
while(st[++i] == ' ')//Skip a continuous space
;
--i;//one back for next loop
} else {
fputs("ERROR: Incorrect data, try again.\n", stderr);
return 1;
}
}
arr[j] = '\0';//st[i]=='\0' never become true in loop
#if DEBUG
puts(st);
puts(arr);
#endif
//split to word
for(word = j = i = 0; arr[i];){
while(arr[i] == ' ')
++i;//skip space
while(arr[i] != ' ' && arr[i] != '\0')
mat[word][j++] = arr[i++];
mat[word++][j] = '\0';
j = 0;
}
#if DEBUG
for(i = 0; i < word; ++i)
puts(mat[i]);
#endif
puts("reverse word");
for(i = 0; i < word; ++i){
if(i)
putchar(' ');
printf("%s", mat[word-1-i]);
}
puts("\nrotate word");
printf("Please, enter number of rotate\n>");fflush(stdout);
scanf("%d", &n);
for(i = 0; i < word; ++i){
if(i)
putchar(' ');
printf("%s", mat[(i+n)%word]);//rotate left
}
}
I have a code like this:
char* s[4][10] = { "abc\0", "aab\0", "cbb\0" };
a want to type a character, like.. 'a', and iterate through the array of strings, check on each string if there's 'a' on it, and then count how many there's on it..
In this case, what I wanted to get is "abc" : 1, "aab" : 2, "cbb" : 0 ...
how can I do the loops to get this result?
char input = '\0';
scanf("%c", &input);
int i, j;
for(i=0; i<4; i++)
{
int count = 0;
for(j=0;j<10;j++)
{
if(s[i][j] == input) count++;
}
printf("%s : %d", s[i], count);
}
although please note, that simply copying and pasting will not teach you anything.
Here is a demonstrative program that shows how you can deal with different declarations of arrays
#include <stdio.h>
int main(void)
{
char* s[4][10] = { { "abc", "aab", "cbb" } };
for ( int i = 0; i < 4; i++ )
{
for ( int j = 0; j < 10; j++ )
{
if ( s[i][j] )
{
size_t count = 0;
for ( char *p = s[i][j]; *p != '\0'; ++p )
{
if ( *p == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", s[i][j], count );
}
}
}
printf( "\n" );
char* t[4] = { "abc", "aab", "cbb" };
for ( char **p = t; *p != NULL; ++p )
{
size_t count = 0;
for ( char *q = *p; *q != '\0'; ++q )
{
if ( *q == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", *p, count );
}
printf( "\n" );
char u[4][10] = { "abc", "aab", "cbb" };
for ( int i = 0; i < 4; i++ )
{
if ( u[i][0] != '\0' )
{
size_t count = 0;
for ( char *p = u[i]; *p != '\0'; ++p )
{
if ( *p == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", u[i], count );
}
}
return 0;
}
The program output is
"abc": 1
"aab": 2
"cbb": 0
"abc": 1
"aab": 2
"cbb": 0
"abc": 1
"aab": 2
"cbb": 0
It seems that you mean either the second variant of the array declaration or the third variant of the array declaration. The first variant looks strange.:)
Take into account that string literals already contain terminating zero. So there is no sense to write, for example
"abc\0"
It is enough to write simply
"abc"
The sizeof( "abc" ) is equal to 4 due to the presence of the terminating zero.
#include <stddef.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char s[10][4] = { "abc", "aab", "cbb" };
size_t i;
for (i = 0; i != sizeof(s) / sizeof(s[0]); i++) {
fprintf(stdout, "%zu: %s\n", i, s[i]);
}
return 0;
}
or
#include <stddef.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *s[4] = { "abc", "aab", "cbb" };
size_t i;
for (i = 0; i != 3; i++) {
fprintf(stdout, "%zu: %s\n", i, s[i]);
}
return 0;
}
Note that the original declaration
char* s[4][10] = { "abc\0", "aab\0", "cbb\0" };
had several errors:
char * instead of char
[4][10] instead of [10][4]
"abc\0" instead of "abc" (the trailing '\0' is implicit).