# Multidimensional arrays in C

1. Mar 29, 2009

### djeitnstine

Hi guys I just learned M-D arrays and was trying to execute this piece of code:

Code (Text):
//initial value of y
printf("\nTime of initial displacement - y(t): t=");
fflush(stdin);
scanf("%lf", &IVP[1][1]);
printf("\nInitial displacement - y(%.4lf)=",&IVP[1][1]);
fflush(stdin);
scanf("%lf", &IVP[1][2]);

//initial value of y_prime
printf("\nTime of initial velocity - y'(t): t=");
fflush(stdin);
scanf("%lf", &IVP[2][1]);
printf("\nInitial velocity - y'(%.4lf)=", &IVP[2][1]);
fflush(stdin);
scanf("%lf", &IVP[2][2])
And for some reason the output keeps screwing up. I placed '1' for the first scanf and ever since then it kept printing '1'. I can post a screen shot if necessary...

thanks

2. Mar 29, 2009

### sylas

You've got address operators "&" in your printf statements. Get rid of them.

If you are reading and writing a single variable, you do it like this.
Code (Text):

{
int x;

printf("Enter a value for x: ");
scanf("%d", &x);
printf("You entered the value %d\n", x);
}

You include or omit the "&" operator the same way for an array element.
Code (Text):

{
int x[5][5];

printf("Enter a value for x[2][3]: ");
scanf("%d", &x[2][3]);
printf("You entered the value %d\n", x[2][3]);
}

It's a good idea to have all possible compiler warnings enabled when you compile your program. If you are using the gnu compiler, the compiler argument is "-Wall". There should be something similar for any other compiler you use.

Cheers -- Sylas

3. Mar 29, 2009

### djeitnstine

Thanks a mil

4. Mar 29, 2009

### djeitnstine

Ok so now I encountered a 3rd problem. I'm truly puzzled this time. I guess its only because I'm really not used to C.

Please bare with the slightly lengthy printf's

Code (Text):

[COLOR="Red"][B]#define FUNY  1[/B][/COLOR]
#define Y_T   0
[B][COLOR="Orange"]#define FUNYP 1
#define YP_T  0[/COLOR][/B]

.
.
.
[COLOR="Red"][B]double[/B] IVP[1][1]={0}[/COLOR]
.
.
.
//initial value of y
printf("\nTime of initial displacement - y(t): t=");
fflush(stdin);
scanf("%lf", &IVP[0][Y_T]);
printf("\nInitial displacement - y(%.4lf)=",IVP[0][Y_T]);
fflush(stdin);
[COLOR="Red"][B]scanf("%lf", &IVP[0][FUNY]);[/B][/COLOR]

//initial value of y_prime
printf("\nTime of initial velocity - y'(t): t=");
fflush(stdin);
[COLOR="Orange"]scanf("%lf", &IVP[1][YP_T]);[/COLOR]
printf("\nInitial velocity - y'(%.4lf)=", IVP[1][YP_T]);
fflush(stdin);
scanf("%lf", &IVP[1][FUNYP]);

printf("\n\nt=%.4lf, [B][COLOR="Red"]Y=%.4lf[/COLOR][/B], t'=%.4lf, Y'=%.4lf\n\n",[COLOR="Orange"][B]IVP[0][Y_T][/B][/COLOR],[COLOR="Red"][B]IVP[0][FUNY][/B][/COLOR],[B][COLOR="Orange"]IVP[1][YP_T][/COLOR][/B],IVP[1][FUNYP]);
.
.
.
coeff[0]=(coeff_solv*IVP[0][FUNY]+IVP[1][FUNYP])/(coeff_solv*sine+solution[IMAG]*cosine_yp);  //step 1 solve for C1
printf("\n\nC1:%.4lf= x:%.4lf* [COLOR="Red"]Y:%.4lf[/COLOR] + Y':%.4lf / x:%.4lf * sin:%.4lf + r:%.4lf * cosy':%.4lf\n\n",coeff[0],coeff_solv,[COLOR="Red"][B]IVP[0][FUNY][/B][/COLOR],IVP[1][FUNYP],coeff_solv,sine+solution[IMAG],cosine_yp);
So this is what showed up. Please note Y:

Last edited: Mar 29, 2009
5. Mar 29, 2009

### Hurkyl

Staff Emeritus
The most obvious problem is that you've overflown your array.

double IVP[1][1]={0};

This declares a two-dimensional array whose first index set has length 1, consisting of the interval [0,1). I.E. the only legal first index is 0. Similarly, the only legal second index is 0.

A more subtle problem -- I'm pretty sure %lf is supposed to be for long double arguments, not double arguments. Though, I bet on your computer, those turn out to be the same type.

6. Mar 29, 2009

### djeitnstine

Maybe I'm totally wrong but aren't 2d arrays
Code (Text):
2D_Array[row][column]

7. Mar 29, 2009

### djeitnstine

Ahh ok, so I should make it 2D_Array[2][2]

8. Mar 29, 2009

### djeitnstine

Yea this is how our professor asks us to do it.

9. Mar 29, 2009

### Hurkyl

Staff Emeritus
Or... maybe the l just does nothing. (Now that I read again, I think %Lf is for long doubles)

10. Mar 29, 2009

### Hurkyl

Staff Emeritus
You should do things correctly. I bet your professor doesn't have any deep reason for asking you to use %lf -- it was simply how he was taught. You should ask him about it. And if he insists you use %lf, then humor him for his class, and but only for his class.

11. Mar 29, 2009

### djeitnstine

Thanks a mil, got it.

12. Mar 29, 2009

### Hurkyl

Staff Emeritus
Aha, I checked the Microsoft visual studio documentation (that is what you're using, right?). Whether or not this is what the C standard dictates, Microsoft's C implementation does interpret %lf as specifying a long double. So, your program would fail to work if long double and double were differently sized types.

13. Mar 29, 2009

### Hurkyl

Staff Emeritus
Ack, I just noticed I never explicitly said what you're supposed to use for doubles! In case it wasn't clear, %f is the correct specifier.

14. Mar 29, 2009

### Hurkyl

Staff Emeritus
BTW, I was looking up the codes for printf -- I think scanf might have slightly different behavior; I generally try to avoid using if whenever possible, so I'm not familiar with the differences between scanf and printf. (maybe %lf is right for scanf even if it's wrong for printf?)

15. Mar 29, 2009

### djeitnstine

Hmm well I'm using Dev C++, and it sees it all the same. %lf seems to work for both scanf and printf. Just to let you know the program works okay now, thanks again.

Also I have another question, can I make an array of strings? or would that have to be a structure or something. Perhaps a 2D string array? char 2D_String[][]=" ";

16. Mar 29, 2009

### djeitnstine

Hmm now I'm having trouble with this simple function. I just want it to loop to grab strings and skip the terminator.

Code (Text):

//declare variables
char final_unit[12]=" ";
int i=0, row=0, length=0;
char skip='-', units[4][10]={" "};

//welcome user
printf("Enter units plz (N-m-s) \n");

fflush(stdin);
scanf("%s", final_unit);

length=strlen(final_unit);

//grab each unit
for(i=0; i<=length; i++)
{
if(final_unit[i]==skip)
{
i++;
row++;
}

//grab each word
units[row][i]=final_unit[i];
printf("%s\n",units[i]);
}

//print to screen
row=0;
for(row=0;row<=2;row++)
{
printf("\n\n%s\n",units[row]);

}

17. Mar 29, 2009

### djeitnstine

For some reason that only prints garbage, then the first word before the terminator. Note that I need each one to be a string not necessarily a char.

18. Apr 1, 2009

### sylas

Your problem, I think, is that C doesn't really have strings in tthe same sense as more high level languages. I love C, but it is pretty close to being block structured assembly language. It doesn't actually treat "strings" as a data type like numbers, but rather it deals with buffers and addresses.

When you declare a string in C, you are really declaring a buffer... an array of characters. If you pass the string (or any other array) to a function, you are actually passing the address of the memory where the characters are stored. You are not passing a thing called a string, but an address where you have stored some characters.

Code (Text):

//declare variables
char final_unit[12]=" ";
/*
* SYLAS: The declaration above is an array of 12 chars.
* The initialization uses a compiler array (a string) of
* of two characters (a space, and a null) to initialize
* the first two places in final_unit, and then leftover
* 10 places are just set to null as well by extending the
* initializer.
*/
int i=0, row=0, length=0;
char skip='-', units[4][10]={" "};
/*
* The 2D array here has an unfortunate initializer. You
* might be better just to omit it.
char units[4][10];
* means that units is a 2D array.
* It also means that units[i] is a valid expression, that
* denotes an 1D array, each element of which behaves as if
* declared as
char xxx[10];
* That is, units[0] up to units [3] are all arrays of
* 10 characters each.
*
* To initialized units, you are initializing 4 arrays of
* characters. You could say, for example:
char units[4][10] = { "zero", "one", "two", "three" };
* In this case, units[1] would be an array, which has
* contents 'o', 'n', 'e', and then a lot of nulls.
* Your initialization only initialized units[0], leaving
* units[1] to units[3] all to have the default, which is
* an array of 10 nulls.
*/

