我正在编写一个程序,该程序使用命令行参数从用户接收文本文件的名称。文本文件是一个非常简单的 CSV 文件,例如:
Bob's experiment,12,14,15,16
Mary's experiment,16,15,18
我只是希望它打印实验名称,然后打印所有数值的平均值。我试图通过将所有数字和逗号放入一个字符数组中来做到这一点,但我不知道哪里出了问题。
这就是我所拥有的:
int main(int argc, char *argv[])
{
if(argc == 2) {
FILE *txt_file;
txt_file=fopen(argv[1], "rt");
char str[4096];
if(!txt_file) {
printf("File does not exist.\n");
return 1;
}
while(!feof(txt_file)){
char s;
s = fgetc(txt_file);
//prints experiment name
if(s != ',' && (!isdigit(s))) {
printf("%c", s);
}
if(isdigit(s) || s == ',') {
fgets(str, 4096, txt_file);
}
}
fclose(txt_file);
return 0;
}
最佳答案
有多种方法可以做到这一点,但您应该根据从文件中读取的数据类型来定制输入例程。这里您正在读取行数据,因此您应该关注面向行输入例程(fgets
、getline
,或硬塞的 scanf
)。基本方法是将文件中的一行输入读取到缓冲区中,然后根据需要解析该行。您可以动态分配所需的所有存储空间,也可以定义一个足以处理数据的最大值。
接下来,您需要解析从文件中读取的缓冲区
,以获取实验名称
以及关联的每个值
,以便可以计算平均值
。同样,有很多方法可以做到这一点,但 strtol
是为此目的量身定制的。它需要一个指向要转换的字符串的指针
,并返回一个指向下一个非数字字符的endptr
。这允许您读取值并设置pointer = endptr+1
,这将设置您读取下一个数字。
我在下面的示例中将这些部分组合在一起。对其进行评论是为了帮助您跟进。如果您还有任何其他问题,请发表评论:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXEXPS 256
int main (int argc, char* argv[])
{
if (argc < 2) {
fprintf (stderr, "error: insufficient input. Usage %s <filename>\n", argv[0]);
return 1;
}
char *line = NULL; /* line read from file (getline allocates if NULL) */
size_t n = 0; /* number of characters to read (0 - no limit) */
ssize_t nchr = 0; /* number of characters actually read by getline */
char *p = NULL; /* pointer to use parsing values from line */
char *lnp = NULL; /* second pointer to use parsing values from line */
char *expname[MAXEXPS] = {0}; /* array of MAXEXPS pointers for experiment names */
int expavg[MAXEXPS] = {0}; /* array of MAXEXPS ints to hold averages */
int val = 0; /* val returned by each call to strtol */
int eidx = 0; /* experiment index */
int idx = 0; /* value index */
FILE *txt_file = fopen(argv[1], "r");
if (!txt_file) {
fprintf (stderr, "error: unable to open file '%s'\n", argv[1]);
return 1;
}
while ((nchr = getline (&line, &n, txt_file)) != -1) /* read each line in file */
{
p = strchr (line, ','); /* find first ',' */
*p = 0; /* set it to null (zero) */
expname[eidx] = strdup (line); /* copy exp name to array (strdup allocates) */
lnp = ++p; /* set lnp to next char */
int sum = 0; /* reset sum to 0 */
idx = 0; /* reset idx to 0 */
while ((val = (int)strtol (lnp, &p, 10)) != 0 && lnp != p) /* read next number */
{
sum += val; /* add val to sum */
lnp = ++p; /* set lnp to next char */
idx++; /* inc idx */
}
expavg[eidx++] = (idx > 0) ? sum / idx : 0; /* calc avg for experiment */
}
fclose (txt_file);
/* print the averages of experiments */
n = 0;
printf ("\n Experiment Avg\n");
printf (" -----------------------\n");
while (expname[n])
{
printf (" %-18s %d\n", expname[n], expavg[n]);
n++;
}
printf ("\n");
/* free all allocated memory */
n = 0;
if (line)
free (line);
while (expname[n])
free (expname[n++]);
return 0;
}
输出:
$ ./bin/csvavgfixed dat/csvavg.dat
Experiment Avg
-----------------------
Bob's experiment 14
Mary's experiment 16
内存分配/空闲摘要:
==22148== HEAP SUMMARY:
==22148== in use at exit: 0 bytes in 0 blocks
==22148== total heap usage: 4 allocs, 4 frees, 723 bytes allocated
==22148==
==22148== All heap blocks were freed -- no leaks are possible
==22148==
==22148== For counts of detected and suppressed errors, rerun with: -v
==22148== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
关于c - 在c中将文本文件读入字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26897673/