【问题标题】:Array of Strings only storing the LAST item in C字符串数组仅存储 C 中的最后一项
【发布时间】:2021-06-03 11:08:48
【问题描述】:

我正在尝试编写一个程序,在该程序中我从文件中读取信息,并将其按用户选择的不同列进行排序。我现在不关心排序,我似乎无法正确存储数据,当我尝试将文件读入这个数组时,我只是从文件中获取最后一组项目。问题是我需要按特定顺序排列信息,以便稍后对它们进行排序。在我的实际代码中,我将使用 146 行和 4 列,并对不同的列进行排序。

我不能为此项目使用动态内存分配。

这是我正在尝试做的一个简单示例,但这不是我的实际代码:

#include <stdio.h>

int main() {
  char *array[2][3]; // Array to store the stuff, like a dataframe??
  int i;
  char name[10]; // Over-writable array to store name
  char age[3]; //Over-writable array to store age
  char occupation[12]; // Over writable for occupation



  for(i=0; i < 2; i++)
  {
    scanf("%s %s %s", name, age, occupation); // Get name, age, and occupation as input from file
    array[i][0] = name; // assign name to row position i, and column position 0
    array[i][1] = age; // assign age to row position i, and column position 1
    array[i][2] = occupation; // assign age to row position i, and column 2
    // i becomes one after this to move to row 1, column assignments
    // should stay the same
  }

  printf("%-20s %-20s %-20s\n", "Name", "Age", "Occupation"); //Print column headers

  for(i = 0; i < 2; i++)
  {
    printf("%-20s %-20s %-20s\n", array[i][0], array[i][1], array[i][2]); //Print corresponding info
  }
  return 0;
}

假设我运行它,然后手动输入:

Steve 50 Retired
Alex 23 Server

我的输出如下所示:

Name                 Age                  Occupation
Alex                 23                   Server
Alex                 23                   Server

我需要将信息存储在临时数组中的原因是因为在某些情况下,我只需要某些信息,而可以省略其他信息。例如 - 我可能需要生成一个按姓名排序的文本文件,包括职业,但不包括年龄,在这种情况下,我只需要一个姓名和年龄数组。

无论我做什么,我都只会得到任何给定数据列表的最后一个元素。这可能是一个 200 行和 4 列的数组,我只会从我正在读取的任何文件中获取最后一个条目,并且它们都将仅使用给出的最后一条信息以正确的格式打印。

如果您有任何想法,请告诉我。

我对 C 中的数组的了解可能会让我失望,我很难掌握指针与数组的关系,但我找不到可以帮助我解决这个问题的大型 2D 示例。

【问题讨论】:

  • 在分配字符串时使用 strdup()
  • 在每次循环迭代中,您都在重用相同的内存缓冲区。更改(例如):array[i][0] = name;array[i][0] = strdup(name);。其他领域也是如此。对于更高级的用法 [使用struct 与 2D 数组],请参阅我最近的回答:stackoverflow.com/questions/66464177/…
  • @tstanisl 老兄,就是这样!如果你有任何解释为什么会这样,请告诉我。它现在完美运行。上帝啊,寻找这个答案已经 3 天了。
  • 你的输入是什么样的,输出应该是什么样的?如果您需要对数据进行排序,如果您可以将所有数据读入内存可能会容易得多,但这需要动态分配。尽管我想您可以将文件mmap() 存储到内存中并对其进行就地排序。 (另外,strdup()也是动态分配。)
  • @bannedfromquestioning 要了解发生了什么,您应该阅读指针和动态内存分配。

标签: arrays c string sorting multidimensional-array


【解决方案1】:

虽然strdup 肯定是一个选项,但它使用动态内存分配(不要忘记释放它),你说你不能使用。

这里的建议是创建您自己的类型,以有组织的方式存储您收集的所有信息,为此您可以使用struct

这使排序过程更容易,因为您可以轻松地使用 qsort 和自定义比较器函数以您需要的任何方式对数组进行排序,而不会遇到太多麻烦。

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

typedef struct
{
    char name[10];       
    char age[3];         
    char occupation[12]; 
}Info;

// comparator function example, sorts by alphabetical order of name
int compare(const void* a, const void* b)
{
    return strcmp(((Info*)a)->name, ((Info*)b)->name);
}
int main()
{
    Info array[3];
    Info temp; // temporary variable you said you need

    for (int i = 0; i < 3; i++)
    {
        // parse into temporary variable
        if(scanf("%9s %2s %11s", temp.name, temp.age, temp.occupation) == 3)
        {
            // if all goes well assign it to the data container
            array[i] = temp;
        }
    }

    qsort(array, 3, sizeof *array, compare); // sorting the array

    printf("%-20s %-20s %-20s\n", "Name", "Age", "Occupation"); //Print column headers

    for (int i = 0; i < 3; i++)
    {
        printf("%-20s %-20s %-20s\n", array[i].name, array[i].age, array[i].occupation); 
    }
}

请注意,我还为您的 scanf 添加了宽度限制以避免缓冲区溢出,我还在检查它的返回值,这些都是为了更健壮的代码应该做的事情。

在我看来,更好的选择是使用 fgets 读取输入/文件并使用 sscanf 解析值。

上面的代码将产生一个输入:

richard 23 engineer
albert 45 driver
charles 24 lawyer

输出:

Name                 Age                  Occupation
albert               45                   driver
charles              24                   lawyer
richard              23                   engineer

按名称按字母顺序对数组进行排序。

【讨论】:

    【解决方案2】:

    您没有为从 scanf 获得的这些 char* 分配任何内存, 您可以直接使用 mmalloc 和 strcpy,或者您也可以使用 strdup 同时执行这两个操作。

    由于您基本上每次都从 name/age/occupation 复制指针,因此您最终会得到相同的值,因为它们包含最后一次 scanf 调用结果。

    简单的案例或你在做什么:

    char* strarray[2];
    char* str ="hello";
    strarray[0]=str;  
    strarray[1]=str;  
    

    两个数组元素都包含相同的指针 所以现在如果我改变 str :

    str ="Not Hello";
    

    两个数组元素仍将指向同一个指针,因此将包含相同的字符串“Not Hello”。

    【讨论】:

    • 你说的没有错,但你可能应该详细说明一下,并考虑如何格式化答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 2015-01-12
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多