-1

I am writing this simple code to take in some credentials of students for an example using C, and im able to print all the other stuff, except my name. As far as I can see, the code seems correct, but no matter what the order is, my name doesn’t print. I am just a beginner at both C language and Stack Overflow, so, kindly bear with me if Ive made some mistakes.

enter image description here

#include<stdio.h>
void main()
{
    char name[10],age[2],add[50],gradyear[50];
    printf("Enter your Name:");
    scanf("%[^\n]%*c", name);
    printf("Enter your Age:");
    scanf("%[^\n]%*c", age);
    printf("Enter your Address:");
    scanf("%[^\n]%*c", add);
    printf("Enter your Year of Graduation:");
    scanf("%[^\n]%*c", gradyear);
    printf("Here are your student credentials:\nName:%s \nAge:%s \nAddress:%s \nYear of Graduation:%s ",name,age,add,gradyear);
}
James Z
  • 12,209
  • 10
  • 24
  • 44
  • Welcome to SO. While it is not causing your problem, you should always care about warnings from your compiler. – Gerhardh Jan 10 '22 at 19:02
  • 1
    `scanf("%[^\n]%*c", age);` You should *always* limit strings to the length of the buffers you provide. And you should also check the return value of `scanf` and similar functions – Gerhardh Jan 10 '22 at 19:03
  • Videsh .V.K, `char age[2]` is good for ages `0-9` as a _string_, Suggest `age[4]`. – chux - Reinstate Monica Jan 10 '22 at 19:03
  • `char name[10],age[2]` You enter age `18` which does not fit into a `char[2]`. You are missing space for the 0-terminator. Also, is there any specific reason why you insist on using a string to handle an age which is basically an integer value? – Gerhardh Jan 10 '22 at 19:04
  • 1
    `"%[^\n]%*c"` is worse than `gets()`. – chux - Reinstate Monica Jan 10 '22 at 19:04
  • 1
    `char gradyear[50];`. Room for 49 digits... how long do you intent to use that program? ;) – Gerhardh Jan 10 '22 at 19:06
  • Don't try to kludge the whitespace away. With formats `%c` and `%[]` and `%n` place a space just before the `%`. Other format specs filter whitespace anyway. So for example you get `char age[4]; scanf(" %3[^\n]", age);` – Weather Vane Jan 10 '22 at 20:01
  • @Gerhardh No, there's no particular reason for using strings, I will change it to an integer. Also, even if I use char[2], and try to print 18, it does show 18, like in the screenshot. The grad year was just a random input, I will change it.Kindly let me know if I'm missing something. Thank you for your help. – Videsh .V.K Jan 11 '22 at 02:31
  • @chux-ReinstateMonica I tried using gets and it was still not showing me my name, so I tried this function which I took of the internet. Kindly let me know if I'm missing something. – Videsh .V.K Jan 11 '22 at 02:36
  • @Videsh.V.K I have tried to explain the cause of your problem as clearly as I can in the answer I gave below. Hope it can help you. – Wu Xiliang Jan 11 '22 at 03:28
  • @Videsh.V.K "I tried using gets and it was still not showing me my name," --> Did you use `fgets()` for all input or did you use `scanf()` too? [scanf() leaves the newline character in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-newline-character-in-the-buffer) – chux - Reinstate Monica Jan 11 '22 at 04:59
  • 1
    @Videsh.V.K "Also, even if I use char[2], and try to print 18, it does show 18" --> To store `"18"` as a _string_, do you see that needs an array of at least 3 `char`? – chux - Reinstate Monica Jan 11 '22 at 05:02
  • @chux-ReinstateMonica I understand that now. Thank you so much for your help.I'm completely new to the language and could not understand what you meant. Now, I do. Thank you. – Videsh .V.K Jan 12 '22 at 10:10

1 Answers1

0

In order to make the problem clear, I add some debugging code in the original code.
This is really the right place to solve this problem, because it is caused by overflow.

#include<stdio.h>
int main(void)
{
    char name[10],age[2],addr[50],gradyear[50];

    /* Debugging Code Begin */
    printf("name\t\t: %p %p\n", (void *)name, (void *)(name+9));
    printf("age\t\t: %p %p\n", (void *)age, (void *)(age+1));
    printf("addr\t\t: %p %p\n", (void *)addr, (void *)(addr+49));
    printf("gradyear\t: %p %p\n", (void *)gradyear, (void *)(gradyear+49));
    /* Debugging Code End */

    printf("Enter your Name:");
    scanf("%[^\n]%*c", name);
    printf("Enter your Age:");
    scanf("%[^\n]%*c", age);
    printf("Enter your Address:");
    scanf("%[^\n]%*c", addr);
    printf("Enter your Year of Graduation:");
    scanf("%[^\n]%*c", gradyear);
    printf("Here are your student credentials:\n"
           "Name:%s \nAge:%s \nAddress:%s \nYear of Graduation:%s \n"
           , name, age, addr, gradyear);
}

When compiled by gcc(GCC 11.2.0), the debugging output is:

name        : 0x7ff7b92ca726 0x7ff7b92ca72f
age         : 0x7ff7b92ca724 0x7ff7b92ca725
addr        : 0x7ff7b92ca6f0 0x7ff7b92ca721
gradyear    : 0x7ff7b92ca6b0 0x7ff7b92ca6e1

As we can see, the address of the second byte of age is 0x7ff7b92ca725, and the address of the first byte of name is 0x7ff7b92ca726. The two addresses are adjacent.
So when we input a two-or-more-digit number and save it in the array of age, the overflow happens.
For example, when we scanf a two-digit long number, say 25 and then age[0] has '2', and age[1] has '5' and the Null character will be stored into the first byte of name.
That's exactly why the string of name shows an unexpected blank.

When compiled by clang(clang-1300.0.29.30), the debugging output is:

name        : 0x7ff7bda1271e 0x7ff7bda12727
age         : 0x7ff7bda1269e 0x7ff7bda1269f
addr        : 0x7ff7bda126e0 0x7ff7bda12711
gradyear    : 0x7ff7bda126a0 0x7ff7bda126d1

Similar to the above situation, here, we can see the address of the second byte of age (0x7ff7bda1269f) is adjacent to the address of the first byte of gradyear (0x7ff7bda126a0). When the overflow happens, the output of age is the content of both age and gradyear concatenated together, such as 152015.

Suggestion and solution : always remember to add one extra byte for a C-style string (Null-terminated String).

If you plan to have a size of two, make it three for the array.

Wu Xiliang
  • 316
  • 3
  • 10