C: Printing from char array produces erroneous characters

≯℡__Kan透↙ 提交于 2021-01-27 19:15:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!