【问题标题】:Sorting string containing numbers entered from a file in C?排序包含从C文件中输入的数字的字符串?
【发布时间】:2018-05-01 16:01:08
【问题描述】:

所以我正在开发一个程序,该程序从包含每个行/项目的“项目编号”、“单价”和“购买日期”的文件中读取行。我已经可以扫描文件并以所需的图表格式组织它,但我不知道如何按“项目编号”对数据进行排序。

这是我的代码:

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

int main() {

FILE *fp;

char ch;

fp = fopen("f.txt", "r"); //open the file named f.txt
if (fp == NULL) //In case we can't find the file, notify the user
    printf("File not found\n");

printf("Item \t\tUnit Price\tPurchase Date\n"); //set up the header

while ((ch = fgetc(fp)) != EOF) { //set the character equal to the character next in the file using fgetc, and
                                //if its not equal to the end of file
    if (ch == ',') {
        printf("\t\t"); //add two tabs every time a ',' is encountered.
    }
    else {
        printf("%c",ch); //just display the output from the file
    }
}

fclose(fp); //closes the file

return 0;
}

示例输入

样本输出

看,我需要按项目编号(最左列)对输出进行排序。 我的想法是将每一行添加到一个字符串数组(c 中的 char 数组),然后从那里我不知道如何识别项目编号,以便对输出进行排序。我对 fscanf 有点熟悉,但不知道如何在这里应用它。 非常感谢任何帮助,谢谢。

【问题讨论】:

  • 您发布的所有这些代码都没有尝试解决您所描述的问题。
  • 定义一个struct 数组,每个数组都包含三个适当类型的数据项。从使用fgets 读取的每一行文件中提取数据。然后将qsort与自定义比较函数一起使用。
  • 欢迎来到 Stack Overflow。请尽快阅读 AboutHow to Ask 页面,但更重要的是,请阅读有关如何创建 MCVE (minimal reproducible example) 的信息。要对数据进行排序,您需要存储它。这意味着您将需要多个存储字符。您遇到了问题,因为fgetc() 返回的是int,而不是char,因此您要么根本检测不到 EOF,要么在有人输入有效字符(可能是“ÿ”)时错误检测到 EOF。显示的代码并没有真正尝试解决所描述的问题;它读取一个文件并回显双标签代替逗号 - 并添加一个标题。
  • 将数据存储在数组中,然后调用qsort对其进行排序。

标签: c sorting io


【解决方案1】:

好的,我相信把它分解成几个步骤会很好。

  1. 为您的数据定义一个特定的结构
  2. 逐行读取文件
  3. 对于每一行,使用strtok()分割字符串
  4. 将这些值添加到结构数组中
  5. 使用qsort() 对结构数组进行排序

如果您不熟悉 strtok() 和 qsort() 函数,我强烈建议您阅读有关它们的更多信息。

代码如下:

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

// STEP 1
typedef struct
{
    int item;
    float price;
    char date[50];
} Data;

int compare (const void * a, const void * b)
{

  Data *dataA = (Data *)a;
  Data *dataB = (Data *)b;

  return ( dataA->item - dataB->item );  // Ascending order
//return ( dataB->item - dataA->item );  // Descending order
}

int main()
{
  FILE * fp;
  char line[150];
  Data data[3];
  int i = 0;

  fp = fopen("f.txt", "r");
  while (1)
  {
    // STEP 2
    if (fgets(line,150, fp) == NULL) break;

    // STEP 3-4
    char * pch;
    pch = strtok (line,",");
    data[i].item = atoi(pch);  // item part
    pch = strtok (NULL, ",");
    data[i].price = atof(pch); // unit price part
    pch = strtok (NULL, ",");
    strcpy(data[i].date, pch); // purchase date part

    i++;
  }

  printf("##### BEFORE #####\n");
  printf("Item \t\tUnit Price\tPurchase Date\n"); //set up the header
  for (int k = 0; k < 3; k++)
  {
    printf("%d\t\t%f\t%s", data[k].item, data[k].price, data[k].date);
  }

  // STEP 5
  qsort (data, 3, sizeof(Data), compare);

  printf("\n##### AFTER #####\n");
  printf("Item \t\tUnit Price\tPurchase Date\n"); //set up the header
  for (int k = 0; k < 3; k++)
  {
    printf("%d\t\t%f\t%s", data[k].item, data[k].price, data[k].date);
  }

  fclose(fp);
  return 0;
}

请注意,此代码仅为您的测试用例编写。如果您的数据结构不同(如果您有超过三列等),您需要修改代码。此外,您还需要进行更多的错误处理。

这是输出:

##### BEFORE #####
Item        Unit Price  Purchase Date
583         13.500000   10/24/2005
3912        599.989990  7/27/2008
12          19.990000   3/16/2001

##### AFTER #####
Item        Unit Price  Purchase Date
12          19.990000   3/16/2001
583         13.500000   10/24/2005
3912        599.989990  7/27/2008

希望这会有所帮助。

巴里斯

【讨论】:

  • 谢谢!!好的,我将阅读一些关于 qsort() 和 strtok() 的综合课程,以便我可以完全理解将来如何实现它。感谢您的帮助。
  • 没问题。我很高兴能提供帮助。
  • Yukut 还有一件事:我读了很多关于 strtok 和 struct 用法的文章,我想知道为什么我不能只设置 data[i].date = pch (而不是使用 strcpy 来复制字符串由 pch 持有)到 data[i].date 中的字符串。谢谢
  • @dave99collins 因为数组名不是可修改的左值。试试吧,你应该得到一个错误。请注意,“日期”也是一个数组(查看结构中的声明)。因此,date = pch 是不可能的。
  • 再次感谢,有道理。
猜你喜欢
  • 2013-11-03
  • 1970-01-01
  • 2013-03-29
  • 2010-11-23
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多