0

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?

4
  • This I noticed when formatting the post for SO: improve your indenting, don't use global variables. Commented Nov 11, 2010 at 15:47
  • I honestly don't understand the question. Commented Nov 11, 2010 at 15:53
  • "for(x=o" ? editing mistake by pmg, or was the code not compiled? Commented Nov 11, 2010 at 15:57
  • @Blank: the x=o was in the original question. I assume it was a "copy/paste error" :-) Commented Nov 11, 2010 at 16:01

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

7 Comments

@cdhowie: Be careful when saying "Array variables are actually just pointers": c-faq.com/aryptr/aryptr2.html ("But I heard that char a[] was identical to char *a.")
Right, I'm referring to the value of "std" at runtime -- it is a pointer, and it can be treated like a pointer (well, a const pointer). The way that each mechanism allocates memory (or doesn't) is different, yes, but you can take both variables and do the same things to them (math/indexing/etc).
sorry for the typo that should have been char[30][4] and so a 30x4 array.Ant thats zero not an o.the program program compiles and runs but accepts over the 120 elements i expect.and i will try that
If that's the case, then you can probably make it work by replacing your "%s" with " %c". (The space there is important.)
@cdhowie: An example: * (char *)&a='x'; is something totally different than * (char *)&p='x'; (a being char a[10]; and p being char *p;). The first is writing 'x' at the first position in a. The second is changing one of the (probably 4) address bytes.
|
1

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.

Comments

0

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];
    /* ... */
};

Comments

0

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);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.