繁体   English   中英

在从.txt文件中获取信息并将其放入C中的.csv文件时遇到麻烦

[英]Having Trouble Taking information From .txt File and putting it in a .csv file in C

这是针对学校项目的,我遇到了很多困难。 我正在Visual Studio 2012中工作。我对C还是很陌生,所以请提前抱歉。

项目概况

从文本文件(Manhattan_temp_data.txt)中获取数据并将其写入.csv文件(TemperatureData.csv)。 最终目标是要有一个电子表格,该电子表格可用于创建曼哈顿1年温度数据的可视表示。

我的文本文件如下所示(精确366行)

Year    Month    Day Mean 
1896    5   1    61.5
1896    5   2    63
1896    5   3    64.5 
1896    5   4    -99   <The -99 means no collected data> 

我的.csv文件如下所示

Year \t Month \t Day \t Mean \t Interpolated Mean

这是我的代码

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

//Structure for my Text file read
typedef struct TempTXTData{ 
    int Year; 
    int Month; 
    int Day; 
    double Mean; 
} TempTXTData_t; 

int main ()
{

FILE *FPT; //Represents My Text File 
FILE *FPC; //Represents My .csv File
int i; 
TempTXTData_t TempData[366]; 

//Where I open both my text and .csv files 
FPT= fopen("Manhattan_temp_data.txt", "r"); 
  if( FPT == NULL )
   {
      printf("Load Failure Press any key to exit...\n");
      exit(EXIT_FAILURE);
   }
FPC= fopen("TemperatureData.csv", "w");
 if( FPC == NULL ) 
   {
      fclose(FPT);
      printf("Load Failure Press any key to exit...\n");
      exit(EXIT_FAILURE);
   }
 //Function where I take data from my .txt file and input it into my .csv file
 for(i=1; i<366 && fscanf(FPT, "%f %f %f %f", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) !=4; i++) 
{
    for (i=1; i<366; i++) 
        fprintf(FPC, "%f, %f, %f, %f \n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
 }


//Closing Files 
fclose(FPT); 
fclose(FPC); 

getch(); 
return 0;  
}

问题

当我运行代码时,我得到并打开excel工作表,所有行和列都相同。 前三列全为0,最后一列为-9.3E + 61。

我的猜测是我没有从.txt文件中获取数据,这使我相信我在此行中有错误...

 for(i=0; i<366 && fscanf(FPT, "%f %f %f %f", &TempData[i].Year, &TempData[i].Month,    &TempData[i].Day, &TempData[i].Mean) !=4; i++) 

谢谢你的时间,

亚历克斯

几乎没有什么东西,但是没有解决方案(目前无法测试):

  • C数组的索引从0size - 1 (实际上是使用<运算符完成的),因此循环应从0迭代。 您要么要避免使用注释文本,否则应将起始索引保持为1并存储在TempData[i-1] ,将索引更改为0
  • 没有理由使您的年/月/日数据类型不为int
  • 电子表格在这里是没有干扰的。 首先,您应该查看CSV文件。 可能需要为excel配置一些内容以正确解析数据。
  • 最后,由于这样会导致错误,因此您的输入文件Manhattan_temp_data.txt应该以只读( r )打开。
  • 奖励之一,我知道Windows伙计们必须放置一些C函数以避免关闭终端,但是您至少应该使用更标准的函数,例如getchar() 对您来说并不昂贵,并且也可以在其他操作系统上进行编译。

希望这对您有所帮助,或者至少可以编辑您的帖子以适合实际问题。

您需要这样在格式字符串的末尾添加换行符

fprintf(FPC, "%f \t %f \t %f \t %f \t\n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
                                  /*  ^ this character is newline.

并且由于您的YearMonthDayint ,因此您必须使用%d指定符

fprintf(FPC, "%d \t %d \t %d \t %f \t\n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);

并且您不将字段的地址传递给fprintf ,而是将字段删除&

fprintf(FPC, "%d \t %d \t %d \t %f \t\n", TempData[i].Year, TempData[i].Month, TempData[i].Day, TempData[i].Mean);

还有一个建议,请检查fscanf准确读取要根据情况读取的参数数量,请对此进行更改

fscanf(FPT, "%f \t %f \t %f \t %f \t", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) !=EOF

对此

fscanf(FPT, "%d \t %d \t %d \t %f \t\n", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) != 4

由于fscanf从Linux手册页返回成功匹配的项目数

另外,您的fscanf将在文件的第一行失败,因此不会更新停留在文件开头的流指针,因此您必须阅读整行并使用sscanf否则您将无法跳过第一行,并且继续阅读,相反,您的代码将中止第一行的阅读,最终您将得到一个空文件。

RETURN VALUE
   These  functions  return  the  number  of  input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early
   matching failure.

   The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs.  EOF is also returned if a  read
   error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.

还有一件事,您的格式字符串可能是

"%d\t%d\t%d\t%f\n"

您不需要多余的空格和最后一个\\t字符。

这段代码应该做到

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

//Structure for my Text file read
typedef struct TempTXTData{
    int Year;
    int Month;
    int Day;
    double Mean;
} TempTXTData_t;

int main ()
{
    FILE *FPT; //Represents My Text File
    FILE *FPC; //Represents My .csv File
    int i;
    int done;
    TempTXTData_t TempData[366];

    //Where I open both my text and .csv files
    //FPT= fopen("Manhattan_temp_data.txt", "r");
    FPT = fopen("data.dat", "r");
    if (FPT == NULL)
    {
        printf("Load Failure Press any key to exit...\n");
        exit(EXIT_FAILURE);
    }

    FPC= fopen("TemperatureData.csv", "w");
    if( FPC == NULL )
    {
        fclose(FPT);
        printf("Load Failure Press any key to exit...\n");
        exit(EXIT_FAILURE);
    }

    done = 0;
    for (i = 1 ; (i < 366) && (done == 0) ;  i++)
    {
        char  buffer[1024];
        char *pointer;
        /* using fgets is better as was mentioned in other answers */
        pointer = fgets(buffer, sizeof(buffer), FPT);
        if (pointer != NULL)
        {
            int matched;
            matched = sscanf(pointer, "%d%d%d%lf", &(TempData[i].Year), &(TempData[i].Month), &(TempData[i].Day), &(TempData[i].Mean));
            if (matched == 4)
                fprintf(FPC, "%d,%d,%d,%f\n", TempData[i].Year, TempData[i].Month, TempData[i].Day, TempData[i].Mean);
        }
        else
            done = 1;
    }


    //Closing Files
    fclose(FPT);
    fclose(FPC);

    return 0;
}

