【问题标题】:How to read text in a file into a string variable in c如何将文件中的文本读入c中的字符串变量
【发布时间】:2022-01-24 05:46:26
【问题描述】:

我有一个 csv 文件,其中包含用逗号分隔的数字,每个数字都像 1,2,3,4,5,6,7,8,9....。我打算将所有这些数字解析为我用 c 编程语言初始化的向量,我已经设法使用下面的代码将文件中的所有字符读取到文件末尾,我现在的问题是分配字符使用getc() 函数将其提取到字符串中,以进行基于逗号的进一步处理,在此我将使用逗号作为分隔符变量将字符串拆分为字符串数组。我尝试在每次迭代时将字符分配给字符串,但没有成功,请帮助

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

int main() {
    // define the vector file
    FILE* vec = fopen("vectors.csv", "r");
    // define the dimensions of the vector
    int rows = 100;
    // this vector has 100 rows for instance
    int vec[rows];
    //I managed to read the csv file now I need to read it into a string
    char ch,line;
    while((ch=getc(vec))!=EOF){
    //append the characters to the empty string
    line+=ch;
    }
 //confirm the accuracy of the string by outputting it
   printf("%s",line);
 //the above line outputs blank, please help
    



    return 0;
}

我一直认为向量与一维数组相同,但我的研究可能会让我误入歧途,请帮助。

【问题讨论】:

  • 有理由不使用fscanf()吗?您是否有任何需要担心的空白字段(相邻的逗号)?
  • 不,它们不是空的相邻逗号。每个逗号后面都有一个数字
  • 我如何使用 fscanf 来做到这一点?
  • 所以,用fscanf() 一次读一个数字。 %d后面可以加逗号;你不会知道什么时候不匹配,但也没关系。
  • 我使用循环然后使用fscanf() 分配?它返回一个整数吗?

标签: c csv vector


【解决方案1】:

将 CSV 记录(字符串)转换为数组实际上非常简单。有几种方法可以做到这一点,但使用带有 string→int 函数的strtok() 可能是最简单的。

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

int main()
{
  char s[1000];
  FILE * f = fopen("vectors.csv", "r");
  while (fgets(s, sizeof(s), f))
  {
    int vector[100];
    int size = 0;

    const char * ds = " ,\t\n";  // skip spaces, commas, tabs, and that newline at the end of s[]
    for (char * token = strtok(s, ds);  token;  token = strtok(NULL, ds))
    {
      vector[size++] = atoi(token);
    }

    do_something(vector, size);
  }
  fclose(f);
  return 0;
}

您可能希望添加一些错误处理:

  • fopen() 可能返回 NULL
  • fgets() 可能不会读完整行(因为 s[] 没有足够的空间)
  • 每行的数字可能比向量中的可用空间多[]
  • atoi() 可能会失败,但它不会告诉你是否失败。 strtol() 更擅长错误检查。

还请注意,您的 string→int 函数可以是 string→whatever:例如,您的向量可以由浮点值组成。您只需要一个执行转换的函数。

我把它写成一个循环,假设“vectorS”意味着你的 CSV 中有多个记录,每个向量一个行,并且您希望依次处理所有这些。如果您的文件真的只是一个 single 向量(在单行上),那么只需摆脱循环。

如果您的文件大量到使用三个传递字符串(fgets() 加上 strtok() 加上 atoi() / strtol() / scanf() / 不管)的程度问题,您只需使用scanf() 即可一次性完成。发表评论,我会更新答案。

更新

由于您的文件只包含用逗号分隔的数字作为单个向量,因此您也可以仅使用 scanf() 循环。

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>

int main()
{
  int vector[100];
  int size = 0;

  FILE * f = fopen("vectors.csv", "r");
  while (fscanf_s(f, "%d ,", vector + size) == 1)
  {
    size += 1;
  }
  fclose(f);

  do_something(vector, size);
}

