C语言CSV列搜索程序报错求助:非类类型成员访问错误
C语言CSV文件按列搜索问题修复
问题概述
需要开发一个C语言程序读取CSV文件,接受列名和关键词两个输入,在指定列中查找包含关键词的行并输出整行。当前程序在第75行报错:
'request for member 'Location1' in 'aol', which is of non-class type 'data [4000]''
错误原因分析
- 数组访问错误:
aol是struct data类型的数组,不能直接通过aol.Location1访问成员,必须通过数组下标(如aol[i].Location1)定位到单个结构体元素后再访问成员。 - 字符串比较错误:C语言中字符串不能用
==直接比较,必须使用strcmp函数判断是否相等。 - 循环逻辑错误:
for循环中i+8不会改变循环变量i的值,会导致死循环;同时硬编码3940不符合动态数据量的需求,应使用全局变量printedlines。 - 搜索逻辑偏差:原代码混淆了列名(
column)和关键词(choice)的判断逻辑,应该根据用户输入的column指定搜索列,再用choice匹配关键词。
代码修正要点
- 替换字符串比较方式:用
strcmp(column, "列名") == 0判断用户选择的列 - 修正数组访问方式:通过
aol[i].成员名访问数组中结构体的成员 - 修复循环逻辑:将
i+8改为i++,用printedlines作为循环上限 - 实现按列搜索:针对不同列,调用
strstr检查对应字段是否包含关键词,匹配则输出整行
修正后的完整代码
#include<stdio.h> #include<string.h> #include<stdlib.h> struct data{ char Location1[100]; char Location2[100]; char price[10]; char rooms[10]; char bathrooms[10]; char carparks[10]; char type[100]; char furnish[100]; }; struct data aol[4000]; int printedlines; // 读取CSV文件内容 void fileread() { FILE *fp = fopen("AOLDATA.csv","r"); if(fp == NULL){ printf("Error! File not found."); exit(0); } // 跳过表头行 char header[500]; fgets(header, sizeof(header), fp); while(fscanf(fp, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", aol[printedlines].Location1, aol[printedlines].Location2, aol[printedlines].price, aol[printedlines].rooms, aol[printedlines].bathrooms, aol[printedlines].carparks, aol[printedlines].type, aol[printedlines].furnish) != EOF) { printedlines++; } fclose(fp); } // 按指定列搜索关键词 void searchByColumn(char *column, char *keyword) { int found = 0; for(int i = 0; i < printedlines; i++) { int match = 0; // 根据选择的列判断是否匹配关键词 if(strcmp(column, "Location1") == 0) { match = strstr(aol[i].Location1, keyword) != NULL; } else if(strcmp(column, "Location2") == 0) { match = strstr(aol[i].Location2, keyword) != NULL; } else if(strcmp(column, "price") == 0) { match = strstr(aol[i].price, keyword) != NULL; } else if(strcmp(column, "rooms") == 0) { match = strstr(aol[i].rooms, keyword) != NULL; } else if(strcmp(column, "bathrooms") == 0) { match = strstr(aol[i].bathrooms, keyword) != NULL; } else if(strcmp(column, "carparks") == 0) { match = strstr(aol[i].carparks, keyword) != NULL; } else if(strcmp(column, "type") == 0) { match = strstr(aol[i].type, keyword) != NULL; } else if(strcmp(column, "furnish") == 0) { match = strstr(aol[i].furnish, keyword) != NULL; } else { printf("Invalid column name!\n"); return; } if(match) { printf("%-20s%-20s%-20s%-20s%-20s%-20s%-20s%-20s\n", aol[i].Location1, aol[i].Location2, aol[i].price, aol[i].rooms, aol[i].bathrooms, aol[i].carparks, aol[i].type, aol[i].furnish); found++; } } if(!found) { printf("Data not found!\n"); } } int main(){ int option; fileread(); printf("What do you want to do?\n1.Display data\n2.Search Data\n3.Sort Data\n4.Export Data\n5.Exit\n"); printf("Your choice: "); scanf("%d", &option); getchar(); // 清除输入缓冲区的换行符 if(option == 1){ int howmanylines; printf("Number of rows: "); scanf("%d", &howmanylines); // 限制输出行数不超过实际读取的行数 if(howmanylines > printedlines) howmanylines = printedlines; for(int i = 0; i < howmanylines; i++) { printf("%-20s%-20s%-20s%-20s%-20s%-20s%-20s%-20s\n", aol[i].Location1, aol[i].Location2, aol[i].price, aol[i].rooms, aol[i].bathrooms, aol[i].carparks, aol[i].type, aol[i].furnish); } }else if(option == 2){ char column[100]; char keyword[100]; printf("Choose column: "); fgets(column, sizeof(column), stdin); column[strcspn(column, "\n")] = '\0'; // 去掉换行符 printf("What do you want to find? "); fgets(keyword, sizeof(keyword), stdin); keyword[strcspn(keyword, "\n")] = '\0'; searchByColumn(column, keyword); } return 0; }
补充说明
- 新增
searchByColumn函数专门处理按列搜索逻辑,代码更清晰 - 读取CSV时跳过表头行,避免表头被当作数据处理
- 用
fgets替代scanf读取字符串,避免空格截断问题 - 限制输出行数不超过实际读取的行数,防止数组越界
输入文件示例(AOLDATA.csv)
Location1,Location2,price,rooms,bathrooms,carparks,type,furnish NY,US,10,20,30,40,Bad,Expensive LN,UK,20,30,40,50,Good,Expensive JK,IN,20,10,50,20,Good,Cheap
内容的提问来源于stack exchange,提问作者Pluto
相关产品推荐
相关产品推荐

