On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 06.04.15 15:50. Заголовок: (for Vlad from SO)


Hi Vlad,

The code is this:

int main(void)
{
// initializing rainfall data for 2010 - 2014
const float rain[YEARS][MONTHS] =
{
{ 4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6 },
{ 8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3 },
{ 9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4 },
{ 7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2 },
{ 7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2 }
};

int year, month;
float subtot, total;

printf(" YEAR RAINFALL (inches)\n");

for (year = 0, total = 0; year < YEARS; year++)
{
// for each year, sum rainfall for each month
for (month = 0, subtot = 0; month < MONTHS; month++)
{
subtot += rain[year][month];
}

printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; // tot al for all years
}

As an exercise the book asks the reader to change the above code so it uses pointers instead of subscripts.

My attempt was to do the

[....]

float (* rainPointer)[2]
rainPointer = rain;

[....]

for (year = 0, total = 0; year < YEARS; year++)
{
// for each year, sum rainfall for each month
for (month = 0, subtot = 0; month < MONTHS; month++)
{
subtot += *(*(rainPointer + year) + month);
}
}

[....]

This would give the correct value for year 0, but year 1 (and subsequent) wouldn't. This confused me because the debugger was showing that rainPointer[year][month] held the correct values but it wasn't reading the correct float from the array.

The book states the following:


 цитата:
[...] Hence,pz must point to an array of two ints, not to a single int. Here is what you can do: int (* pz)[2]; // pz points to an array of 2 ints



In my case I changed pz to rainPointer.

I learned that rainPointer is useless as I can just use rain. But if rainPointer points to rain, surely the following should be the same:

const float rain[YEARS][MONTHS] = [....]

float (* rainPointer)[2]
rainPointer = rain;

// the same?

subtot += rain[year][month];
subtot += *(*(rain + year) + month);
subtot += *(*(rainPointer + year) + month);


the first one works, the second one works, the third one doesn't.

I hope this is not too confusing.


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 12 [только новые]





ссылка на сообщение  Отправлено: 06.04.15 15:51. Заголовок: argh, I was meant to..


argh, I was meant to amend that topic title.

sorry!

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 06.04.15 16:28. Заголовок: It is not clear why ..


It is not clear why you use a pointer declared like
 
float (* rainPointer)[2];

and assign it by rain
while the element of the array has type
 
float [MONTHS]

If you want to get equivalent results you have to use a pointer declared like
 
float (* rainPointer)[MONTHS];


Here is a demonstrative program. Also I appended it with a code block that shows the difference between these two pointer declarations. That is elements they point to have different sizes.

 
#include <stdio.h>

#define YEARS 5
#define MONTHS 12

int main(void)
{
// initializing rainfall data for 2010 - 2014
const float rain[YEARS][MONTHS] =
{
{ 4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6 },
{ 8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3 },
{ 9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4 },
{ 7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2 },
{ 7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2 }
};

const float ( * rainPointer )[MONTHS];

int year = 0;
float total = 0.0f;

printf(" YEAR RAINFALL (inches)\n");

for ( ; year < YEARS; year++ )
{
// for each year, sum rainfall for each month
float subtot = 0.0f;
int month = 0;
for ( ; month < MONTHS; month++ )
{
subtot += rain[year][month];
}

printf( "%5d %15.1f\n", 2010 + year, subtot );
total += subtot; // tot al for all years
}

printf( "\n" );

rainPointer = rain;


for ( ; rainPointer != rain + YEARS; rainPointer++ )
{
// for each year, sum rainfall for each month
float subtot = 0.0f;
const float *monthPointer = *rainPointer;
for ( ; monthPointer != *rainPointer + MONTHS; monthPointer++ )
{
subtot += *monthPointer;
}

printf( "%5d %15.1f\n", 2010 + year, subtot );
total += subtot; // tot al for all years
}


printf( "\n" );

{
float (* rainPointer)[MONTHS];
float (* rainPointer2)[2];

printf( "sizeof( *rainPointer ) = %zu\n", sizeof( *rainPointer ) );
printf( "sizeof( *rainPointer2 ) = %zu\n", sizeof( *rainPointer2 ) );
}

return 0;
}


The program output is
 
YEAR RAINFALL (inches)
2010 32.4
2011 37.9
2012 49.8
2013 44.0
2014 32.9

2015 32.4
2015 37.9
2015 49.8
2015 44.0
2015 32.9

sizeof( *rainPointer ) = 48
sizeof( *rainPointer2 ) = 8



Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 06.04.15 23:06. Заголовок: thanks. I was misre..


thanks.

I was misreading the book. It's still a little confusing but I certainly understand what I was doing wrong and how you fix it.

a massive help!

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 06.04.15 23:18. Заголовок: If to declare the po..


If to declare the pointer like
 
float (* rainPointer)[2] = rain;

then the compiler should issue a diagnostic message like


 цитата:
error: initialization from incompatible pointer type





Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 01:56. Заголовок: I hate to be a pain ..


I hate to be a pain but could you point me in the right direction with this one?



Write a program that initializes an array-of-double and then copies the contents of the
array into three other arrays. (All four arrays should be declared in the main program.) To
make the first copy, use a function with array notation. To make the second copy, use a
function with pointer notation and pointer incrementing. Have the first two functions
take as arguments the name of the target array, the name of the source array, and the
number of elements to be copied. Have the third function take as arguments the name
of the target, the name of the source, and a pointer to the element following the last
element of the source. That is, the function calls would look like this, given the following
declarations:

double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
double target1[5];
double target2[5];
double target3[5];
copy_arr(target1, source, 5);
copy_ptr(target2, source, 5);
copy_ptrs(target3, source, source + 5);


I've done the first two, I cannot for the life of me, figure out how copy_ptrs is meant to work with source + 5.

I thought maybe I have to do it backwards?

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 10:17. Заголовок: The function can be ..


The function can be written the following way
 
double * copy_ptrs( double *target, const double *first, const double *last )
{
for ( ; first != last; ++first ) *target++ = *first;

return target;
}

Or
 
double * copy_ptrs( double *target, const double *first, const double *last )
{
for ( ; first != last; ++first, ++target ) *target = *first;

return target;
}

Or one more equivalent implementation using while loop
 
double * copy_ptrs( double *target, const double *first, const double *last )
{
while ( first != last ) *target++ = *first++;

return target;
}


For all these three loops the compiler can generate the same object code.:)