虽然这看起来很方便,但它不能直接处理输入中的换行符。如果您希望扫描多个向量记录,每行一个,您仍然需要将行作为字符串读取,然后解析字符串。你仍然可以使用sscanf() 来做这件事,但乍一看就不太容易理解了。

真正的单遍解析?

更新是一次通过,但如果您需要保留它(因为您正试图处理字面上的数万个值)并且行-逐行,那么在处理“分隔符”时您需要更加狡猾。再次,如果有问题,请发表评论。

向量

在编程语言中,您可以放心地将向量假设为类似于数组的某种列表。该术语的确切含义取决于语言或环境。

例如,向量可以表示为元组、数组、列表等。在 C++ 中,vector 是表示动态数组的库对象。以此类推。

在数学术语中,向量是线性空间的一个组成部分。但同样,它通常表示为标量值的元组。

【讨论】:

  • 为什么每次迭代都在 while 循环中创建一个新向量?您可以编辑以在 te 循环外初始化向量,然后在 while 循环中分配吗?
  • 编译器足够聪明,可以自行优化。将其保留在循环中使 vectorsize 变量的范围保持在循环的本地。更重要的是,向量的size 每次通过循环都需要初始化为零,我们使用这个声明来执行此操作,而不是将其分散到多行代码中。但是,您可以随意排列变量。
  • 好的,我要去第二个答案,因为 csv 文件只包含逗号分隔的整数
  • 是的,请记住,第二个答案太笨了,不能在 single 行输入时停止阅读。因此,如果您想在循环内执行 do_something(),则必须编写一个单独的函数来跳过分隔符并识别换行符。 (不过,听起来您不必担心。)
  • 你在哪里将 csv 中解析的整数分配给向量?
【解决方案2】:

查看fopen的结果,看是否成功。 if(vec == NULL) { /* error handling here */ }.

如果文件中的数字数量有限,使用fgets 将其全部作为单个字符串读取可能是最简单的。或者编写一个循环并重复调用fgetsfscanf。如果您使用fgets 读取输入,则需要使用strtol 将数字转换为整数(fscanf 在内部执行此操作,因此更易于使用)。

您需要检查函数的结果以查看它们是否成功,以防止格式错误以及超出文件末尾的读取。

完成后记得fclose文件句柄。

【讨论】:

  • 如何更改循环以使其将字符分配给字符串,然后我将拆分为字符数组并根据向量中的行数进行解析?
  • @KINYUATIMOTHYNJIRU 如果您将其读取为像"1,2,3,4" 这样的字符串,那么您实际上可以重复调用strtol 以进行解析,方法是使用该函数的endptr 参数来查看在哪里它停止读取每个数字。
  • 您能否就我如何实现这一目标发表一个全面的答案?
  • @KINYUATIMOTHYNJIRU 当然,如果您发布一个包含到目前为止的代码的综合问题,包括文件 I/O。而不仅仅是伪代码。
  • 编辑以解决更改
【解决方案3】:

你会失败,因为你的输入(你所说的字符串不是字符串。在 C 中没有字符串这样的东西,而是一个以 null 结尾的字符数组)。

所以这个(那里的行变量): char ch,line;

不能像这样使用:

line+=ch;

它只会增加“line”变量的char值,并在超过其限制(MAX_CHAR)时一遍又一遍。

您最好首先使用 fgets(),然后根据每行中的字符数 (strlen()) 为您的 char 指针使用 malloc()/realloc()/free() 内存。 所以你的变量应该是: char *line;

另一种解决方案是找出文件中的行数,然后找出其中的最大行长度,然后将变量设置为:

字符线[ + + 1];

【讨论】:

  • 一个字符数组一个字符串。
猜你喜欢
  • 2013-03-28
  • 2021-06-04
  • 1970-01-01
  • 2012-01-12
  • 2012-11-10
  • 2012-08-24
  • 2021-04-16
相关资源
最近更新 更多