问题
Solutions for K. N. King's C Programming: A Modern Approach, 2nd Edition, Chapter 8, Programming Project 14, produces different outputs both correct and incorrect. Examples shown below:
Reversal of sentence: you can't swallow a cage can you?
Reversal of sentence: you can't swallow a cage can you�(�?
Reversal of sentence: you can't swallow a cage can you��x�?
Reversal of sentence: you can't swallow a cage can you�Ց�?
As shown by the example input, correct output should be:
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: you can't swallow a cage can you?
My own solution and below solution (courtesy of Github user @williamgherman; slightly modified for sake of readability) both produces the different outputs.
#include <stdio.h>
int main(void)
{
char ch, terminator, sentence[100] = {0};
int i = 0, j;
printf("Enter a sentence: ");
for (i = 0; (ch = getchar()) != '\n' && i < 100; i++) {
if (ch == '.' || ch == '!' || ch == '?') {
terminator = ch;
break;
}
sentence[i] = ch;
}
printf("Reversal of sentence: ");
while (i >= 0) {
while (sentence[--i] != ' ' && i != 0)
;
j = i == 0 ? 0 : i + 1;
while (sentence[j] != ' ' && sentence[j] != '\0')
putchar(sentence[j++]);
if (i > 0)
putchar(' ');
}
printf("%c\n", terminator);
return 0;
}
Despite double checking the code, and running through the example input on paper, I've not been able to find an answer.
How come the code produces these different outputs, correct as well as incorrect? What produces the erroneous characters?
回答1:
Most likely, the problem is with the exit condition for the while
loop used to print the sentence in reverse
while (i >= 0) {
while (sentence[--i] != ' ' && i != 0) ;
....
Consider the case where the code is going to print the first word (i=3):
- The second while will decrement i all the way to 0
- then the code will print the word 'you' (positions 0 to 2, inclusive)
- At this point i=0, the first while still is true
- The second while will decrement i to -1, and will continue to decrement it to -2, -3, until a space is found.
- The code will print the word with indices of -1, -2, -3, and will print a string based on those undefined values.
回答2:
Yes, as stated in the answer above the problem is within this block
while (i >= 0) {
while (sentence[--i] != ' ' && i != 0) ;
....
You should change the i != 0
part into i >= 0
, this should solve the thing
The problem is that i decrementation sentence[--i]
happens before i != 0
and so imagine the while loop starting with i = 0 - this will mean that sentence[i - 1]
will (likely) not be ' '
and i will not be equal to zero.
回答3:
For starters the program has undefined behavior because the variable terminator
is not initialized. The user can press the Enter key without supplying one of these characters ".!?"
for (i = 0; (ch = getchar()) != '\n' && i < 100; i++) {
^^^^^^^
In this case this statement
printf("%c\n", terminator);
will output an indeterminate value.
Moreover the user can interrupt the loop pressing a corresponding key combination but the loop does not process such a situation.
If the user pressed the Enter key in the very beginning of the loop then i
will be equal to 0
In this case the inner while loop
while (i >= 0) {
while (sentence[--i] != ' ' && i != 0)
^^^
;
will invoke undefined behavior.
Moreover before the terminating character (".!?"
) the sentence can contain spaces. Thus this loop
while (sentence[--i] != ' ' && i != 0)
;
j = i == 0 ? 0 : i + 1;
again will be incorrectly terminated. That is j will be equal to i + 1 where a zero character is stored (provided that the user did not entered all 100 elements of the array sentence).
Apart from this the program does not output existent number of spaces between words. It only tries to output one space
putchar(' ');
Take into account that the user can enter for example the tab character '\t'
instead of the space character ' '
.
Below there is shown how the program can be written.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
const char *punctuation = ".?!";
enum { N = 100 };
char s[N] = "";
char terminator = '\0';
printf( "Enter a sentence: " );
size_t n = 0;
for ( int c; n < N && ( c = getchar() ) != EOF && c != '\n'; n++ )
{
if ( strchr( punctuation, c ) )
{
terminator = c;
break;
}
s[n] = c;
}
printf( "Reversal of sentence: " );
putchar( '\"' );
size_t i = 0;
while ( i != n && isblank( ( unsigned char )s[i] ) ) putchar( s[i++] );
for ( size_t j = n; i != n; )
{
while ( i != n && !isblank( ( unsigned char )s[i] ) ) i++;
while ( isblank( ( unsigned char )s[j-1] ) ) j--;
size_t k = j;
while ( j != 0 && !isblank( ( unsigned char )s[j-1] ) ) j--;
for ( size_t l = j; l != k; l++ ) putchar( s[l] );
while ( i != n && isblank( ( unsigned char )s[i] ) ) putchar( s[i++] );
}
if ( terminator ) putchar( terminator );
putchar( '\"' );
return 0;
}
The program output might look like
Enter a sentence: you can cage a swallow can't you?
Reversal of sentence: "you can't swallow a cage can you?"
As you can see the program preserved all spaces contained in the entered sentence.
来源:https://stackoverflow.com/questions/63635543/c-printing-from-char-array-produces-erroneous-characters