Home > front end >  Why printing arrays of characters gives garbled characters?
Why printing arrays of characters gives garbled characters?

Time:09-09

I'm reading characters into an array and try to print them out. The code is given below.

#include <stdio.h>
#include <ctype.h>

#define N 50

int read_message(char a[], int n)
{
    char ch;
    int i = 0;

    printf("Enter a message: ");
    for (i = 0; (ch = getchar()) != EOF && ch != '\n'; i  ) {
        if (toupper(ch) >= 'A' && toupper(ch) <= 'Z') {
            a[i] = tolower(ch);
        }
    }

    return i;
}

void print_message(char a[], int n)
{
    int i;

    for (i = 0; i < n; i  )
        printf("%c", a[i]);

    printf("\n");
}

int main()
{
    char message[N];
    int message_len = read_message(message, N);

    print_message(message, message_len);
}

When I enter "He h", it shows "he蘦".

However, if I change the read_message() in the following way, the problem is solved.

int read_message(char a[], int n)
{
    char ch;
    int i = 0;

    printf("Enter a message: ");
    while ((ch = getchar()) != EOF && ch != '\n') {
        if (toupper(ch) >= 'A' && toupper(ch) <= 'Z') {
            a[i] = tolower(ch);
            i  ;
        }
    }

    return i;
}

I heard that for and while are equivalent, so I have no idea why this is happening.

CodePudding user response:

In the first version of read_message() you have the following issues:

  1. int ch as getchar() returns an int (on my system char is unsigned and EOF defined as -1).
  2. Only increment i when you have a valid letter which is in the if body not for each iteration of the loop.
  3. \0-terminate the string a.
  4. a is subject to overflows (i >= n).
  5. (minor) prefer using unsigned types for length (unsigned, size_t etc).
  6. (minor and not fixed to minimize change) replace for with while as it now has neither initialization or increment parts.
unsigned read_message(char a[], unsigned n) {
    printf("Enter a message: ");
    int ch;
    unsigned i = 0;
    for (; (ch = getchar()) != EOF && ch != '\n' && (i   1) < n;) {
        if (isalpha(ch)) {
            a[i  ] = tolower(ch);
        }
    }
    if(n)
        a[i] = '\0';
    return i;
}

If you swap the order of arguments you can document the relationship between n and a:

unsigned read_message(unsigned n, char a[n])
  • Related