第一个程序,指向结构和realloc .... [英] first program with pointers to structures and realloc....

查看:88
本文介绍了第一个程序,指向结构和realloc ....的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我想尝试一些我觉得非常好的东西

练习...我从键盘和商店读取数据它们采用

结构。有一个名为data_pointer的指针。我用它来跟踪结构......但它有点令人困惑 - 我的

程序不会编译而且我不知道该怎么办

警告/错误信息。


c:\documents and settings\dell\Desktop\test\main.c (5):警告

C4115:''tablevalues'':括号中的命名类型定义


c:\documents and settings \dell\Desktop \ test\main.c(41):警告

C4133:''功能'':不兼容的类型 - 从''tablevalues *''到

'' tablevalues *''


c:\documents and settings\dell\Desktop\test\main.c(75):错误

C2065 :''tablevalues'':未声明的标识符


c:\documents and settings \dell \Desktop\test\main.c(80):warning

C4133:''='':不兼容的类型 - 从''int *''到''tablevalues *''


c:\documents and settings\dell\Desktop\test\main.c(84):错误

C2107:非法索引,间接不允许

- - - - - - - - - - - - - - - - - - - -

#include< stdlib .h>

#include< stdio.h>

void save_in_memory(struct tablevalues * data_pointer,

unsigned * number_of_sets_in_memory,
unsigned increase_memory_number,

double double_x,int var1,

int var2,int var3);


/ * ************主程序************ * /


int main()

{


const unsigned increase_memory_number = 3;

unsigned number_of_sets_in_memory;


double doub_x;

int va1,va2,va3;


typedef struct

{

double double_x;

int var1;

int var2;

int var3;

} tablevalues;


tabl evalues * data_pointer;

number_of_sets_in_memory = 0; / *这一刻没有任何东西存储在

* /


/ *获取用户输入 - 并存储数据* /

printf("输入一个double值,后跟3个整数:\ n");

while(scanf("%lf%d%d%d \ n", & doub_x,& va1,& va2,& va3)==

4)

{

save_in_memory(data_pointer,

& number_of_sets_in_memory,

increase_memory_number,

doub_x,va1,

va2,va3);

printf("输入单个double值,然后是3

整数:\ n");

}

退出(EXIT_SUCCESS);

}

/ * ************功能************ * /


void save_in_memory(struct tablevalues * data_pointer,

unsigned * number_of_sets_in_memory,

unsigned increase_memory_number,

double double_x,int var1,

int var2,int var3)

{

unsigned i; / * counter * /

int * tmp_ptr;


/ *更新计数器当前保存多少* /

* number_of_sets_in_memory ++;


/ *需要分配更多内存吗? * /

if(* number_of_sets_in_memory%increase_memory_number == 0)

{


/ *首先为指针数组分配空间* /

if((tmp_ptr = realloc(data_pointer,

(* number_of_sets_in_memory + increase_memory_number)

* sizeof(tablevalues)))== NULL){

printf(内存失败!\ n\ n);

退出(EXIT_FAILURE);

}

/ * ???可能我需要将旧值复制到新的

数组??? * /

data_pointer = tmp_ptr;

}


/ *好的,有足够的可用内存 - 现在:将信息存储在

structure-1 * /

data_pointer [number_of_sets_in_memory-1] - > double_x =

double_x;

data_pointer [ number_of_sets_in_memory-1] - > var1 = var1;

data_pointer [number_of_sets_in_memory-1] - > var2 = var2;

data_pointer [number_of_sets_in_memory-1] - > var3 = var3;

}


- - - - - - - - - - - - - - - - - - - -


如果有人可以帮助我让程序运行,我会很高兴。

然后我想调试它并观察不同地方发生的事情

在记忆中...... :-)


我还记得另一件事:也许data_pointer

变量应该是**指针而不是*指针。我实际上得到了整个程序来编译和运行**

指针(没有警告/错误),但后来我说服了自己

一个* -pointer会一样好,我修改了整个

程序...我很感激任何评论...


现在我不记得当我让程序工作时我做了什么

使用** - data_pointer ...... :-)

祝你好运/ Med venlig希尔森

Martin J?rgensen


-

--------------- -------------------------------------------------- ----------

Martin J?rgensen的家 - http://www.martinjoergensen.dk

Hi,

I wanted to try something which I think is a very good
exercise... I read in data from the keyboard and store them in a
structure. There''s a pointer called "data_pointer" which I use to
keep track on the structures... But it''s a bit confusing - my
program won''t compile and I don''t know what to do about the
warnings/error messages.

c:\documents and settings\dell\Desktop\test\main.c(5) : warning
C4115: ''tablevalues'' : named type definition in parentheses

c:\documents and settings\dell\Desktop\test\main.c(41) : warning
C4133: ''function'' : incompatible types - from ''tablevalues *'' to
''tablevalues *''

c:\documents and settings\dell\Desktop\test\main.c(75) : error
C2065: ''tablevalues'' : undeclared identifier

c:\documents and settings\dell\Desktop\test\main.c(80) : warning
C4133: ''='' : incompatible types - from ''int *'' to ''tablevalues *''

c:\documents and settings\dell\Desktop\test\main.c(84) : error
C2107: illegal index, indirection not allowed
- - - - - - - - - - - - - - - - - - - -
#include <stdlib.h>
#include <stdio.h>
void save_in_memory( struct tablevalues *data_pointer,
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3);

/* ************ Main program ************ */

int main()
{

const unsigned increase_memory_number = 3;
unsigned number_of_sets_in_memory;

double doub_x;
int va1, va2, va3;

typedef struct
{
double double_x;
int var1;
int var2;
int var3;
} tablevalues;

tablevalues *data_pointer;
number_of_sets_in_memory = 0; /* there''s nothing stored at
this moment */

/* get user input - and store the data */
printf("Enter a double value, followed by 3 integers:\n");
while( scanf("%lf %d %d %d\n", &doub_x, &va1, &va2, &va3) ==
4)
{
save_in_memory( data_pointer,
&number_of_sets_in_memory,
increase_memory_number,
doub_x, va1,
va2, va3);
printf("Enter single double value, followed by 3
integers:\n");
}
exit(EXIT_SUCCESS);
}
/* ************ Function ************ */

void save_in_memory( struct tablevalues *data_pointer,
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3)
{
unsigned i; /* counter */
int *tmp_ptr;

/* update counter of how much is saved currently */
*number_of_sets_in_memory++;

/* need to allocate more memory ? */
if(*number_of_sets_in_memory % increase_memory_number == 0)
{

/* first allocate space for the pointer array */
if ((tmp_ptr = realloc(data_pointer,
(*number_of_sets_in_memory + increase_memory_number)
* sizeof(tablevalues) )) == NULL) {
printf("Memory failure!\n\n");
exit(EXIT_FAILURE);
}
/* ??? possibly I need to copy the old values to the new
array ??? */
data_pointer = tmp_ptr;
}

/* Ok, enough memory available - now: store information in
structure-1 */
data_pointer[number_of_sets_in_memory-1]->double_x =
double_x;
data_pointer[number_of_sets_in_memory-1]->var1 = var1;
data_pointer[number_of_sets_in_memory-1]->var2 = var2;
data_pointer[number_of_sets_in_memory-1]->var3 = var3;
}

- - - - - - - - - - - - - - - - - - - -

If somebody can help me get the program to work, I would be glad.
Then I want to debug it and watch what happens different places
in memory... :-)

One other thing on my mind is: Perhaps the "data_pointer"
variable should have been an ** pointer instead of a * pointer. I
actually got the whole program to compile and run using a **
pointer (without warnings/errors), but then I convinced myself
that a *-pointer would be just as good and I modified the whole
program... I would appreciate any comments on this...

Now I can''t remember what I did when I got the program to work
using a **-data_pointer... :-)
Best regards / Med venlig hilsen
Martin J?rgensen

--
---------------------------------------------------------------------------
Home of Martin J?rgensen - http://www.martinjoergensen.dk

推荐答案

文章< f2 ****** ******@news.tdc.dk>

Martin Joergensen< un ********* @ spam.jay.net>写道:
In article <f2************@news.tdc.dk>
Martin Joergensen <un*********@spam.jay.net> wrote:
...我的程序不会编译,我不知道如何处理
警告/错误消息。

c :\documents and settings \dell\Desktop\test\main.c(5):warning
C4115:''tablevalues'':括号中的命名类型定义


GCC'的投诉可能稍微有用:


警告:`struct tablevalues''在参数列表中声明

警告:其范围只是这个定义或声明,

这可能不是你想要的。

c:\documents and settings \dell \Desktop\test \ main。 c(41):警告
C4133:''功能'':不兼容的类型 - 从''tablevalues *''到
''tablevalues *''


然而,这个特别的抱怨是完全错误的。其中一个类型确实是tablevalues *,但另一个是struct

tablevalues *。不同之处在于,第二个关键字是struct,而不是
关键字struct。在它面前,向世界(以及人类程序员)宣布这实际上是一个类型名称。第一个

看起来像一个普通的变量名;但如果是,那将是

a语法错误,所以它必须是通过类型别名定义的标识符。


[snippage - 代码片段如下]

#include< stdlib.h>
#include< stdio.h>

void save_in_memory(struct tablevalues * data_pointer,
unsigned * number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x,int var1,
int var2,int var3);


这是第一个问题:struct tablevalues这里出现在

括号中。这是命名类型。 (按照你的编译器)。

但是,正如GCC所说,这个声明的范围 - 那个

存在一个名为struct tablevalues的类型。 - 仅限于

原型声明。一旦原型结束,类型名称

就会消失,永远不会再被提及。


这是事情变得有点棘手的地方。如果你写:


void f(无效){

int x;

...

}

void g(无效){

int x;

...

}


我们都知道f()中的x与g()中的

x完全不同。两者都是int x。但它们不是同一个变量;

如果g()调用f(),两个x同时变为活动状态。


这种情况​​发生因为两个x具有不同的范围。


类型名称也会出现同样的情况。如果您创建一个新的

类型:


struct zorg;


此类型可以命名,直到它的名称为止范围终止。然后它有超出范围的
,它永远不会再被命名。因此:


void f(无效){

struct zorg {int i; };

struct zorg a,b,x,y;

...

}

void g (无效){

struct zorg {double d; char * p; };

struct zorg a,b,x,y;

...

}


不仅是a,b,x和y,还是y。 f()和g()不同,所以

是两个不同的struct zorg!它们都被命名为struct

zorg,但它们有不同的内容,实际上是不同的

类型。


与变量一样,在内部和外部范围内使类型名称做双重任务通常是个坏主意。请考虑以下代码

片段:


int bang;

void f(无效){

double bang;

...

}


假设我现在说的是:当爆炸为负时 ;。

哪个爆炸我在说什么?显然我必须更具体。


同样适用于类型名称(我们使用struct定义

关键字,像往常一样):


struct zorg {int i; };

void g(无效){

struct zorg {double d; char * p; };

...

}


在这种情况下,如果我说一下当d的成员一个zorg

是否定的,很明显我指的是g()中的zorg,而

不是外部zorg,因为只有inner-zorg有一个 ; d" ;.但是这仍然不是一个很好的想法,允许这种混乱。


你现在的问题是,你正在尝试

声明函数save_in_memory(),完成原型,

但类型为tablevalues。尚未宣布。解决方案

很简单:声明类型。然后

原型中的内部范围名称将引用外部范围中已声明为

的* same *类型。这就像*不*声明一个新的
" struct zorg"在g()中。所以现在我们有:


struct tablevalues; / *这只是声明类型。 * /


void save_in_memory(struct tablevalues * data_pointer,

unsigned int * number_of_sets_in_memory,

unsigned int increase_memory_number,
double double_x,int var1,int var2,int var3);


我们继续:

/ * ****** ******主程序************ * /


[此评论有点多余:-)]

int main()
{


[最好写int main(void){...},以便提供一个

原型以及定义,但这没关系。

const unsigned increase_memory_number = 3;
unsigned number_of_sets_in_memory;


[我更喜欢写出unsigned int,但这也没问题]

double doub_x;
int va1,va2, va3;

typedef struct
{double double_x;
int var1;
int var2;
int var3;
} tablevalues;


这里有一个问题:这会创建一个新的,未命名的类型 - 我们

写道struct {不使用标签 - 然后typedef是该未命名类型的

别名。 (请记住,typedef * never *定义

一个新类型;它只为现有类型创建别名。)所以这个

产生一个名为tablevalues的类型别名这是

的别名,没有标记的结构。但事实上,至少

一个特定的人类 - 虽然不是电脑 - 显然你要b $ b想在这里使用*相同*结构类型在你的函数中

save_in_memory()。


您可以通过执行以下操作来尝试修复此问题:


typedef struct tablevalues tablevalues;

struct tablevalues {... contents ...};


(假设你坚持使用无用的typedef) ,否则

你可以完全省略该行。但这注定要失败:

为我定义一个新类型的语法是写:


struct tagname_opt {... contents ...};


所以这意味着定义一个*新* ,内部范围类型名为struct

tablevalues"。 typedef-name" tablevalues"现在将

引用到旧的,外部范围的struct tablevalues,而新的,
内部范围struct tablevalues是一种新的和不同的类型,

无论内容如何部分。


唯一的解决方案是定义(不仅仅是声明)struct

tablevalues。键入* outside * main()。你可以在main()之前,之前或之后的任何时候做这个
,在save_in_memory()的原型之前或之后,

只要你至少*声明*存在

之前的类型定义原型。


再次,请记住声明之间的区别:


我声明圣诞老人存在!


实际上并没有描述任何东西,只是说它存在b $ b和一个定义:


他是以前称为Joe Shlabotnik的人。上周他的名字改变了他的

名字。


这不仅告诉你存在某些东西,而且还给你

all详情(这可能与你b $ b预期的那些:-)完全不同。


所以现在,考虑到所有这些,我们可以重写代码最多

这一点:


#include ... / *包括,根据需要* /


struct tablevalues;

[再次声明该类型存在,所以

save_in_memory可以参考它]


void save_in_memory(struct tablevalues * data_pointer,

unsigned int * number_of_sets_in_memory,

unsigned int increase_memory_number,

double double_x,int var1, int var2,int var3);


struct tablevalues {

double double_x;

int var1;

int var2;

int var3;

};

[这实际上*定义*类型,所以现在我们可以使用。 var1

成员等等]


int main(void){

const unsigned int increase_memory_number = 3;

unsigned int number_of_sets_in_memory;

double doub_x;

int va1,va2,va3;

tablevalues * data_pointer;


由于我讨厌无用的typedef,我只想扩展一下:


struct tablevalues * data_pointer;

number_of_sets_in_memory = 0; / *这一刻没有任何东西存储在这个时刻* /

/ *获取用户输入 - 并存储数据* /
printf("输入一个双精度值,然后是3个整数:\ n");
while(scanf("%lf%d%d%d \ n",& doub_x,& va1,& va2,& va3) == 4)
{


[到目前为止很好]

save_in_memory(data_pointer,
& number_of_sets_in_memory, increase_memory_number,
doub_x,va1,
va2,va3);


我们遇到了问题。在第一次调用save_in_memory()时,

存储在data_pointer中的值是多少? (你在上面初始化了

吗?)而且,你给了save_in_memory()一个名为number_of_sets_in_memory的

的地址,以便save_in_memory()

可以更改number_of_sets_in_memory,但是你没有给出
save_in_memory()地址data_pointer,所以save_in_memory()

*不能*改变 ; data_pointer"。


第二个问题有很多不同的解决方案,

其中至少有两个完全合理且非常传统:

或者给save_in_memory()提供data_pointer的地址,或者根据需要更改

它为data_pointer返回一个新值。 (第三个
解决方案是打包几个项目 - 至少数据指针

和项目数,也许还有increase_memory_number,

在另一个struct类型中,并将指针传递给

类型的实例。)


其余部分代码我不会解决太多问题,除了

注意严重的错误并提一个我觉得非常有用的技术:

void save_in_memory(struct tablevalues * data_pointer,
unsigned * number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x,int var1,
int var2,int var3)
{


在这个函数中,你会引用很多次

(确切地说是7次)到* number_of_sets_in_memory。我发现它更好,在这种情况下,制作本地副本

* number_of_sets_in_memory,使用本地副本,

把最终结果放在合适的地方。之前

返回。 (Somewhere可以是刚刚结束,或者只要新值已知,或者b / b
方便的话。 )

未签名的i; / * counter * /
[" i"永远不会使用] int * tmp_ptr;


tmp_ptr应该与data_pointer具有相同的类型(如果你更改

函数来获取指向main()的data_pointer的指针,你可以

使用与* number_of_sets_in_memory相同的技术)。

/ *更新计数器当前保存了多少* /
* number_of_sets_in_memory ++;


运营商*和++绑定(有优先级,因为有些人把它放在

它,但是绑定是一个更好的词),而不是你想要的方式:

这意味着:


*(number_of_sets_in_memory)++;


但你想要:


(* number_of_sets_in_memory)++;

/ *需要分配更多内存吗? * /
if(* number_of_sets_in_memory%increase_memory_number == 0)
{

/ *首先为指针数组分配空间* /
if((tmp_ptr = realloc) (data_pointer,
* sizeof(tablevalues)))== NULL){
printf(" Memory failure!\ n\ nn);;
退出(EXIT_FAILURE);
}
/ * ???可能我需要将旧值复制到新的
数组??? * /
data_pointer = tmp_ptr;


您不需要复制值(realloc()已经完成了),但

你*做*需要通知main(),in某种方式,它是数据指示的旧版本副本。已经过时了,它应该使用

新的。

}

/ *好的,有足够的可用内存 - 现在:存储信息
structure-1 * /
data_pointer [number_of_sets_in_memory-1] - > double_x =
double_x;
data_pointer [number_of_sets_in_memory-1] - > var1 = var1;
data_pointer [number_of_sets_in_memory-1] - > var2 = var2;
data_pointer [number_of_sets_in_memory-1] - > var3 = var3;


如果是data_pointer是指向结构的指针,然后必然是
" data_pointer [i]"对于某些有效索引,我是

结构的一个实例 - 所以这些应该是data_pointer [i] .field = value。

}
... my program won''t compile and I don''t know what to do about the
warnings/error messages.

c:\documents and settings\dell\Desktop\test\main.c(5) : warning
C4115: ''tablevalues'' : named type definition in parentheses
GCC''s complaint is perhaps slightly more useful:

warning: `struct tablevalues'' declared inside parameter list
warning: its scope is only this definition or declaration,
which is probably not what you want.
c:\documents and settings\dell\Desktop\test\main.c(41) : warning
C4133: ''function'' : incompatible types - from ''tablevalues *'' to
''tablevalues *''
This particular complaint is just plain wrong, however. One of
the types is indeed "tablevalues *", but the other is "struct
tablevalues *". The difference is that the second one has the
keyword "struct" in front of it, announcing to the world (and the
human programmer) that this is in fact a type-name. The first
looks like an ordinary variable name; but if it were, it would be
a syntax error, so it must be an identifier defined via a type-alias.

[snippage - code fragment follows]
#include <stdlib.h>
#include <stdio.h>

void save_in_memory( struct tablevalues *data_pointer,
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3);
Here is the first problem: "struct tablevalues" appears here in
parentheses. This is a "named type" (as per to your compiler).
But, as GCC says, the scope of this declaration -- that there
exists a type called "struct tablevalues" -- is limited to the
prototype declaration. Once the prototype ends, the type-name
vanishes, and can never be mentioned again.

This is where things get a little tricky. If you write:

void f(void) {
int x;
...
}
void g(void) {
int x;
...
}

we all understand that the x in f() is quite different from the
x in g(). Both are "int x" but they are not the same variable;
if g() calls into f(), both "x"s become active simultaneously.

This occurs because the two "x"s have different scope.

The same thing occurs with type-names. If you create a new
type:

struct zorg;

this type is name-able until its scope terminates. Then it has
gone out of scope and it can never be named again. Thus:

void f(void) {
struct zorg { int i; };
struct zorg a, b, x, y;
...
}
void g(void) {
struct zorg { double d; char *p; };
struct zorg a, b, x, y;
...
}

Not only are "a", "b", "x", and "y" different in f() and g(), so
are the two different "struct zorg"s! They are both named "struct
zorg", but they have different contents and are in fact different
types.

As with variables, it is usually a bad idea to make a type-name do
double duty in inner vs outer scopes. Consider the following code
fragment:

int bang;
void f(void) {
double bang;
...
}

Suppose I now say something beginning with: "when bang is negative".
Which "bang" am I talking about? Obviously I will have to be
more specific.

The same holds for type-names (which we define with the "struct"
keyword, as usual):

struct zorg { int i; };
void g(void) {
struct zorg { double d; char *p; };
...
}

In this case, if I say something about "when the d member of a zorg
is negative", it is clear enough that I mean the zorg in g(), and
not the outer zorg, because only inner-zorg has a "d". But it is
still not a great idea to allow for this kind of confusion.

The problem you have, at this point, is that you are trying to
declare the function save_in_memory(), complete with a prototype,
but the type "tablevalues" has not yet been declared. The solution
is simple: declare the type. Then the inner-scope name in the
prototype will refer to the *same* type that is already declared
in the outer scope. This is just like *not* declaring a new
"struct zorg" inside g(). So now we have:

struct tablevalues; /* This just declares the type. */

void save_in_memory(struct tablevalues *data_pointer,
unsigned int *number_of_sets_in_memory,
unsigned int increase_memory_number,
double double_x, int var1, int var2, int var3);

We proceed onward:
/* ************ Main program ************ */
[this comment is a little redundant :-) ]
int main()
{
[better to write "int main(void) { ... }", so as to provide a
prototype along with the definition, but this is OK]
const unsigned increase_memory_number = 3;
unsigned number_of_sets_in_memory;
[I prefer to write out "unsigned int", but this is also OK]
double doub_x;
int va1, va2, va3;

typedef struct
{
double double_x;
int var1;
int var2;
int var3;
} tablevalues;
Here we have a problem: this creates a new, unnamed type -- we
wrote "struct {" without using a tag -- and then "typedef"s an
alias for that unnamed type. (Remember, typedef *never* defines
a new type; it only makes aliases for existing types.) So this
produces a type-alias named "tablevalues" that is an alias for
a structure with no tag. But in fact, it is obvious to at least
one particular human -- though not to a computer -- that you
wanted to use the *same* structure type here as in your function
save_in_memory().

You could attempt to repair this by doing something like:

typedef struct tablevalues tablevalues;
struct tablevalues { ... contents ... };

(assuming you insist on using the useless "typedef", otherwise
you could omit that line entirely). But this is doomed to fail:
the syntax for "define a new type for me" is to write:

struct tagname_opt { ... contents ... };

so this means "define a *new*, inner-scope type named struct
tablevalues". The typedef-name "tablevalues" will now refer
to the old, outer-scope "struct tablevalues", while the new,
inner-scope "struct tablevalues" is a new and different type,
regardless of the "contents" part.

The only solution is to define (not just declare) the "struct
tablevalues" type *outside* main(). You can do this at any point
before main(), before or after the prototype for save_in_memory(),
as long as you at least *declare* the existence of the type before
defining the prototype.

Again, keep in mind the difference between a "declaration":

I declare that Santa Claus exists!

which does not actually describe anything, just say that it
exists, and a "definition":

He''s the guy formerly known as Joe Shlabotnik. He had his
name legally changed last week.

which not only tells you that something exists, but gives you
all the particulars (which may be quite different from what you
were expecting :-) ).

So now, with all that in mind, we can rewrite the code up to
this point:

#include ... /* do includes, as needed */

struct tablevalues;
[again this just declares that the type exists, so that
save_in_memory can refer back to it]

void save_in_memory(struct tablevalues *data_pointer,
unsigned int *number_of_sets_in_memory,
unsigned int increase_memory_number,
double double_x, int var1, int var2, int var3);

struct tablevalues {
double double_x;
int var1;
int var2;
int var3;
};
[this actually *defines* the type, so now we can use the .var1
member and so on]

int main(void) {
const unsigned int increase_memory_number = 3;
unsigned int number_of_sets_in_memory;
double doub_x;
int va1, va2, va3;
tablevalues *data_pointer;
Since I hate useless "typedef"s, I will just expand this one out:

struct tablevalues *data_pointer;
number_of_sets_in_memory = 0; /* there''s nothing stored at
this moment */

/* get user input - and store the data */
printf("Enter a double value, followed by 3 integers:\n");
while( scanf("%lf %d %d %d\n", &doub_x, &va1, &va2, &va3) == 4)
{
[so far so good]
save_in_memory( data_pointer,
&number_of_sets_in_memory,
increase_memory_number,
doub_x, va1,
va2, va3);
Here we have a problem. On the first call to save_in_memory(),
what is the value stored in "data_pointer"? (Did you initialize
it above?) Moreover, you gave save_in_memory() the address of the
thing named "number_of_sets_in_memory", so that save_in_memory()
can change number_of_sets_in_memory, but you did not give
save_in_memory() the address of "data_pointer", so save_in_memory()
*cannot* change "data_pointer".

There are a number of different solutions to this second problem,
at least two of them perfectly reasonable and quite conventional:
either give save_in_memory() the address of data_pointer, or change
it to return a new value for data_pointer, as desired. (A third
solution is to package up several items -- at least the data pointer
and the count of items, and perhaps also the "increase_memory_number",
in yet another "struct" type and pass a pointer to an instance of
that type.)

The rest of the code I am not going to address too much, except
to note serious bugs and mention a technique I find quite useful:
void save_in_memory( struct tablevalues *data_pointer,
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3)
{
Inside this function, you will refer, quite a few times
(7 times, to be exact) to "*number_of_sets_in_memory". I
find it works better, in such cases, to make a local copy
of *number_of_sets_in_memory, work with the local copy, and
put the final result back "somewhere appropriate" before
returning. ("Somewhere" can be "just at the end", or
"as soon as the new value is known", or whatever is most
convenient.)
unsigned i; /* counter */ ["i" is never used] int *tmp_ptr;
tmp_ptr should have the same type as data_pointer (and if you change
the function to take a pointer to main()''s data_pointer, you can
use the same technique as for *number_of_sets_in_memory here).
/* update counter of how much is saved currently */
*number_of_sets_in_memory++;
The operators "*" and "++" bind ("have precedence", as some put
it, but "bind" is a better word) in a way other than what you want:
this means:

*(number_of_sets_in_memory)++;

but you want:

(*number_of_sets_in_memory)++;
/* need to allocate more memory ? */
if(*number_of_sets_in_memory % increase_memory_number == 0)
{

/* first allocate space for the pointer array */
if ((tmp_ptr = realloc(data_pointer,
(*number_of_sets_in_memory + increase_memory_number)
* sizeof(tablevalues) )) == NULL) {
printf("Memory failure!\n\n");
exit(EXIT_FAILURE);
}
/* ??? possibly I need to copy the old values to the new
array ??? */
data_pointer = tmp_ptr;
You do not need to copy the values (realloc() has done that), but
you *do* need to inform main(), in some way or another, that its
old copy of "data_pointer" is out of date and it should use the
new one.
}

/* Ok, enough memory available - now: store information in
structure-1 */
data_pointer[number_of_sets_in_memory-1]->double_x =
double_x;
data_pointer[number_of_sets_in_memory-1]->var1 = var1;
data_pointer[number_of_sets_in_memory-1]->var2 = var2;
data_pointer[number_of_sets_in_memory-1]->var3 = var3;
If "data_pointer" is a pointer to the structure, then necessarily
"data_pointer[i]" for some valid index i is an instance of the
structure -- so these should be "data_pointer[i].field = value".
}




在这种特殊情况下,我可能更有可能从修改后的函数返回新的

data_pointer值;但为了说明

我刚才说的一切,这里有一个指向

的指针data_pointer更新,以及指向

的(单独的)指针number_of_sets_in_memory更新:


void save_in_memory(
struct tablevalues ** tpp,

unsigned int * nsaved,unsigned int nincrease,

double x,int var1,int var2,int var3

){

struct tablevalues * tp = * tpp;

int old_n = * nsaved,new_n = old_n + 1;


/ *如果需要扩展表格* /

if((new_n%nincrease) == 0){

/ *

*请注意,我们这里有一个*副本* * tpp。如果我们把垃圾归还给我们b $ b *我们的副本,那又怎样?原版仍在* tpp。

* /

tp = realloc(tp,(old_n + nincrease)* sizeof * tp);

if(tp == NULL){

/ *

*真的应该返回一些失败指示

*而不是粗暴地退出。 (作为低

*级别功能,我们​​不应该做出重大的

*战略决策 - 比如完全放弃

* - 在这个级别:我们应该只报告

*问题,让更高级别的代码决定如何处理它。)但是这里save_in_memory()有

*没有返回值,所以没有明显的方法来表示

*失败。

* /

fprintf( stderr,不能分配内存;)

退出(EXIT_FAILURE);

}

* tpp = tp; / *分配成功 - 更新来电者的* tpp * /

}


/ *

*这里old_n仍然没改变,new_n仍然是old_n + 1,

*和(new_n%nincrease)非零,意思是

*我们在表中有空间,或者表大小有已经

*成功增加,这意味着我们现在有空间在桌子上。所以只需输入值,并记住

*来更新调用者的内存中的数字。值也是。

* /

tp [old_n] .double_x = x;

tp [old_n] .var1 = var1;

tp [old_n] .var2 = var2;

tp [old_n] .var3 = var3;

* nsaved = new_n; / *这可能发生在这里的任何地方* /

}


目前,新版本的版本要长得多,但仅仅因为

所有评论。

-

In-Real-Life:风河系统Chris Torek

盐湖城, UT,USA(40°39.22''N,111°50.29''W)+1 801 277 2603

电子邮件:忘了它 http://web.torek.net/torek/index.html

阅读电子邮件就像搜索垃圾邮件中的食物。感谢垃圾邮件发送者。



In this particular case, I might be more likely return the new
data_pointer value from the modified function; but to illustrate
everything I just said, here is a version that takes a pointer to
the "data_pointer" to update, as well as a (separate) pointer to
the "number_of_sets_in_memory" to update:

void save_in_memory(
struct tablevalues **tpp,
unsigned int *nsaved, unsigned int nincrease,
double x, int var1, int var2, int var3
) {
struct tablevalues *tp = *tpp;
int old_n = *nsaved, new_n = old_n + 1;

/* expand the table if needed */
if ((new_n % nincrease) == 0) {
/*
* Note that we have a *copy* of *tpp here. If we trash
* our copy, so what? The original is still in *tpp.
*/
tp = realloc(tp, (old_n + nincrease) * sizeof *tp);
if (tp == NULL) {
/*
* Really should return some failure indication
* rather than just rudely exiting. (As a "low
* level function", we should not be making major
* strategic decisions -- like giving up entirely
* -- at this level: we should just report the
* problem, and let higher level code decide how
* to handle it.) But here save_in_memory() has
* no return value, so no obvious way to indicate
* failure.
*/
fprintf(stderr, "can''t allocate memory");
exit(EXIT_FAILURE);
}
*tpp = tp; /* allocation succeeded - update caller''s *tpp */
}

/*
* Here old_n is still unchanged, new_n is still old_n+1,
* and either (new_n % nincrease) was nonzero, meaning
* we had room in the table, or the table size has been
* increased successfully, meaning we now have room in
* the table. So just put in the values, and remember
* to update the caller''s "number in memory" value too.
*/
tp[old_n].double_x = x;
tp[old_n].var1 = var1;
tp[old_n].var2 = var2;
tp[old_n].var3 = var3;
*nsaved = new_n; /* this can happen anywhere along here */
}

At the moment, the new version is much longer, but only because
of all the comments.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22''N, 111°50.29''W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


Martin Joergensen写道:
Martin Joergensen wrote:


我想要尝试一些我认为非常好的练习......我从键盘读取数据并将它们存储在一个结构中。有一个名为data_pointer的指针。我用它来跟踪
结构...但它有点令人困惑 - 我的程序不会编译,我不知道如何处理警告/错误消息。

c:\documents and settings \dell\Desktop\test\main.c(5):警告C4115:
''tablevalues'':命名类型括号中的定义

c:\documents and settings \dell\Desktop\test\main.c(41):警告C4133:
''功能'':不兼容类型 - 从''tablevalues *''到''tablevalues *''

c:\documents and settings\dell\Desktop\test\main.c(75):error C2065:
''tablevalues'':未声明的标识符

c:\documents and settings \dell\Desktop\test\main.c(80):警告C4133:
''='':不兼容的类型 - 从''int *''到''tablevalues *''

c:\documents and settings \de ll\Desktop\test\main.c(84):错误C2107:
非法索引,间接不允许

- - - - - - - - - - - - - - - - - - - -
#include< stdlib.h>
#include< stdio.h>

void save_in_memory(struct tablevalues * data_pointer,


你还没告诉编译器什么类型的struct tablevalues!在C

之前,你应该在使用它们之前声明它们。

unsigned * number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x,int var1,
int var2,int var3);

/ * ************主程序************ * /

int main()

const unsigned increase_memory_number = 3;
unsigned number_of_sets_in_memory;

double doub_x;
int va1,va2,va3;

typedef struct
{double double_x;
int var1;
int var2;
int var3;
} tablevalues;


在这里你声明一个结构的本地定义,但是它与

完全没有任何关系。另外,这确实没有定义struct tablevalues,它定义了一个未命名的struct并给它

一个只是tablevalues的别名。

tablevalues * data_pointer;

number_of_sets_in_memory = 0; / *没有任何东西存储在这个
时刻* /

/ *获取用户输入 - 并存储数据* /
printf("输入一个双精度值,然后是3个整数:\ n");
while(scanf("%lf%d%d%d \ n",& doub_x,& va1,& va2,& va3) == 4)
{
save_in_memory(data_pointer,
&number_of_sets_in_memory,
increase_memory_number,
doub_x,va1,
va2,va3);
printf("输入单个double值,后跟3个整数:\ n");
}

退出(EXIT_SUCCESS);
}

/ * ************函数************ * /

void save_in_memory(struct tablevalues * data_pointer,


到这里,你的typedef超出了范围。

unsigned * number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x,int v ar1,
int var2,int var3)
{
未签名的i; / * counter * /
int * tmp_ptr;

/ *更新当前保存多少的计数器* /
* number_of_sets_in_memory ++;

/ *需要分配更多内存? * /
if(* number_of_sets_in_memory%increase_memory_number == 0)
{

/ *首先为指针数组分配空间* /
if((tmp_ptr = realloc) (data_pointer,


唯一的data_pointer是main的本地变量,你怎么期望这个函数能看到这个函数?

(* number_of_sets_in_memory + increase_memory_number)
* sizeof(tablevalues)))== NULL){
printf(Memory failure!\ n\ n);
exit(EXIT_FAILURE );
}
/ * ???可能我需要将旧值复制到新数组
??? * /


阅读C课本。它会告诉你realloc定义为

为你处理。

data_pointer = tmp_ptr;
}

/ *好的,足够的内存可用 - 现在:将信息存储在
structure-1 * /
data_pointer [number_of_sets_in_memory-1] - > double_x = double_x;
data_pointer [number_of_sets_in_memory-1] - > var1 = var1;
data_pointer [number_of_sets_in_memory-1] - > var2 = var2;
data_pointer [number_of_sets_in_memory-1] - > var3 = var3;
}

- - - - - - - - - - - - - - - - - - - -
如果有人可以帮助我让程序工作,我会很高兴的。然后我想调试它并观察内存中不同位置发生的事情...... :-)

我想到的另一件事是:也许是data_pointer。变量
应该是**指针而不是*指针。我实际上已经整个程序使用**指针进行编译和运行(没有
警告/错误),但后来我确信一个* -pointer会同样好,我修改了整个程序...我很感激对此的任何评论...

现在我不记得当我使用<程序工作时我做了什么br /> ** - data_pointer ...: - )
Hi,

I wanted to try something which I think is a very good exercise... I
read in data from the keyboard and store them in a structure. There''s a
pointer called "data_pointer" which I use to keep track on the
structures... But it''s a bit confusing - my program won''t compile and I
don''t know what to do about the warnings/error messages.

c:\documents and settings\dell\Desktop\test\main.c(5) : warning C4115:
''tablevalues'' : named type definition in parentheses

c:\documents and settings\dell\Desktop\test\main.c(41) : warning C4133:
''function'' : incompatible types - from ''tablevalues *'' to ''tablevalues *''

c:\documents and settings\dell\Desktop\test\main.c(75) : error C2065:
''tablevalues'' : undeclared identifier

c:\documents and settings\dell\Desktop\test\main.c(80) : warning C4133:
''='' : incompatible types - from ''int *'' to ''tablevalues *''

c:\documents and settings\dell\Desktop\test\main.c(84) : error C2107:
illegal index, indirection not allowed
- - - - - - - - - - - - - - - - - - - -
#include <stdlib.h>
#include <stdio.h>

void save_in_memory( struct tablevalues *data_pointer,
You haven''t yet told the compiler what type struct tablevalues is! In C
you should always declare things before using them.
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3);

/* ************ Main program ************ */

int main()
{

const unsigned increase_memory_number = 3;
unsigned number_of_sets_in_memory;

double doub_x;
int va1, va2, va3;

typedef struct
{
double double_x;
int var1;
int var2;
int var3;
} tablevalues;
Here you declare a local definition of a structure, but it has
absolutely nothing to do with anything outside of main. Also, this does
not define struct tablevalues, it defines an unnamed struct and gives it
an alias that is simply tablevalues.
tablevalues *data_pointer;
number_of_sets_in_memory = 0; /* there''s nothing stored at this
moment */

/* get user input - and store the data */
printf("Enter a double value, followed by 3 integers:\n");
while( scanf("%lf %d %d %d\n", &doub_x, &va1, &va2, &va3) == 4)
{
save_in_memory( data_pointer,
&number_of_sets_in_memory,
increase_memory_number,
doub_x, va1,
va2, va3);
printf("Enter single double value, followed by 3 integers:\n");
}
exit(EXIT_SUCCESS);
}
/* ************ Function ************ */

void save_in_memory( struct tablevalues *data_pointer,
By here, your typedef has gone out of scope.
unsigned *number_of_sets_in_memory,
unsigned increase_memory_number,
double double_x, int var1,
int var2, int var3)
{
unsigned i; /* counter */
int *tmp_ptr;

/* update counter of how much is saved currently */
*number_of_sets_in_memory++;

/* need to allocate more memory ? */
if(*number_of_sets_in_memory % increase_memory_number == 0)
{

/* first allocate space for the pointer array */
if ((tmp_ptr = realloc(data_pointer,
The only data_pointer is a variable local to main, how do you expect
this function to see it?
(*number_of_sets_in_memory + increase_memory_number)
* sizeof(tablevalues) )) == NULL) {
printf("Memory failure!\n\n");
exit(EXIT_FAILURE);
}
/* ??? possibly I need to copy the old values to the new array
??? */
Read your C text book. It will tell you that realloc is defined as
handling that for you.
data_pointer = tmp_ptr;
}

/* Ok, enough memory available - now: store information in
structure-1 */
data_pointer[number_of_sets_in_memory-1]->double_x = double_x;
data_pointer[number_of_sets_in_memory-1]->var1 = var1;
data_pointer[number_of_sets_in_memory-1]->var2 = var2;
data_pointer[number_of_sets_in_memory-1]->var3 = var3;
}

- - - - - - - - - - - - - - - - - - - -

If somebody can help me get the program to work, I would be glad. Then I
want to debug it and watch what happens different places in memory... :-)

One other thing on my mind is: Perhaps the "data_pointer" variable
should have been an ** pointer instead of a * pointer. I actually got
the whole program to compile and run using a ** pointer (without
warnings/errors), but then I convinced myself that a *-pointer would be
just as good and I modified the whole program... I would appreciate any
comments on this...

Now I can''t remember what I did when I got the program to work using a
**-data_pointer... :-)




嗯,我肯定肯定会有比你声称的更多的差异。


您需要再次阅读C课本的前几章。那些

,它讨论了范围,局部变量,以及在使用它们之前定义的东西。

-

Flash Gordon,生活在有趣的时代。

网站 - http://home.flash-gordon.me.uk/

comp.lang.c发布指南和介绍:
http://clc-wiki.net/wiki/Intro_to_clc


Inviato da X-Privat.Org - Registrazione gratuita http://www.x -privat.org/join.php



Well, I''m sure there must have been more differences than you claim.

You need to read the early chapters of your C text book again. The ones
where it talks about scope, local variables, and defining things before
using them.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php


Chris Torek< no **** @ torek.net>写道:
Chris Torek <no****@torek.net> writes:
文章< f2 ************ @ news.tdc.dk>
Martin Joergensen< un *** ******@spam.jay.net>写道:
In article <f2************@news.tdc.dk>
Martin Joergensen <un*********@spam.jay.net> wrote:
c:\documents and settings \dell \Desktop\test\main.c(41):warning
C4133:''function'':不兼容的类型 - 从''tablevalues *''到
''tablevalues *''
c:\documents and settings\dell\Desktop\test\main.c(41) : warning
C4133: ''function'' : incompatible types - from ''tablevalues *'' to
''tablevalues *''



然而,这个特别的抱怨是完全错误的。 One of
the types is indeed "tablevalues *", but the other is "struct
tablevalues *". The difference is that the second one has the
keyword "struct" in front of it, announcing to the world (and the
human programmer) that this is in fact a type-name. The first
looks like an ordinary variable name; but if it were, it would be
a syntax error, so it must be an identifier defined via a type-alias.



This particular complaint is just plain wrong, however. One of
the types is indeed "tablevalues *", but the other is "struct
tablevalues *". The difference is that the second one has the
keyword "struct" in front of it, announcing to the world (and the
human programmer) that this is in fact a type-name. The first
looks like an ordinary variable name; but if it were, it would be
a syntax error, so it must be an identifier defined via a type-alias.




This makes me wonder whether a C++ compiler is being used. I

wouldn’’t expect a C compiler to confuse typedefs and structs in

its error messages.


(I didn’’t read the rest of the thread, so I don’’t know if there’’s

something else here that rules out that possibility.)

--

"Given that computing power increases exponentially with time,

algorithms with exponential or better O-notations

are actually linear with a large constant."

--Mike Lee



This makes me wonder whether a C++ compiler is being used. I
wouldn''t expect a C compiler to confuse typedefs and structs in
its error messages.

(I didn''t read the rest of the thread, so I don''t know if there''s
something else here that rules out that possibility.)
--
"Given that computing power increases exponentially with time,
algorithms with exponential or better O-notations
are actually linear with a large constant."
--Mike Lee


这篇关于第一个程序,指向结构和realloc ....的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