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

char str[50];

int main() {

    int hasSign = 0;

    printf("Enter your email: ");
    scanf("%s", str);

    // email validation
    if (strchr(str, '@') != NULL) {
        hasSign = 1;
    }
    printf("%s", hasSign + "\n");
    
    return 0;
}

How can I print a newline when I am printing the value of hasSign like in the upper code?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Jbb
  • 217
  • 1
  • 7
  • 2
    `printf("%d\n", hasSign );`. Note also that `%s` is for string and `%d` is needed for int. – kaylum Oct 23 '21 at 20:27
  • Can I also use %i for integer? – Jbb Oct 23 '21 at 20:34
  • @Jbb: Yes, `%d` and `%i` behave exactly the same. – Nate Eldredge Oct 23 '21 at 20:35
  • 3
    The fundamental problem is that you can't use `+` to concatenate strings in C, and you certainly can't use it to convert an integer to a string and then concatenate it. C is not Javascript. Strings are not really a basic data type; you have to understand arrays and pointers to work with them properly. See https://stackoverflow.com/questions/8465006/how-do-i-concatenate-two-strings-in-c – Nate Eldredge Oct 23 '21 at 20:35
  • 5
    `hasSign + "\n"` doesn't make much sense here. You're doing pointer addition, so if `hasSign` is 0, the addition will have no effect, and if `hasSign` is 1, it will advance the pointer past the newline so that it points directly at the terminating `\0` character. So you will print a newline if `hasSign` is 0 and the empty string (i.e., nothing) if `hasSign` is 1. – Tom Karzes Oct 23 '21 at 20:36
  • 1
    @Jbb "*Can I also use %i for integer*". You can answer such questions for yourself by reading the [scanf manual](https://www.man7.org/linux/man-pages/man3/scanf.3.html). – kaylum Oct 23 '21 at 20:38
  • @Jbb: `%i` and `%d` are equivalent for `printf`, but different for `scanf`: `%d` expects a number in decimal whereas `%i` will accept octal numbers starting with `0` and hexadecimal numbers starting with `0x` or `0X`. – chqrlie Oct 24 '21 at 09:54

2 Answers2

3

There is a big bitfall here in the line printf("%s", hasSign + "\n" );

"\n" is actually a pointer to const char (const char *) which is array of two characters: [0] = '\n', [1] = '\0' so when you add hasSign to it, it is actually doing pointer arithmetic.

To make it clear by example, let's say hasSign equals 0 so hasSign + "\n" evaluates to 0 + "\n" which is like &"\n"[0] = pointer to '\n' so a new line will printed in this case.

But when hasSign equals 1 so hasSign + "\n" evaluates to 1 + "\n" which is like &"\n"[1] = pointer to '\0' which is a null character or in other words 'nothing' and therefore nothing will be printed in this case.

To your question:

How can I print a newline when I am printing the value of hasSign like in the upper code?

you can do it like printf("%d\n", hasSign);

Alaa Mahran
  • 663
  • 4
  • 12
  • Your answer is inaccurate: `"\n"` is not a pointer, it is a string constant. Adding an integer to a string constant does not produce a character, but indeed a pointer inside the array generated for the string constant if the offset is range 0..2 in this example. The behavior is defined for 0 and 1, and the newline is actually output if no `@` is found in the input string. – chqrlie Oct 24 '21 at 09:50
  • A c-string is an array of characters. An array is a pointer to its first element. This means c-string is a pointer to a character which in turn means a string constant is a pointer to const character. I strongly recommend that you read more about c-strings. Yes the new line will be generated if no `@`in the input string because in this case `hasSign`equals 0 so `hasSign + "\n"`evaluates to `"n"[0]` which is the new line character `'\n'` – Alaa Mahran Oct 24 '21 at 10:00
  • 1
    I'm afraid you are mistaken: *An array is a pointer to its first element* is a very confusing statement. Arrays and pointers are very different things. Arrays decay into pointers to their first element in many contexts, such as this one, which creates confusion among beginners, which I don't suppose you are :) By the way `0 + "\n"` does not evaluate to `"\n"[0]`, but to `&"\n"[0]` which is a pointer to the `\n`. Purists might even contend that it evaluate to `&0["\n"]`, which is equivalent to `&"\n"[0]` anyway, but less readable. – chqrlie Oct 24 '21 at 10:09
  • That's right, `0 + "\n"`does actually evaluates to `&"\n"[0]` then the `%s` in the `printf` is the one which is doing the magic of actually printing `'\n'` instead of the pointer value itself. Thanks for your clarification! and for '*An array is a pointer to its first element*', of course, I was referring to the context we are talking about here. regarding confusion, I agree but what's not confusing about pointers anyway :D – Alaa Mahran Oct 24 '21 at 10:47
2

You cannot concatenate strings with + in C, nor convert numbers to strings by adding a number and a string. Your program compiles because hasSign + "\n" is not a syntax error: adding a string and an integer evaluates to a pointer inside the string. The program will output a newline if hasSign is 0 and nothing of hasSign equals 1.

Here is a modified version that illustrates printf usage for string and integer arguments:

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

int main() {
    char str[50];
    int hasSign = 0;

    printf("Enter your email: ");
    if (scanf("%49s", str) != 1) { // prevent scanf from writing beyond s[49]
        // exit upon input error
        return 1;
    }

    // email validation
    if (strchr(str, '@') != NULL) {
        hasSign = 1;
    }
    printf("email: %s, hasSign: %d\n", str, hasSign);
    
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189