0

I'm going through "C Programming: A Modern Approach" by K.N. King right now. This program is taken from "Section 12 - Pointers and Arrays", Project 1b. Roughly, the goal is: Write a program that reads a message, then prints the reverse of the message. Store the message in an array, and keep track of the current position in the array using a pointer.

Currently, I'm just trying to get the message to print normally before I try and make it print backwards. I'm frustrated because my printMessage() function is 1:1 with the print_message() function from here, however when the program is run and some text is entered, it just prints out a blank line. This happens if the line within the for-loop of printMessage() is changed to 'printf("%c", *p);' as well.

Here is my code:

#include <stdio.h>

#define MAX_MESSAGE_LENGTH 100

int readMessage(char msg[]);
void printMessage(char msg[], int len);

/* finish later
 void printMessageReversed(char msg[], int len); */

int main(void){
    int msg_length;
    char c[MAX_MESSAGE_LENGTH];

    printf("Enter a message: ");
    msg_length = readMessage(c);

    printf("Length: %d", msg_length);

    printf("\nMessage: ");
    printMessage(c, msg_length);

    return 0;
}

int readMessage(char msg[]){
    int i;
    for(i = 0; (*msg = getchar()) != '\n'; i++);
    return i;
}

void printMessage(char msg[], int len){
    char *p;

    for(p = msg; p < msg + len; p++){
        putchar(*p);
    }
}

Wondering if anyone can help identify my problem? I'm sure it's something painfully obvious or naive that I'm just missing. Thanks for any help.

14
  • 1
    @Shravan40: No, that's not it. The msg parameter is a pointer. Commented Sep 9, 2016 at 19:44
  • 2
    @Shravan40: C does not support pass by reference! It is strictly pass by value. Commented Sep 9, 2016 at 19:45
  • 1
    @Olaf: Of course -- but passing a pointer (by value) can give you the equivalent functionality of pass-by-reference. Commented Sep 9, 2016 at 19:46
  • 1
    Apart from the lack of increment others have commented, you have not written a nul terminator at the end of the input to make the array a "string", in readMessage Commented Sep 9, 2016 at 19:47
  • 1
    @Olaf : In C, Pass-by-reference is simulated by passing the address of a variable (a pointer) and dereferencing that address within the function to read or write the actual variable. This will be referred to as "C style pass-by-reference." Commented Sep 9, 2016 at 19:47

3 Answers 3

9
int readMessage(char msg[]){
    int i;
    for(i = 0; (*msg = getchar()) != '\n'; i++);
    return i;
}

Each character is assigned to *msg (equivalently to msg[0]). The msg pointer is never updated and never indexed by i, so you never assign values to the remaining characters in the array whose initial element is pointed to by msg.

Replacing *msg by msg[i] is one partial solution. Note that this still doesn't write a null '\0' terminator into msg, so the msg array does not contain a string. But since your printMessage function doesn't require a string (it takes a len argument), that's not strictly necessary. Still, if you're going to operator on the array in other ways, it's probably a good idea to null-terminate it.

Also, as chux points out in a comment, you have an infinite loop if getchar() returns EOF before returning '\n' (on Unix that can happen if you type Ctrl-D twice in the middle of a line, or if you're reading from a file), and it has no protection against a buffer overrun.

Sign up to request clarification or add additional context in comments.

8 Comments

so you need msg[i] = getchar()
Thank you! Altered the for-loop to read for(c = msg; (*msg = getchar()) != '\n'; msg++, i++); and it works perfectly now.
@pm100 and yes that would also work just as well, thanks :)
Also realise the example I just gave is probably overcomplicated so I'll try and cut it down a bit.
Side issues: for(i = 0; (*msg = getchar()) != '\n'; i++); is potential infinite loop upon reading EOF and it has no buffer over-run protection.
|
1

Use it like that :

int readMessage(char msg[]){
    int i;
        for (i = 0; (*(msg + i) = getchar()) != '\n'; i++);
    return i;
}

3 Comments

This is far more concise than everything I was trying. Thanks!
@WeatherVane agreed, but for the purposes of this chapter of the book I'm going to try and stick entirely to pointers, just so I can get used to them.
@Sato yeah, but the argument was an array (although that decays to a pointer). Another point: please be aware that if the argument was int msg[] instead of char msg[] there is no size adjustment required when using *(msg + i) = getchar() - just as with array indexing, the pointer arithmetic takes care of the size for you.
0

Write a program that reads a message, then prints the reverse of the message

#include <stdio.h>
#define MAX_MESSAGE_LENGTH 100
int main(void) {
    int i, j;
    char c[MAX_MESSAGE_LENGTH];
    printf("Enter a message: ");
    fgets(c, sizeof c, stdin);
    printf("Reverse Order\n");
    i = 0;
    while (c[i] != '\0') {
        if (c[i] == ' ' || c[i] == '\n') {
            for (j = i - 1; j >= 0 && c[j] != ' '; j--)
                printf("%c", c[j]);
            printf(" ");
        }
        i++;
    }
    printf("\n");
    return 0;
}

Test

Enter a message: Stackoverflow

Reverse Order
wolfrevokcatS 

Try it with ideone.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.