如何在C中按字母顺序排列.csv文件的第一列?

iyzzxitl  于 2023-01-18  发布在  其他
关注(0)|答案(2)|浏览(121)

我有一个.csv文件,假设数据如下:

Location 1,Location 2,Price,Rooms,Bathrooms,CarParks,Type,Area,Furnish
Upper-East-Side,New-York,310000,3,2,0,Built-up,1000,Partly
West-Village,New-York,278000,2,2,0,Built-up,1000,Partly
Theater-District,New-York,688000,3,2,0,Built-up,1000,Partly

预期输出(按字母顺序):

Theater-District
Upper-East-Side
West-Village

如何只显示文件的第一列(位置1)并按字母顺序排列,同时跳过文件头?
这是目前我的代码,但它仍然是一个“读取和显示”的形式。

#include <stdio.h>

int main()
{
  FILE *fh;
  
  fh = fopen("file.csv", "r");
  
  if (fh != NULL)
  {
    int line_number = 0;
    char c;
    while ( (c = fgetc(fh)) != EOF )
    {
        if(line_number > 0 || c == '\n'){
            putchar(c);
        }
        if(c == '\n'){
            line_number++;
        }
    }
    fclose(fh);
  
  } else printf("Error opening file.\n");
  
  return 0;
}
lqfhib0f

lqfhib0f1#

csv不是一个定义良好的格式,所以我建议您使用现有的csv库,而不是自己解析数据。例如,如果第一个字段有任何嵌入的逗号,这将不起作用。它依赖scanf()来分配行,并根据需要调整lines数组的大小。这意味着没有任何限制。

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

int strcmp2(const void *a, const void *b) {
    return strcmp((const char *) a, (const char *) b);
}

int main() {
    FILE *f = fopen("unsorted.csv", "r");
    if(!f) return 1;

    char **lines = NULL;
    size_t n = 0;
    for(;; n++) {
        char *location1;
        int rv = fscanf(f, "%m[^,]%*[^\n]\n", &location1);
        if(rv != 1) break;
        char **tmp = realloc(lines, (n + 1) * sizeof *tmp);
        if(!tmp) return 1;
        lines = tmp;
        tmp[n] = location1;
    }
    fclose(f);

    free(lines[0]); // header
    qsort(&lines[1], n - 1, sizeof *lines, strcmp2);
    for(size_t i = 1; i < n; i++) {
        printf("%s\n", lines[i]);
        free(lines[i]);
    }
    free(lines);
}

它将生成预期输出:

Theater-District
Upper-East-Side
West-Village
u5i3ibmn

u5i3ibmn2#

因此,假设对行长度和CSV文件记录计数有一些硬性限制,我们可以只使用数组。
要读取一条记录,只需使用fgets()。使用常用方法将每行文本添加到数组中。
我们使用一个简单的字符串搜索和截断来分离第一个字段(假设没有像双引号字段这样的花哨内容,我假设您正在做功课)。
要对 * 除了 * CSV头记录之外的所有内容进行排序,请使用qsort()并进行一些额外的计算。

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

#define unused(x) (void)(x)

#define MAX_LINE_LENGTH 100
#define MAX_RECORD_COUNT 100

int main( int argc, char ** argv )
{
  unused( argc );

  char records[MAX_RECORD_COUNT][MAX_LINE_LENGTH];
  size_t record_count = 0;
  
  const char * filename = argv[1];
  if (!filename) return 1;

  // Read our records from file
  FILE * f = fopen( filename, "r" );
  if (!f) return 1;

  while ((record_count < MAX_RECORD_COUNT)
      and fgets( records[record_count], MAX_LINE_LENGTH, f ))
    record_count += 1;

  fclose( f );
  
  // Truncate the strings to just the first field
  for (size_t n = 0;  n < record_count;  n++)
  {
    char * p = strchr( records[n], ',' );
    if (p) *p = '\0';
  }
  
  // Sort everything but the header
  if (record_count > 2)  // must exist at least two records + header
    qsort( records+1, record_count-1, MAX_LINE_LENGTH, 
      (int (*)( const void *, const void * ))strcmp );
  
  // Print everything but the header
  for (size_t n = 1;  n < record_count;  n++)
    printf( "%s\n", records[n] );
  
  return 0;
}

相关问题