我是编程新手,我在C项目中需要帮助。我必须搜索一个城市,确认它存在于第一个文件(city.csv)中,并从那里获取其ID。然后我必须将该id与第二个文件(meteo.csv)中的相应ID匹配,然后编辑其天气信息,即第二个文件中的天气信息。但是,我不知道如何从第一个文件中获取城市ID,然后在获取所有新的天气信息后如何编辑第二个文件。这是代码:
void addInfo() {
FILE * fp;
char id_city[100];
char city[100];
char humidity[100];
char temp_max[100];
char temp_min[100];
char pressure[100];
char date[100];
printf("Name of the city: ");
scanf("%s", city);
// I think it's here that I have to write the code for take the city's id from the first file
if (id_city != NULL) {
printf("Maximun temperature: ");
scanf("%s", temp_max);
printf("Minimun temperature: ");
scanf("%s", temp_min);
printf("Humidity: ");
scanf("%s", humidity);
printf("Pressure: ");
scanf("%s", pressure);
printf("Date, in the format YYYY-MM-DD: ");
scanf("%s", date);
fp = fopen ("meteo.csv", "a");
fprintf(fp, "%s, %s, %s, %s, %s \n", temp_max, temp_min, humidity, pressure, date); //I think there's something wrong here too...
fclose(fp);
printf("Information edited successfully");
}
文件city.csv有152行和4列:
(id_city,city,county,district)
,例如
(56,Lisbon,Lisbon,Lisbon)
文件meteo.csv有152行和7列:
(id_meteo_city,id_city,temp_max,temp_min,humidity,pressure,date)
,例如
(56,56,14,5,62,1025,2018-02-12)
答案 0 :(得分:0)
我要做的第一件事就是将数据封装在一个struct
中
更容易将CSV文件的一行映射到表示一行的对象中。
如果文件city.csv
和meteo.csv
都有不同的列,我会创建一个
每个文件不同struct
。如果两个文件具有相同的列,则可以
使用struct
。我假设两个文件都不同,city
有
格式meteo_id,city_id,name
。
typedef struct city_t {
int meteo_id;
int city_id;
char name[100]; // no city should have
// longer than 100 chars
} city_t;
typedef struct meteo_t {
int meteo_id;
int city_id;
int tempt_max;
int tempt_mix;
double humidity;
double preassure;
char date[11];
} meteo_t;
我们假设这两个文件都格式正确,否则你必须这样做 编写检查错误并处理错误的代码,这将是下一步 在练习中,所以我将只编写带有基本错误的基本版本 识别。
#include <stdio.h>
#include <string.h>
#include <errno.h>
// takes 2 params, the filename and a pointer
// to size_t where the number of cities is stored
city_t *read_cities(const char *filename, size_t *len)
{
if(filename == NULL || len == NULL)
return NULL;
FILE *fp = fopen(filename, "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
return NULL;
}
city_t *arr = NULL, *tmp;
*len = 0;
// assuming that no line will be longer than 1023 chars long
char line[1024];
while(fgets(line, sizeof line, fp))
{
tmp = realloc(arr, (*len + 1) * sizeof *arr);
if(tmp == NULL)
{
fprintf(stderr, "could not parse the whole file %s\n", filename);
// returning all parsed cities so far
if(*len == 0)
{
free(arr);
arr = NULL;
}
return arr;
}
arr = tmp;
// %99[^\n] is to read up to 99 characters until the end of the line
if(sscanf(line, "%d,%d,%99[^\n]", &(arr[*len].meteo_id),
&(arr[*len].city_id), arr[*len].name) != 3)
{
fprintf(stderr, "Invalid line format (skipping line):\n%s\n", line);
// skip this line, and decrement *len
(*len)--;
continue;
}
// incrementing only when parsing of line was OK
(*len)++;
}
fclose(fp);
// file is empty or
// all lines have wrong format
if(*len == 0)
{
free(arr);
arr = NULL;
}
return arr;
}
void print_cities(city_t *cities, size_t len, FILE *fp)
{
if(cities == NULL || fp == NULL)
return;
for(size_t i = 0; i < len; ++i)
fprintf(fp, "%d,%d,%s\n", cities[i].meteo_id, cities[i].citiy_id,
cities[i].name);
}
现在我已经为文件citiy.csv
编写了读写函数
格式meteo_id;city_id;name
。 print_cities
允许您打印CSV
屏幕上的内容(将stdout
作为最后一个参数传递)或文件
(传递FILE
对象作为最后一个参数。)
您可以将这些功能用作读写meteo.csv
的模板
想法是一样的。
您可以按如下方式使用这些功能:
int main(void)
{
size_t cities_len;
city_t *cities = read_cities("city.csv", &cities_len);
// error
if(cities == NULL)
return 1;
do_something_with_cities(cities, cities_len);
// update csv
FILE *fp = fopen("city.csv", "w");
if(fp == NULL)
{
fprintf(stderr, "Could not open city.csv for reading: %s\n",
strerror(errno));
free(cities);
return 1;
}
print_cities(cities, cities_len, fp);
fclose(fp);
free(cities);
return 0;
}
现在练习:编写一个解析meteo.csv
的类似函数(使用
我作为模板的功能应该不那么困难)并解析这两个文件。现在
你已经将它们存储在内存中,操作数据很容易(插入,
更新,删除)。然后像我在示例中所做的那样编写文件,就是这样。
最后一个提示:如何搜索城市:
// returns the index in the array or -1 on error or when not found
int search_for_city_by_name(city_t *cities, size_t len, const char *name)
{
if(cities == NULL || name == NULL)
return -1;
for(size_t i = 0; i < len; ++i)
if(strcmp(name, cities[i].name) == 0)
return i;
// not found
return -1;
}
现在我已经给了你几乎所有的任务部分,你所要做的就是
将它们粘在一起并为meteo.csv
文件编写相同的函数。