The same way except the parameter order there is defined standard template algorithm std::copy in C++.

It looks the following way
 
template <typename InputIterator, typename OutputIterator>

OutputIterator copy( InputIterator first, InputIterator last, OutputIterator result )
{
for ( ; first != last; ++first, ++result ) *result = *first;

return result;
}


Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 12:23. Заголовок: okay, I'm kickin..


okay, I'm kicking myself right now.

I had the same idea in my head, my logic was just wrong and I couldn't get it out. I should've taken a break.

you've been a major help!

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 12:35. Заголовок: Here is a demonstrat..


Here is a demonstrative program of using the function
 
#include <stdio.h>

double * copy_ptrs( double *target, const double *first, const double *last )
{
for ( ; first != last; ++first, ++target ) *target = *first;

return target;
}

#define N 5

int main(void)
{
double a[N] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
double b[N] = { 5.5, 4.4, 3.3, 2.2, 1.1 };
double c[2 * N];
int i;

printf( "A: " );
for ( i = 0; i < N; i++ ) printf( "%1.1lf ", a );
printf( "\n" );

printf( "B: " );
for ( i = 0; i < N; i++ ) printf( "%1.1lf ", b );
printf( "\n" );

copy_ptrs( copy_ptrs( c, a, a + N ), b, b + N );

printf( "C: " );
for ( i = 0; i < 2 * N; i++ ) printf( "%1.1lf ", c );
printf( "\n" );

return 0;
}


The program output is
 
A: 1.1 2.2 3.3 4.4 5.5
B: 5.5 4.4 3.3 2.2 1.1
C: 1.1 2.2 3.3 4.4 5.5 5.5 4.4 3.3 2.2 1.1



Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 13:23. Заголовок: Trying to understand..


Trying to understand your first example, stepping through the code with the debugger I notice it's going backwards when putting things into target

I tried adding comments to help myself follow the logic here:

void copy_ptrs(double *target, double *source, double *lastElement)
{
// go to source get what's there
// go to lastElement get what's there
// if they're not the same continue

// (increment source)


for (; *source != *lastElement; ++source)
{

// get whatever is at source
// increase target location and get whatever is at target
// assign whatever is at source to target

// (increment source + repeat until source and lastElement are equal)

*target++ = *source;
}

}

how does target[4] end up being the first element to be filled? or am I reading my debugging window incorrectly?

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 07.04.15 14:01. Заголовок: ScottyScott пишет: ..


ScottyScott пишет:

 цитата:
how does target[4] end up being the first element to be filled?



I do not understand what you mean. The function sequantially fills elements pointed to by pointer target. For example after assigning the first element pointed to by target target is increased and so on.

Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 08.04.15 13:14. Заголовок: I understand, but wh..


I understand, but when I step through with a debugger, target seems to pointing to the back?

http://i.imgur.com/RfG97Wa.png

so, target + 4 gets filled first, then moved down and target + 3 and so on.

I thought target would be filled first, followed by target + 1 and etc.

the debug window linked above shows what I mean.

again, you're being super cool with this. thanks man.


Спасибо: 0 
ПрофильЦитата Ответить



ссылка на сообщение  Отправлено: 08.04.15 13:32. Заголовок: It looks strange. Yo..


It looks strange. You should look through the generated assembler code.

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 2
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет