简体   繁体   中英

Problem with multidimensional c array

Ok am new to programming so go easy on me. I want to make a program that allows a user to input a name, marital status, sex and residence of 30 students. Here's my code and the only problem is the program is allowing inputs above the expected 120 inputs.

#include <stdio.h>

char std[30][40];
int x,y;

main()
{
  printf("Enter number of students: \n");

  for(x=0;x<30;x++)
    for(y=0;y<4;y++)
      scanf("%s" &std[x][y],);

  return 0;
}

I'm wondering: can I use pointers to access multidimensional array elements?

A few things:

for(x=o;x<30;x++)

Surely you meant 0 and not o there. Who knows what o contains, but apparently not zero...

This:

char std[30][40];

And this (corrected):

for(x=0;x<30;x++)
  for(y=0;y<4;y++)
    scanf("%s", &std[x][y]);

Do not match up. You are declaring std in essence as an array of 30 strings, each 40 characters long. But you are treating it as a 30x4 array of strings. Something is not adding up. Consider using this instead:

for(x=0;x<30;x++)
  scanf(" %s", &std[x][0]);

And yes, taking pointers to multidimensional arrays is just fine. Array variables are actually just pointers anyway, so it's really just pointer math under the hood.

Yes.

However, I think the code there now is broken.

There is an array of 30 elements, where each element is 40 chars.

The code then loops over each of the 30 elements; for each element, it then loops over the first four chars, scanning a string ("%s") into each char. The second scanf will overwrite all but the first char of the first scanf, the third scanf will overwrite all but the first char of the first and second scanf, etc.

You want a structure.

A structure can hold several different types (char[] for student names; enum MaritalStatus for marital status; enum Gender for sex; etc ...) in a single object, eg

enum MaritalStatus { MS_SINGLE, MS_MARRIED, MS_DIVORCED,
                     MS_WIDOWED, MS_UNKNOWN, MS_OTHER };
enum Gender { G_MALE, G_FEMALE, G_UNDECIDED, G_UNKNOWN, G_OTHER };
struct Student {
    char name[120];
    enum MaritalStatus maritalstatus;
    enum Gender gender;
    char residence[120];
    /* ... */
};

Several issues:

First of all, you've defined std as a 30-element array of 40-element arrays of char ; IOW, you can store at most 30 strings of at most 39 characters (plus 0 terminator), not 120 strings.

Secondly, to read into each of these strings, the call to scanf would simply be

for (x = 0; x < 30; x++)
  scanf("%s", std[x]);

The type of the expression std[x] is char [40] , or 40-element array of char. However, there is a rule that when expressions of type "N-element of T" are encountered, they are implicitly converted ("decay") to type "pointer to T" (the exceptions to this rule are when the array expression is an operand of the sizeof or unary & operators, or if the array expression is a string literal being used to initialize another array in a declaration); thus, in this context, the type of the expression std[x] decays to type char * , or pointer to char, so you don't need to use the & operator explicitly.

The risk of using scanf like this is that it's possible for the user to type in more characters than the target buffer can hold; if the user types 100 characters, those extra 60 characters will be stored in the memory immediately past the end of the buffer, which may or may not cause problems later on. You can get around this two ways: first, you can add a field width specifier to the %s conversion specification, like so:

scanf("%39s", std[x]);

second, you can avoid using scanf completely and use fgets instead:

fgets(std[x], sizeof std[x], stdin);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM