Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 循环中的结构数组_C_Arrays_Loops_Struct - Fatal编程技术网

C 循环中的结构数组

C 循环中的结构数组,c,arrays,loops,struct,C,Arrays,Loops,Struct,我在学习C语言,我在玩弄结构,但我发现了一些我无法解释的行为,我想知道为什么会发生 这是我的代码: struct my_struct{ char *name; }; int main() { struct my_struct arr[3]; int i = 0; char str[10]; while (i<3) { fgets(str, 10, stdin); arr[i].name = str; printf("Array numb

我在学习C语言,我在玩弄结构,但我发现了一些我无法解释的行为,我想知道为什么会发生

这是我的代码:

struct my_struct{
  char *name;
};

int main()
{

  struct my_struct arr[3];
  int i = 0;
  char str[10];

  while (i<3)
  {
    fgets(str, 10, stdin);
    arr[i].name = str;
    printf("Array number %d: %s", i, arr[i].name); 
    i++;
  }

  printf("1 - %s\n2 - %s\n3 - %s", arr[0].name, arr[1].name, arr[2].name);

  return 0;
}
预期产出:

Array number 0: test1

Array number 1: test2

Array number 2: test3
1 - test1

2 - test2

3 - test3
结果输出:

Array number 0: test1

Array number 1: test2

Array number 2: test3
1 - test3

2 - test3

3 - test3
结果输出:

Array number 0: test1

Array number 1: test2

Array number 2: test3
1 - test3

2 - test3

3 - test3
问题是,只要while循环继续运行,它似乎就可以了;但是,当它退出时,它似乎将数组中结构的每个“name”值设置为最后一个值

如果退出循环后,在最后一个printf()之前,我手动设置数组中最后一个结构的名称,这是唯一更新的结构,但以前的结构的名称仍然设置为在循环中输入的最后一个


我想我错过了一些关于内存管理的东西,比如在再次调用fgets()之前刷新缓冲区之类的东西,但是我想不出发生了什么。有人知道这是怎么回事吗?

这就是你所期望的,这样想,你有
char str[10]
,这是存储字符串的内存。当您使用
arr[i].name=str设置每个数组名时,您将
char*name
指向该内存。下面是for循环的作用:

0. str = [];         arr[0].name = NULL; arr[1].name = NULL; arr[1].name = NULL;
1. str = [string1];  arr[0].name = str;  arr[1].name = NULL; arr[1].name = NULL;
2. str = [string2];  arr[0].name = str;  arr[1].name = str;  arr[1].name = NULL;
3. str = [string3];  arr[0].name = str;  arr[1].name = str;  arr[1].name = str;
因此,在循环结束时,所有
arr.name
指针都指向字符串,您每次都编辑了字符串。如果希望单个
arr
元素存储它们自己的字符串,那么最好这样做:

struct my_struct{
  char name[10]; // Note how each instance of `my_struct` now stores its own string.
};

int main() {
  struct my_struct arr[3];
  int i = 0;

  while (i<3) {
    fgets(arr[i].name, 10, stdin);
    printf("Array number %d: %s", i, arr[i].name); 
    i++;
  }

  printf("1 - %s\n2 - %s\n3 - %s", arr[0].name, arr[1].name, arr[2].name);

  return 0;
}
struct my\u struct{
char name[10];//注意“my_struct”的每个实例现在如何存储自己的字符串。
};
int main(){
struct my_struct arr[3];
int i=0;

虽然(i这是您所期望的,请这样想,您有
char str[10]
,这是存储字符串的内存。当您使用
arr[i].name=str
设置每个数组名时,您将
char*name
指向此内存。下面是for循环的操作:

0. str = [];         arr[0].name = NULL; arr[1].name = NULL; arr[1].name = NULL;
1. str = [string1];  arr[0].name = str;  arr[1].name = NULL; arr[1].name = NULL;
2. str = [string2];  arr[0].name = str;  arr[1].name = str;  arr[1].name = NULL;
3. str = [string3];  arr[0].name = str;  arr[1].name = str;  arr[1].name = str;
因此,在循环结束时,所有的
arr.name
指针都指向字符串,您每次都编辑了字符串。如果您希望单个
arr
元素存储自己的字符串,那么最好这样做:

struct my_struct{
  char name[10]; // Note how each instance of `my_struct` now stores its own string.
};

int main() {
  struct my_struct arr[3];
  int i = 0;

  while (i<3) {
    fgets(arr[i].name, 10, stdin);
    printf("Array number %d: %s", i, arr[i].name); 
    i++;
  }

  printf("1 - %s\n2 - %s\n3 - %s", arr[0].name, arr[1].name, arr[2].name);

  return 0;
}
struct my\u struct{
char name[10];//注意“my_struct”的每个实例现在如何存储自己的字符串。
};
int main(){
struct my_struct arr[3];
int i=0;

while(i您不能像那样复制C字符串
arr[i].name=str

您所做的是将每个
名称
指针设置为相同的地址,由
str
表示。因此,当您调用
printf
时,每个
name
指向相同的字符串,
str
,而
printf
只需打印
str
三次


如果要复制字符串,请使用strcpy。此外,还需要为
name
变量分配内存。

您不能像那样复制C字符串
arr[i]。name=str

您所做的是将每个
名称
指针设置为相同的地址,由
str
表示。因此,当您调用
printf
时,每个
name
指向相同的字符串,
str
,而
printf
只需打印
str
三次


如果要复制字符串,请使用strcpy。此外,还需要为
名称
变量分配内存。

必须为每个结构的char*名称分配内存:

while (i<3)
  {
    fgets(str, 10, stdin);
    arr[i].name=(char *)malloc(10*sizeof(char));
    strcpy(arr[i].name,str);

    printf("Array number %d: %s", i, arr[i].name); 
    i++;
  }

while(i您必须为每个结构的char*名称分配内存:

while (i<3)
  {
    fgets(str, 10, stdin);
    arr[i].name=(char *)malloc(10*sizeof(char));
    strcpy(arr[i].name,str);

    printf("Array number %d: %s", i, arr[i].name); 
    i++;
  }

while(i因为这是C,所以您需要自己管理所有的内存构造/销毁/管理

如果您只是在学习C,那么现在最好还是坚持使用字符数组,而不是直接使用指针,除非您知道自己在做什么,或者至少事先不做一点研究/学习

数组不同于指针,有一篇文章详细介绍了它们之间的区别

针对您的问题,您可以通过向代码添加多一点输出来更清楚地了解发生了什么。使用
%p
格式说明符,您可以打印出变量的指针位置

有几种方法可以调试C程序来解决这个问题,比如在Linux上使用
gdb
,或者在Windows上使用Visual Studio,但这是在这里显示的最简单的方法

将一些调试输出添加到程序中,可以得到以下结果:

#include<stdio.h>

struct my_struct{
  char *name;
};

int main()
{

  struct my_struct arr[3];
  int i = 0;
  char str[10];

  while (i<3)
  {
    fgets(str, 10, stdin);
    arr[i].name = str;
    printf("Array number %d: %s", i, arr[i].name); 
    printf("  %p\n", arr[i].name);
    i++;
  }

  printf("\n1 - %s (%p)\n2 - %s (%p)\n3 - %s (%p)", 
    arr[0].name, arr[0].name, 
    arr[1].name, arr[1].name,
    arr[2].name, arr[2].name);

  return 0;
}
从这一点上,我们可以看出,您每次都在明显地覆盖相同的内存地址。这是因为
name
被分配给
str
,更迂腐的是,
name
被设置为
char*
str
在内存中存在的位置,这可能不会改变。这与在循环中执行三次
x=3
基本相同

要解决这个问题,您需要做两件事

  • 分配每个
    arr[i]。在使用前命名
    实例。这可以通过
    stdlib.h
    中的
    malloc
    calloc
    实现
  • 将从
    stdin
    检索到的输入复制到
    arr[i].name
    中。这可以使用
    strcpy
    strncpy
    string.h
  • 应用修复程序(两行代码)后,循环将如下所示:

    while (i<3)
    {
      fgets(str, 10, stdin);
    
      // Allocate 10 (most likely) bytes of memory to arr[i].name
      // And also clear out that memory space      
      arr[i].name = (char*)calloc(10, sizeof(char));
    
      // Safely copy the data (max 10 chars) from 'str' into 'arr[i].name'
      strncpy(arr[i].name, str, 10);
    
      printf("Array number %d: %s", i, arr[i].name); 
      printf("  %p\n", arr[i].name);
    
      i++;
    }
    

    因为这是C,所以您需要自己管理所有的内存构造/销毁/管理

    如果您只是在学习C,那么现在最好还是坚持使用字符数组,而不是直接使用指针,除非您知道自己在做什么,或者至少事先不做一点研究/学习

    数组不同于指针,有一篇文章详细介绍了它们之间的区别

    针对您的问题,您可以通过向中添加多一点输出来更清楚地了解发生了什么