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;
}
Related
I'm trying to make a program that counts all the words that start and end with the same character. in C
It tells me correctly which is the first and which is the last, I don't know how to make it show me the ones that are equal.
#include <stdio.h>
#include <string.h>
int main()
{
char s[50];
printf("Introdu propozitia : ");
gets(s);
int i, j = 0;
// Traversing the Character array
for (i = 0; i < strlen(s); i++) {
// To store first character of
// String if it is not a
// whitespace.
if (i == 0 && s[i] != ' ') {
printf("%c ", s[i]);
}
if (s[i] == ' ')
printf("%c", s[i -1]);
// To check whether Character
// is first character of
// word and if yes store it.
else if (i > 0 && s[i - 1] == ' ') {
printf(" %c ", s[i]);
}
else if (i>0 && s[i] == ' ')
printf("%c", s[i -1]);
if(s[i]==s[i-1])
Total ++;
printf("\n Sunt : %d", Total);
}
return 0;
}
For starters the function gets is unsafe and is not supported by the C Standard. Instead use either scanf or fgtes.
This if statement
if(s[i]==s[i-1])
Total ++;
does not make sense.
Using the function strlen in the for loop is inefficient and redundant.
To find starts and ends of words in a string you can use standard string functions strspn and strcspn.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
char s[50];
printf( "Introdu propozitia : " );
fgets( s, sizeof( s ), stdin );
size_t count = 0;
const char *delim = " \t\n";
for ( const char *p = s; *p; )
{
p += strspn( p, delim );
size_t n = strcspn( p, delim );
if (n != 0 && p[0] == p[n - 1])
{
++count;
}
p += n;
}
printf( "\nSunt : %zu\n", count );
}
Its output might look like
Introdu propozitia : 123454321 2345432 34543 454 5
Sunt : 5
If you want to output the words that satisfy the condition then add one statement in the if statement of the program
if (n != 0 && p[0] == p[n - 1])
{
++count;
printf( "%.*s\n", ( int )n, p );
}
Write a program that allows the user to enter a sentence. The program should then print the sentence starting with the third word.
For example it should print like:
Enter a sentence: Welcome to the course in programming
the course in programming
The problem with my code is that it only print the sentence starting with the second word instead of the thrird.And I wonder what is wrong with my code?
#include <stdio.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char arr[SIZE];
char* p = NULL;
int count = 0;
printf("Enter a sentence:");
fgets(arr, SIZE, stdin);
for (int i = 0; i < SIZE; i++) {
if (arr[i] == ' ') {
count++;
}
}
if (count < 3 ) {
printf("The sentence is to short!\n");
}
else {
count = 0;
for (int i = 0; i < strlen(arr); i++) {
if (arr[i] == ' ') {
count++;
}
if (count == 2) {
p = &arr[i + 1];
}
}printf("%s\n", p);
}
return 0;
}
I do not know why the program outputs the sentence from the second word instead of the third word but in any case this for loop
for (int i = 0; i < strlen(arr); i++) {
if (arr[i] == ' ') {
count++;
}
if (count == 2) {
p = &arr[i + 1];
}
}
is incorrect because when count is equal to 2 then for each character in the string that is not a space the value of p is changed due to this if statement
if (count == 2) {
p = &arr[i + 1];
}
At least you need to insert a break statement like
if (count == 2) {
p = &arr[i + 1];
break;
}
Also the first for loop
for (int i = 0; i < SIZE; i++) {
if (arr[i] == ' ') {
count++;
}
}
invokes undefined behavior because instead of SIZE you need to use strlen( arr ).
And moreover you need to remove the trailing new line character '\n' from the string before calculating the number of words.
Apart from that the approach in any case is incorrect because it will not work when a string contains adjacent spaces.
You're trying to do to much with too much. Simplifying the code makes life easier.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 100
int main(void) {
printf( "Enter a sentence:" );
/* ONE buffer to hold the input */
char arr[SIZE] = { 0 }; // define (and initialise) variables close to use
fgets( arr, SIZE, stdin );
/* ONE counter (index) to traverse the input */
int i = 0;
while( arr[i] && isspace( arr[i] ) ) i++; // skip over leading whitespace (not considered)
while( arr[i] && !isspace( arr[i] ) ) i++; // skip over the 1st "word" (if present )
while( arr[i] && isspace( arr[i] ) ) i++; // skip over intervening whitespace (if present )
while( arr[i] && !isspace( arr[i] ) ) i++; // skip over the 2nd "word" (if present )
while( arr[i] && isspace( arr[i] ) ) i++; // skip over intervening whitespace (if present )
if( arr[i] )
printf( "%s\n", arr + i );
else
printf("The sentence is to short!\n");
return 0;
}
Enter a sentence: Now is the time for all good men
the time for all good men
You can see the repetitive code (testing for spaces, then testing for non-spaces.) This could be "packaged-up" in a function that takes a couple of parameters. I'll leave that as an exercise. (Perhaps look into strpbrk() strspn() and strcspn()...)
I'm doing the exercises from C Programming Language, the one where you need to make a function to reverse a line. So I did and it works sometimes. But only some times. With the same test it gives different results. I really don't get it, and would appreciate some help. 3 tries out of 4 it would print around 150 spaces and 1 out of 4 it would print the reversed line just like I wanted, though with some junk in the end for some reason.
I was thinking of doing it with pointers, but couldn't figure them out as of now.
Here's my code:
#include <stdio.h>
void reverse(char theline[150]){
int i, j;
char tmp[150];
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
for (j = 0; i >= 0; j++){
theline[j] = tmp[i];
i--;
}
}
int main() {
char line[150];
char c;
int counter = 0;
do {
counter = 0;
while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
line[counter] = c;
counter++;
}
if (counter > 80){
reverse(line);
printf("%s\n", line);
}
}
while (c != EOF);
return 0;
}
I compile it with "gcc -g -Wall program -o test" and the compiler doesn't give me any errors or warnings. My OS is Ubuntu and I test it with "./test < longtext.txt". This text file has a few lines of different length.
After this loop
while (((c = getchar()) != '\n') && (c != EOF)) { //one line loop
line[counter] = c;
counter++;
}
the character array line does not contain a string because the stored characters are not appended with the terminating zero character '\0'.
So this loop within the function
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
invokes undefined behavior.
You need to append the array with the terminating zero character '\0'.
But even if the passed character array will containe a string the second for loop
for (i = 0; theline[i] != 0; i++){
tmp[i] = theline[i];
}
for (j = 0; i >= 0; j++){
theline[j] = tmp[i];
i--;
}
writes the terminating zero character '\0' in the first position if the array theline. As a result you will get an empty string.
Also the function shall not use the magic number 150 and an auxiliary array.
Pay attention to that the variable c should be declared as having the type int. In general the type char can behave either as the type signed char or unsigned char depending on compiler options. If it will behave as the type unsigned char then this condition
c != EOF
will always evaluate to true.
Without using standard C string functions the function can be declared and defined the following way
char * reverse( char theline[] )
{
size_t i = 0;
while ( theline[i] != '\0' ) i++;
size_t j = 0;
while ( j < i )
{
char c = theline[j];
theline[j++] = theline[--i];
theline[i] = c;
}
return theline;
}
Here is a demonstration program
#include <stdio.h>
char * reverse( char theline[] )
{
size_t i = 0;
while ( theline[i] != '\0' ) i++;
size_t j = 0;
while ( j < i )
{
char c = theline[j];
theline[j++] = theline[--i];
theline[i] = c;
}
return theline;
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
puts( reverse( s ) );
}
The program output is
Hello World!
!dlroW olleH
Why muck-around with reversing a buffer when you can simply store-up the entered characters as they arrive.
#include <stdio.h>
int main() {
for( ;; ) {
char line[ 150 ];
int c, counter = sizeof line;
line[ --counter ] = '\0';
// NB: EOF is an int, not a char
while( ( c = getchar() ) != '\n' && c != EOF && counter > 0 )
line[ --counter ] = (char)c;
printf( "%s\n\n", line + counter );
counter = sizeof line;
}
return 0;
}
Output:
the quick
kciuq eht
Once upon a time in a land far awy
ywa raf dnal a ni emit a nopu ecnO
I wish I was what I was when I wished I was what I am now.
.won ma I tahw saw I dehsiw I nehw saw I tahw saw I hsiw I
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
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