0

I'm a student studying C, and seem to be stuck when using Structures and Arrays to read in characters as part of the array.

When I run the code, it skips over the char scanf and will not read in any characters. There is no problem reading in integers etc.

For example (This is an example, my code is much longer but I know there's a problem here). Is the scanf part that reads in the name correct?

struct stud s[5];
int i = 0;
for (int i = 0; i < 5; i++)
{
    fflush(stdout);
    s[i].no = i + 1;
    printf("\nStud number %d\n", s[i].no);
    printf("Enter name:");
    scanf_s("%c", &s[i].name);
    printf("Enter grade: ");
    scanf_s("%d", &s[i].grade);
    printf("Successfully added to grade book\n");
}

I declared them below:

struct stud {
    int no;
    char name;
    int grade;
};

It would be great if someone could point me in the correct direction?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Meh
  • 3
  • 1
  • 2

3 Answers3

3

You have to declare name as a char array

struct room {
    int no;
    char name[32]; /* pick a reasonable size */
    int grade;
};

And then this

scanf_s("%c",&s[i].name);

would change to

scanf_s("%s",s[i].name, _countof(s[i].name));

and since there is no guarantee that the name would be 31 characters length, you have to specify a field length like this

scanf_s("%31s",s[i].name, _countof(s[i].name));

the length should be the sizeOfArray - 1 since c strings need to mark the end of the string with a null byte '\0', and scanf_s will append that byte to the read string.

If you don't specify the field length and it turns out that there are more than characters than requested by _countof(s[i].name) then nothing is read, for more information read here.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • 3
    Note that [`_countof()`](http://msdn.microsoft.com/en-us/library/ms175773.aspx) is not standard C (a Microsoft extension), and while `scanf_s()` is defined in Annex K of the C11 standard, it is not widely implemented (it is available with Microsoft and not usually available with Unix-like systems). – Jonathan Leffler Dec 20 '14 at 02:13
  • @JonathanLeffler: Annex K `scanf_s` and MS `scanf_s` are incompatible. The size parameters for the Annex K version are of type `size_t`, and `int` for the MS version. In a variadic function. – mafso Dec 20 '14 at 02:25
  • @mafso: I wish I could say I was [surprised](http://stackoverflow.com/a/373911/15168). I knew of issues with `snprintf_s()`; I wasn't specifically aware of issues with `scanf_s()`. – Jonathan Leffler Dec 20 '14 at 02:27
  • 2
    `_countof` has type `int`, not `size_t`, so it is equivalent to `(int)(sizeof array/sizeof *array)`. `_countof` is correct for MS `scanf_s` and `sizeof array/sizeof *array` for Annex K `scanf_s` (I don't know if there are common platforms implementing it at all). My advice is not to use these functions at all. They are non-portable, almost always used wrongly (in questions and answers on SO, I haven't seen real-world code using them), and solve too few problems of the standard functions. – mafso Dec 20 '14 at 02:46
  • @mafso, ok then shuold I leave it in the comments or do I fix the answer? – Iharob Al Asimi Dec 20 '14 at 02:50
  • I have no idea. Maybe ask OP if she wants to tag as Windows. Or mention portability problems in the answer (and maybe suggest `scanf` or something else if you like). Or just leave it as-is; at least, the first correct use of `scanf_s` I've seen on SO for a while. – mafso Dec 20 '14 at 02:59
  • @mafso Seems like [`_countof` has type `size_t` in newer versions of VS](https://msdn.microsoft.com/en-us/library/ms175773(v=vs.140).aspx). – Spikatrix Feb 14 '16 at 17:21
2

Note that you should create a char array of a reasonable size and use %s as mentioned by @iharob in his answer if you want to enter more than 1 character for a student. If you want name to be a char,then change

scanf_s("%c", &s[i].name);

To

scanf_s(" %c", &s[i].name, 1);

The space before %c skips all kinds of blanks(like newlines and spaces) present in the stdin and %c will then scan a non-whitespace character.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
  • 1
    `scanf_s(" %c")` needs 2 following arguments – chux - Reinstate Monica Dec 20 '14 at 02:57
  • I didn't know that! But [this site](http://code.wikia.com/wiki/Scanf_s) does not mention about 2 arguments. If that site is wrong,then is `scanf_s(" %c",&s[i].name,1);` right? – Spikatrix Dec 20 '14 at 10:19
  • A [ms sample](http://msdn.microsoft.com/en-us/library/w40768et.aspx) uses `scanf_s("%4c", &c, _countof(c));` There are various details surrounding use of `scanf_s` like the type of `_countof(c)`. – chux - Reinstate Monica Dec 20 '14 at 16:12
  • Ok - This I think is the correct way, I recall a lecturer telling us this: scanf_s(" %c", &s[i].name,1); – Meh Dec 20 '14 at 21:17
  • How do you add something in a variable, e.g. s[i].gradetotal = s[i].grade * 50;. Is this correct? Thanks! – Meh Dec 20 '14 at 21:18
  • @Meh , There isn't a variable named `gradetotal` in the structure. So you cannot do that. BTW,you can accept my answer if it helped. – Spikatrix Dec 21 '14 at 02:20
  • @chux The problem is that `gradetotal` is defined in my programme. `s[i].gradetotal = 0.0000` when I print it after multiplying it by 50. I've tried making everything int or float etc but the answer is 0.0000 when I print `s[i].gradetotal` after the calculation. How do you multiply or divide something in this scenario? – Meh Dec 21 '14 at 13:07
  • @Meh ,Try `s[i].gradetotal = s[i].grade * 50.0;` – Spikatrix Dec 21 '14 at 13:15
2

The %c will not the characters because the characters will be present in stdin, and you have to skip the characters.

scanf_s("%c", &s[i].name);

if the last character in the previous is \n the %c will take the \n as input. You have to change the code, just give a space before the %c.

scanf_s(" %c", &s[i].name);

This will flush the white space characters in the stdin and it will get the input.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
sharon
  • 734
  • 6
  • 15