从文件中获取信息时遇到问题.txt并将其放入 C 语言中的.csv文件中



这是一个学校项目,我遇到了很多困难。我在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 tn",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
                                  /*  ^ this character is newline.

由于您的YearMonthDay int,您必须使用%d说明符

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

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

fprintf(FPC, "%d t %d t %d t %f tn", 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 tn", &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.

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

"%dt%dt%dt%fn"

您不需要额外的空格和最后一个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,%fn", 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值,但printf()使用%f来打印两者(因为float值在函数调用期间转换为double(。

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

如果是我,我会使用fgets()一次读取一行,然后扫描用sscanf()读取的行。 这使我能够更轻松地检测格式不正确的数据。

奇怪的是,你正在处理的年份只有128天;我遇到的大多数年份都有365或366天(这个问题现在已经解决了!(。

不要测试 EOF fscanf();测试"给了我正确的值数"。

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, "%dt%dt%dt%.2fn", TempData[i].Year, TempData[i].Month,
            TempData[i].Day, TempData[i].Mean);

这将生成制表符分隔的数据(TSV 文件(,但通常将此类文件称为 CSV 文件,即使 C 明显不准确。 (DSV 表示"分隔符分隔值"是此类文件的准确但罕见的术语。 输出文件是带有制表符分隔符的 DSV,而不是带有逗号分隔符的 DSV。

最新更新