您编辑了该问题,有可能破坏先前的答案,这不是一个好办法。

由于您将年,月,日元素更改为int (从double更改),因此必须更改scanf()printf()字符串。 scanf()的陷阱之一是%f用于读取float值, %lf用于读取double float值,但是printf()使用%f来打印两个值(因为在函数调用期间将float值转换为double值)。

您不会跳过文件的标题行; 那是个问题。

是我吗,我会使用fgets()一次读取一行,然后扫描使用sscanf()读取的那一行。 这使我可以更轻松地检测格式错误的数据。

您正在处理的年份只有128天,这似乎很奇怪。 我遇到的大多数计算机都有365或366(问题现已解决!)。

不要测试fscanf()的EOF; 测试“为我提供正确数量的值”。

C中的数组从索引0开始。

您的代码嵌套了输入和输出循环。 由于您为读取的第一行打印了366个结果值,然后为读取的下一行打印了366个结果值,依此类推,因此这是一个灾难性的灾难。 请注意,大多数这些值是未定义的。 它们不必为零或类似的有用内容。 仅在阅读完所有内容后才想打印(尤其是当您要插入缺失值时)。 您不想打印地址。 您确实要打印换行符。

enum { MAX_DAYS_PER_YEAR = 366 };

char line[4096];

/* Skip header line */
if (fgets(line, sizeof(line), FPT) == 0)
{
    fputs("Empty file!\n", stderr);
    exit(1);
}

/* Read up to 366 input lines */
for (i = 0; i < MAX_DAYS_PER_YEAR; i++)
{
    if (fscanf(FPT, "%d %d %d %lf", &TempData[i].Year, &TempData[i].Month,
               &TempData[i].Day, &TempData[i].Mean) != 4)
        break;
}

/* Print only the lines that were read */
for (j = 0; j < i; j++) 
    fprintf(FPC, "%d\t%d\t%d\t%.2f\n", TempData[i].Year, TempData[i].Month,
            TempData[i].Day, TempData[i].Mean);

这会产生制表符分隔的数据(TSV文件),但是即使C明显不准确,也经常将此类文件称为CSV文件。 (“分隔符分隔值”的DSV是此类文件的准确但很少使用的术语。与带有逗号分隔符的DSV相比,输出文件是带有制表符分隔符的DSV。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM