Gabriel Saul
Gabriel Saul

Reputation: 83

Unexpected newline occuring with use of for loops, ternary operators and conditions

I understand that some functions automatically append newlines to their outputs, but I've encountered a scenario where a newline is not expected. I've tried to fix it and understand why it occurs in a multitude of ways, but to no avail. This is an output issue I haven't experienced before.

I am doing a very basic project from C Programming: A Modern Approach by K.N. King, Chapter 8, project 6: "B1FF filter", where certain characters get converted and printed as such. I used ternary operators combined with conditions to get the appropriate output. Here's the program:

/*  C Programming: A Modern Approach
        Chapter 8: Arrays, Project 5: B1FF filter
*/

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

int main(void)
{
    char message[50];
    int msg_len;

    printf("Enter message: ");
    fgets(message, 50, stdin);
    msg_len = strlen(message);

    printf("In B1FF-speak: ");

    for (int i = 0; i < msg_len; i++)
    {
        message[i] = toupper(message[i]);

        if (message[i] == 'A' || message[i] == 'B')
            printf("%c", (message[i] == 'A') ? '4' : '8');

        else if (message[i] == 'E' || message[i] == 'I')
            printf("%c", (message[i] == 'E') ? '3' : '1');

        else if (message[i] == 'O' || message[i] == 'S')
            printf("%c", (message[i] == 'O') ? '0' : '5');

        else
            printf("%c", message[i]);

        if (i == (msg_len - 1))
        {
            for (int j = 0; j < 10; j++)
                printf("!");

            printf("\n");
        }
    }

    return 0;
}

The output isn't expected:

Enter message: C is rilly cool
In B1FF-speak: C 15 R1LLY C00L
!!!!!!!!!!

Why is there a newline between the modified string and the exclamation marks? I've clearly specified for the newline to occur after all text is printed, just before the loop terminates. I've tried alterations, such as printing a newline outside of the loop, not using a for loop for the exclamation marks etc., but it yields the same result. There doesn't seem to be an explicit reason for its occurrence.

Upvotes: 1

Views: 593

Answers (2)

MikeCAT
MikeCAT

Reputation: 75062

fgets() will save the newline character read to the buffer. If you don't want it, remove it.

Example:

fgets(message, 50, stdin);
/* remove newline character */
{
    char* lf = strchr(message, '\n');
    if (lf != NULL) *lf = '\0';
}

The meaning is:

fgets(message, 50, stdin); /* read one line from the standard input */
/* remove newline character */
{
    char* lf /* declare a variable */
        = strchr(message, '\n'); /* and initialize it with the pointer to the first '\n' in the string message */
    if (lf != NULL) /* check if '\n' is found */
        *lf = '\0'; /* if found, replace '\n' with '\0' and delete the newline character (and string after '\n', which won't usually present) */
}

Upvotes: 1

underscore_d
underscore_d

Reputation: 6791

fgets includes the newline in what it copies to the destination char buffer. Hence your character-by-character printing routine passes it unaltered.

Result #1 for fgets on Google: http://www.cplusplus.com/reference/cstdio/fgets/

A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.

Of course, as mentioned in the other answer, you can ignore this when printing, or null it out in advance.

Upvotes: 2

Related Questions