//welcome user
printf("Enter units plz (N-m-s) \n");

fflush(stdin);
scanf("%s", final_unit);
/*
* This scanf here is fine, but it's a good idea to know
* what it does. final_unit is an array of 12 characters.
* You pass to the function the address, as a pointer to
* the first character position. The function can then
* read and store characters into this part of the memory.
* If you enter more than 11 characters, then you'll be in
* trouble, because it will keep storing past the size you
* have allocated in the declaration. C is dangerous like
* that. There are ways to code more safely, but this is
* ok to explore how it works.
*/
length=strlen(final_unit);

//grab each unit
for(i=0; i<=length; i++)
{
if(final_unit[i]==skip)
{
i++;
row++;
}

//grab each word
units[row][i]=final_unit[i];
printf("%s\n",units[i]);
}
/*
* Alas, this loop makes no sense.
* You should count up to i<length, because there are only
* length charactes, in places 0 to length-1. There is a
* null character stored at final_unit[length], but you
* don't need to look at it.
* The assignment units[row][i] only sets one character
* in the row i. The assignment refers to units[i],
* which is not the same as units[row] wherein you stored
* the character. And in any case, you need to store more
* than one character in row, don't you?
*/
//print to screen
row=0;
for(row=0;row<=2;row++)
{
printf("\n\n%s\n",units[row]);

}
I might put up a bit of sample code for you in a tick...

Cheers -- Sylas

Last edited: Apr 1, 2009
19. Apr 1, 2009

### sylas

Try this program. It writes out the each line
of input, but with words reversed. The code
assumes proper line terminated input with a
newline just before end of file. It's naive
about words, just counting anything with spaces
between them as words. It's careful not to
overflow any arrays. It handles a maximum of
12 words per line, and 15 characters per word,
simply ignoring anything extra without crashing.
If I use this paragraph as input to the program,
then I get the following as output:
Code (Text):

Words reversal. Stops at end of file. Go...
line each the out writes It program. this Try
code The reversed. words with but input, of
a with input terminated line proper assumes
naive It's file. of end before just newline
spaces with anything counting just words, about
to not careful It's words. as them between
of maximum a handles It arrays. any overflow
word, per characters 15 and line, per words 12
crashing. without extra anything ignoring simply
program, the to input as paragraph this use I If
output: as following the get I then

Here's the program.
Code (Text):

#include <stdio.h>

#define NWORDS 12  // Store up to 12 words, no more
#define MAXLEN 16  // Store up to 16 chars, including null, for each word

// A program to collect words (separated by spaces) and print each line
// out with words in reverse order.

int main()
{
char word[NWORDS][MAXLEN]; // Stores the words. Note subscript order
char c;   // The input character
int w;    // A counter of the number of words
int len;  // A counter for the length of a word

printf("Words reversal. Stops at end of file. Go...\n");

c = getchar();
while ( c != EOF ) {
// Each time around the loop does one line of input.
// Skip initial spaces
while ( c == ' ' ) {
c = getchar();
}
// Read until end of line
// Loop invariant. At end of line, or at the start of a new word
w = 0;
while ( c != '\n' && w < NWORDS ) {
len = 0;
do {
if ( len < MAXLEN-1 ) {
// Only store if there is space. Leave room for a null
word[w][len] = c;
len++;
}
c = getchar();
} while ( c != ' ' && c != '\n' );
word[w][len] = 0; // Add a null to terminate the word
w++;
// Skip over any spaces
while ( c == ' ' ) {
c = getchar();
}
}
// We might not have finished reading the line, if there were
// too many words. Finish it off now.
while ( c != '\n' ) {
c = getchar();
}
// Now output the words
// w is the number of stored words; we can use to count back
// This loop uses word[w] as an array of chars to pass to
// printf. All words are null terminated, so printf can work.

while ( w > 0 ) {
w--;
printf("%s ", word[w]);
}
printf("\n");

// This loop needs the first char of next line to be read
c = getchar();
}

return 0; // Finished
}

Observe that I use words[w][len] to refer to a place where I store one single character, and words[w] as an expression for an array of len characters, passed to printf. Note how I leave space to store the final null character in each word. It's needed for printf.

Cheers -- Sylas