reversing only certain words of a string - c

I have a string with the name "Mustang Sally Bob"
After i run my code i want the string output to be like this: gnatsuM yllaS boB
My approach is to count the words until the space and save the index of where the space is located in the string. then Then I want to print the characters starting from the space backwards.
#include <stdio.h>
int main()
{
char* test="Mustang Sally Bob";
int length; //string length
int x;
for(length=0;test[length] !=0&&test[length];length++); //get string length
int counter;
int words = 0;
int space_index =0;
for(counter=0;counter<length;counter++) {
words++;
if(test[counter]==' ') {
space_index=counter;
for(x=space_index-1;x>=words;x--) {
printf("%c",test[x]);
}
words=0;
space_index = 0;
}
}
return 0;
}
but when I execute this code the output I get is yllaS g
does anyone know why i cant get the full string?

In general the approach is incorrect.
For example an arbitrary string can start with blanks. In this case the leading blanks will not be outputted.
The last word is ignored if after it there is no blank.
The variable words does not keep the position where a word starts.
Calculating the length of a string with this loop
for(length=0;test[length] !=0&&test[length];length++);
that can be written simpler like
for ( length = 0; test[length] != '\0' ; length++ );
is redundant. You always can rely on the fact that strings are terminated by the zero-terminating character '\0'.
I can suggest the following solution
#include <stdio.h>
int main( void )
{
const char *test = "Mustang Sally Bob";
for ( size_t i = 0; test[i] != '\0'; )
{
while ( test[i] == ' ' ) putchar( test[i++] );
size_t j = i;
while ( test[i] != '\0' && test[i] != ' ' ) i++;
for ( size_t k = i; k != j; ) putchar( test[--k] );
}
return 0;
}
The program output is
gnatsuM yllaS boB
You could append the program with a check of the tab character '\t' if you like. In C there is the standard C function isblank that performs such a check.
Here is a demonstrative program that uses the function isblank. I also changed the original string literal.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const char *test = " Mustang\tSally\tBob ";
puts( test );
for ( size_t i = 0; test[i] != '\0'; )
{
while ( isblank( ( unsigned char )test[i] ) ) putchar( test[i++] );
size_t j = i;
while ( test[i] != '\0' && !isblank( ( unsigned char)test[i] ) ) i++;
for ( size_t k = i; k != j; ) putchar( test[--k] );
}
putchar( '\n' );
return 0;
}
The program output is
Mustang Sally Bob
gnatsuM yllaS boB

Related

Is this a good way to remove spaces from a string in C? note, I am only using the <stdio.h> header file. Also I am new to computer science

int remove_whitespace(char* string, int size) /* input parameters: the character array, size of that array */
{
int i = 0, j = 0, num = 0; /* i - counter variable | j - counter variable | num - number of white spaces */
for (i; i < size; i++)
{
if (string[i] == ' ')
{
for (j = i; j < size - 1; j++)
{
string[j] = string[j + 1];
}
num++;
}
}
return num; /* returns the number of white spaces */
}
Count the 5 variables used by the function presented. Five! Are they all being incremented correctly? A pair of nested for() loops and an if() conditional. Are the indexes the correct index for the purpose??
Depending on the parameters passed, will whitespace be compacted but leave trailing characters in the array? Is this why the caller receives the "shrinkage" quantity?
Your title suggests "string", yet the code presented indicates an array of characters (without consideration for a C string terminating '\0'.) Taking the approach that you want to remove SP's (0x20) from a null terminated C string, the following will do that:
void stripSP( char *s ) {
for( char *d = s; (*d = *s) != '\0'; s++ ) d += *d != ' ';
}
One line of code utilising two pointers.
You could pass/use a second parameter that is the character to be expunged, or change the d += *d != ' '; to d += !isspace(*d); to compact-out any whitespace characters (incl. '\t', '\r' & '\n').
Obviously, this leads to possibilities of stripping out punctuation, or whatever you'd like removed. If the caller needs to know the new length of the string, the caller can invoke strlen().
It's one little line of source code, amenable to customising to suit your needs. For instance, the function could preserve and return the start address for chaining function calls.
For starters the function should be declared like
size_t remove_char( char *string, size_t size, char c );
That is you should not write a separate function if you will want to remove another character instead of the space character ' '. Always try to write more general functions.
Also the function should return the size of the character array without the removed character.
Using nested for loops when all characters after the removed character are moved to the left is inefficient.
The function can be defined the following way
size_t remove_char( char *string, size_t size, char c )
{
size_t n = 0;
for ( size_t i = 0; i < size; i++ )
{
if ( string[i] != c )
{
if ( n != i ) string[n] = string[i];
++n;
}
}
return n;
}
Here is a demonstration program.
#include <stdio.h>
size_t remove_char( char *string, size_t size, char c )
{
size_t n = 0;
for ( size_t i = 0; i < size; i++ )
{
if ( string[i] != c )
{
if ( n != i ) string[n] = string[i];
++n;
}
}
return n;
}
int main( void )
{
char s[10] = "H e l l o";
size_t n = remove_char( s, sizeof( s ), ' ' );
printf( "%zu: %s\n", n - 1, s );
}
The program output is
5: Hello
If you want to remove a character from a string then the function can be declared like
char * remove_char( char *string, char c );
because you can determine the length of a string within the function by founding the terminating zero character '\0'.
Here is a demonstration program
#include <stdio.h>
char * remove_whitespace( char* string, char c )
{
if ( *string )
{
char *dsn = string, *src = string;
do
{
if ( *src != c )
{
if ( dsn != src ) *dsn = *src;
++dsn;
}
} while ( *src++ );
}
return string;
}
int main( void )
{
char s[10] = "H e l l o";
puts( remove_whitespace( s, ' ' ) );
}
The program output is
Hello

Keep getting gibberish output when trying to print an array in C

I am trying to write a program that reverses words in a sentence, the code is able to do that but also prints gibberish in between. (see below code for sample)
#include <stdio.h>
#define MAX_VALUE 50
int main(){
char c[MAX_VALUE],
b[MAX_VALUE];
int i = 0, j = 0;
while ((c[i] = getchar()) != '\n'){
i++;
}
for(i = MAX_VALUE; i >= 0; i--){
if (c[i] == ' '){
for(j = i+1; j < MAX_VALUE; j++){
if (c[j] != ' '){
printf("%c", c[j]);
}
else{
break;
}
}
printf(" ");
}
}
while (c[i] != ' '){
printf("%c", c[i]);
i++;
}
}
Loop goes backwards when it detects a space it prints the word until it finds another space then goes backwards again from where it left off last
The input and output expected:
input: test a is this
output: this is a test
What I get:
input: test a is this
output:
this
`����l�,+�D �=� is a test
This for loop
while ((c[i] = getchar()) != '\n'){
i++;
}
can write outside the array c and store the new line character '\n' in the array.
And this output consisting from two lines
this
`����l�,+�D �=� is a test
demonstrates that the new line character was stored in the array.
Also you forgot to append the entered sequence of characters with the zero terminating character '\0' to form a string.
You could write the while loop the following way
int ch;
while ( i < MAX_VALUE - 1 && ( ch = getchar() ) != '\n' && ch != EOF ){
c[i++] = ch;
}
c[i] = '\0';
Or if you want store the entered sequence without the terminating zero character '\0' then the loop can look like
int ch;
while ( i < MAX_VALUE && ( ch = getchar() ) != '\n' && ch != EOF ){
c[i++] = ch;
}
In this case the variable i will contain the number of entered symbols in the array and you should use its value instead of the value MAX_VALUE in the following loops.
This outer for loop
for(i = MAX_VALUE; i >= 0; i--){
is incorrect because the user can enter a sequence of symbols that contains less than MAX_VALUE symbols. You should either use standard string function strlen (if you appended the sequence with the terminating zero character '\0') to determine the length of the string stored in the array or the value of the variable i as mentioned above that denotes the number of entered symbols.
And it is not enough to check this condition
if (c[i] == ' '){
because the leading spaces can be absent in the entered string. So you need to check also whether i is equal to 0. Otherwise the output can be incorrect if the sequence contains for example only one word.
The inner for loop
for(j = i+1; j < MAX_VALUE; j++){
again is incorrect by the same reason of using MAX_VALUE in the condition.
Pay attention to that the array b
char c[MAX_VALUE],
b[MAX_VALUE];
is not used in your program.
Using your approach I can suggest the following solution to output words of a string in the reverse order shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main( void )
{
const char *s = "test a is this";
for( size_t i = strlen( s ); i != 0; )
{
while ( i != 0 && isblank( ( unsigned char )s[i-1]) )
{
putchar( s[--i] );
}
size_t j = i;
while ( j != 0 && !isblank( ( unsigned char )s[j-1]) )
{
--j;
}
if ( j != i )
{
size_t last = i;
i = j;
while ( j != last )
{
putchar( s[j++] );
}
}
}
putchar( '\n' );
}
The program output is
this is a test
The code uses two arrays and two 'counters', and fiddles around with individual characters one-at-a-time. It's easy to get lost and use an upper bound that is outside the array size.
Simplify! This "reversal" is an excellent example of when recursion should be the go-to method of solving the problem.
#include <stdio.h>
#include <string.h>
void output( char *p ) {
if( (p = strtok( p, " " )) == NULL ) return;
output( NULL );
printf( "%s ", p );
}
int main() {
char str[] = "The quick brown fox jumps over the dogs";
output( str );
return 0;
}
dogs the over jumps fox brown quick The
Some purists may want an entire buffer to be assembled before printing. This resulting string includes an invisible SP at the end that could be lopped off if desired.
#include <stdio.h>
#include <string.h>
char *revWords( char *dst, char *p ) {
if( (p = strtok( p, " " )) == NULL ) return NULL;
revWords( dst, NULL );
return strcat( strcat( dst, p ), " " );
}
int main() {
char str[] = "The quick brown fox jumps over the dogs";
char buf[sizeof str + 1 + 1] = { 0 }; // important to initialise
puts( revWords( buf, str ) );
return 0;
}
For an alternative, here's a version without recursion. It requires, like above, a mutable buffer holding the string.
#include <stdio.h>
#include <ctype.h>
int main() {
char str[] = " The quick brown fox jumps over the dogs ";
int i = 0;
// note: 1 string buffer, 1 index variable
for( i = 0; str[i]; i++ ) ; // loop
while( i >= 0 ) {
while( i >= 0 && !isalnum( str[ i ] ) ) str[i--] = '\0';
while( i >= 0 && isalnum( str[ i ] ) ) i--;
printf( "%s ", str + i + 1 );
}
puts( "" );
return 0;
}

Output a string with a new character in each line, forming a right triangle

Trying to output a string that has been assigned to an array, with different characters on each new line, eventually creating a right triangle. But I'm completely stuck. I believe some for loops should be involved to iterate over each character but I don't know how to increase the array index on each new line to output one character more than the line before.
This is a sketch that allowed me to visualize this:
string[0]
string[1] + string[2]
string[3] + string[4] + string[5]
string[6] + string[7] + string[8] + string[9]
For example, let's take into account this line of code: char string[50] = "Assignment";
The output desired would look like this:
A
s s
i g n
m e n t
Any guidance would be appreciated.
You can do it using only one while loop.
Here is a demonstrative program
#include <stdio.h>
void triangle_output( const char *s )
{
size_t n = 1;
size_t i = n;
while ( *s )
{
if ( i-- == 0 )
{
putchar( '\n' );
i = n++;
}
putchar( *s++ );
putchar( ' ' );
}
if ( i != n - 1 ) putchar( '\n' );
}
int main(void)
{
char *s = "Assignment";
triangle_output( s );
return 0;
}
The program output is
A
s s
i g n
m e n t
Or the function can be rewritten the following way
void triangle_output( const char *s )
{
size_t n = 1;
size_t i = 0;
while ( *s )
{
putchar( *s++ );
putchar( ' ' );
if ( ++i == n )
{
putchar( '\n' );
i = 0;
++n;
}
}
if ( i != 0 ) putchar( '\n' );
}
This function will print the triangle. If the string have enough chars to print the whole last line it will print -.
void printTriangle(const char *s)
{
size_t length = strlen(s), pos = 0;
for(size_t line = 1; line < -1; line++)
{
for(size_t ch = 1; ch <= line; ch++)
{
if(pos < length) printf("%c", *s++);
else printf("-");
pos++;
}
printf("\n");
if(pos >= length) break;
}
}
int main(void)
{
printTriangle("Assignment123");
}
https://godbolt.org/z/xxM1eEY6a

How to reverse every characters in words in a string in C language? [duplicate]

I have a string with the name "Mustang Sally Bob"
After i run my code i want the string output to be like this: gnatsuM yllaS boB
My approach is to count the words until the space and save the index of where the space is located in the string. then Then I want to print the characters starting from the space backwards.
#include <stdio.h>
int main()
{
char* test="Mustang Sally Bob";
int length; //string length
int x;
for(length=0;test[length] !=0&&test[length];length++); //get string length
int counter;
int words = 0;
int space_index =0;
for(counter=0;counter<length;counter++) {
words++;
if(test[counter]==' ') {
space_index=counter;
for(x=space_index-1;x>=words;x--) {
printf("%c",test[x]);
}
words=0;
space_index = 0;
}
}
return 0;
}
but when I execute this code the output I get is yllaS g
does anyone know why i cant get the full string?
In general the approach is incorrect.
For example an arbitrary string can start with blanks. In this case the leading blanks will not be outputted.
The last word is ignored if after it there is no blank.
The variable words does not keep the position where a word starts.
Calculating the length of a string with this loop
for(length=0;test[length] !=0&&test[length];length++);
that can be written simpler like
for ( length = 0; test[length] != '\0' ; length++ );
is redundant. You always can rely on the fact that strings are terminated by the zero-terminating character '\0'.
I can suggest the following solution
#include <stdio.h>
int main( void )
{
const char *test = "Mustang Sally Bob";
for ( size_t i = 0; test[i] != '\0'; )
{
while ( test[i] == ' ' ) putchar( test[i++] );
size_t j = i;
while ( test[i] != '\0' && test[i] != ' ' ) i++;
for ( size_t k = i; k != j; ) putchar( test[--k] );
}
return 0;
}
The program output is
gnatsuM yllaS boB
You could append the program with a check of the tab character '\t' if you like. In C there is the standard C function isblank that performs such a check.
Here is a demonstrative program that uses the function isblank. I also changed the original string literal.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const char *test = " Mustang\tSally\tBob ";
puts( test );
for ( size_t i = 0; test[i] != '\0'; )
{
while ( isblank( ( unsigned char )test[i] ) ) putchar( test[i++] );
size_t j = i;
while ( test[i] != '\0' && !isblank( ( unsigned char)test[i] ) ) i++;
for ( size_t k = i; k != j; ) putchar( test[--k] );
}
putchar( '\n' );
return 0;
}
The program output is
Mustang Sally Bob
gnatsuM yllaS boB

Splitting a string into chunks.

I'm trying to split a string into chunks of 6 using C and I'm having a rough time of it. If you input a 12 character long string it just prints two unusual characters.
#include <stdio.h>
#include <string.h>
void stringSplit(char string[50])
{
int counter = 0;
char chunk[7];
for (unsigned int i = 0; i < strlen(string); i++)
{
if (string[i] == ' ')
{
continue;
}
int lastElement = strlen(chunk) - 1;
chunk[lastElement] = string[i];
counter++;
if (counter == 6)
{
printf(chunk);
memset(chunk, '\0', sizeof chunk);
counter = 0;
}
}
if (chunk != NULL)
{
printf(chunk);
}
}
int main()
{
char string[50];
printf("Input string. \n");
fgets(string, 50, stdin);
stringSplit(string);
return(0);
}
I appreciate any help.
Your problem is at
int lastElement = strlen(chunk) - 1;
Firstly, strlen counts the number of characters up to the NUL character. Your array is initially uninitialized, so this might cause problems.
Assuming your array is filled with NULs, and you have, let's say, 2 characters at the beginning and you are looking to place the third one. Remember that your 2 characters are at positions 0 and 1, respectively. So, strlen will return 2 (your string has 2 characters), you subtract one, so the lastElement variable has the value 1 now. And you place the third character at index 1, thus overwriting the second character you already had.
Also, this is extremely inefficient, since you compute the number of characters each time. But wait, you already know how many characters you have (you count them in counter, don't you?). So why not use counter to compute the index where the new character should be placed? (be careful not to do the same mistake and overwrite something else).
The function is wrong.
This statement
int lastElement = strlen(chunk) - 1;
can result in undefined behavior of the function because firstly the array chunk is not initially initialized
char chunk[7];
and secondly after this statement
memset(chunk, '\0', sizeof chunk);
the value of the variable lastElement will be equal to -1.
This if statement
if (chunk != NULL)
{
printf(chunk);
}
does not make sense because the address of the first character of the array chunk is always unequal to NULL.
It seems that what you mean is the following.
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[] )
{
const size_t N = 6;
char chunk[N + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == N )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
stringSplit( s );
}
The program output is
Youand
Iarebe
ginner
sinC
You can modify the function such a way that the length of the chunk was specified as a function parameter.
For example
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[], size_t n )
{
if ( n )
{
char chunk[n + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == n )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
for ( size_t i = 3; i < 10; i++ )
{
stringSplit( s, i );
puts( "" );
}
}
The program output will be
You
and
Iar
ebe
gin
ner
sin
C
Youa
ndIa
rebe
ginn
ersi
nC
Youan
dIare
begin
nersi
nC
Youand
Iarebe
ginner
sinC
YouandI
arebegi
nnersin
C
YouandIa
rebeginn
ersinC
YouandIar
ebeginner
sinC

Resources