从文件中捕获用逗号分隔的带引号的字符串
Capture quoted strings separated with commas from a file
假设我想从这样的文件中获取输入:-
"8313515769001870,GRKLK,03/2023,eatcp,btlzg"
"6144115684794523,ZEATL,10/2033,arnne,drrfd"
我做的一个结构如下
typedef struct{
char Card_Number[20];
char Bank_Code[6];
char Expiry_Date[8];
char First_Name[30];
char Last_Name[30];
}Card;
这是我尝试在阅读模式下从名为 'file' 的文件中读取输入,fgets 中的 str 正在存储正确的字符串,但它没有被吸收 c[i]:
FILE * fptr;
int count=0;
fptr= fopen("file","r");
Card *c = (Card*)calloc(10,sizeof(Card));
printf("StartAlloc\n");
int i=0;
char str[1000];
fgets(str,80,fptr);
if(fptr==NULL)
{return 0;}
do{
sscanf(str,"\"%[^,],%[^,],%[^,],%[^,],%[^,]\" \n",c[i].Card_Number,c[i].Bank_Code,c[i].Expiry_Date,c[i].First_Name,c[i].Last_Name);
i++;
}while(fgets(str,80,fptr)!=NULL);
我不明白为什么正则表达式 %[^,] 没有捕获单个元素,我浪费了很多时间,将不胜感激。
最后一个标记没有以 ','
结尾,因此您不能为它使用 %[^,]
。但是它后面跟着一个 '\"'
,所以你可以使用 %[^\"]
来代替:
sscanf(str,"\"%[^,],%[^,],%[^,],%[^,],%[^\"]\" \n",c[i].Card_Number,c[i].Bank_Code,c[i].Expiry_Date,c[i].First_Name,c[i].Last_Name);
如果您只需要从文件中读取,您可以只使用 fscanf()
而不是从文件读取到字符数组,然后使用 sscanf()
来读取该字符串。
而且您不需要显式地强制转换 calloc()
的 return 值。参见 is it necessary to type-cast malloc and calloc。
你在做
if(fptr==NULL)
{return 0;}
在您尝试读取文件后。如果无法打开文件,程序会在控件到达此 if
语句之前崩溃。
打开文件后立即检查
FILE *fptr = fopen("file", "r");
if(fptr==NULL)
{
return EXIT_FAILURE;
}
和return值0
通常被认为是成功的意思。由于未找到输入文件是错误,请尝试 returning EXIT_FAILURE
。
最后 %[^,]" in the format string of sscanf function in your program, there is no comma for the last entry of each line in the input file. So change it to read till the last
"` 被发现。
此外,在格式字符串的末尾,有一个 space,后跟一个 \n
。 \n
在这里是多余的,因为 space 将匹配“One white-space character in format-string matches any combination of white-space characters in the input”
所以最终的格式字符串可以是
"\"%[^,],%[^,],%[^,],%[^,],%[^\"]\" "
并且不要忘记关闭您打开的文件并释放您在程序结束前分配的内存,例如
free(c); //for the Card pointer
fclose(fptr);
使用 fscanf()
和正确的格式,您可以从每一行中检索所需的元素:
"\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n"
With the previous format, the opening quote is ignored (\"
), and the strings separated by commas are captured (%[^,]%*c
). Finally the the closing quote is discarded (%[^\"]%*c
), and the line break considered (\n
), to let next line to be read.
这是将其集成到代码中的方法:
while (fscanf(file, "\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name) != -1 ) i++;
用于测试目的的完整代码片段:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char Card_Number[20];
char Bank_Code[6];
char Expiry_Date[8];
char First_Name[30];
char Last_Name[30];
}Card;
int main(){
FILE *file;
file = fopen("data.csv", "r");
int i=0;
Card *c = (Card*)calloc(10,sizeof(Card));
while (fscanf(file, "\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name) != -1 ) {
printf("%s | %s | %s | %s | %s \n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name);
i++;
}
fclose(file);
return 0;
}
假设我想从这样的文件中获取输入:-
"8313515769001870,GRKLK,03/2023,eatcp,btlzg"
"6144115684794523,ZEATL,10/2033,arnne,drrfd"
我做的一个结构如下
typedef struct{
char Card_Number[20];
char Bank_Code[6];
char Expiry_Date[8];
char First_Name[30];
char Last_Name[30];
}Card;
这是我尝试在阅读模式下从名为 'file' 的文件中读取输入,fgets 中的 str 正在存储正确的字符串,但它没有被吸收 c[i]:
FILE * fptr;
int count=0;
fptr= fopen("file","r");
Card *c = (Card*)calloc(10,sizeof(Card));
printf("StartAlloc\n");
int i=0;
char str[1000];
fgets(str,80,fptr);
if(fptr==NULL)
{return 0;}
do{
sscanf(str,"\"%[^,],%[^,],%[^,],%[^,],%[^,]\" \n",c[i].Card_Number,c[i].Bank_Code,c[i].Expiry_Date,c[i].First_Name,c[i].Last_Name);
i++;
}while(fgets(str,80,fptr)!=NULL);
我不明白为什么正则表达式 %[^,] 没有捕获单个元素,我浪费了很多时间,将不胜感激。
最后一个标记没有以 ','
结尾,因此您不能为它使用 %[^,]
。但是它后面跟着一个 '\"'
,所以你可以使用 %[^\"]
来代替:
sscanf(str,"\"%[^,],%[^,],%[^,],%[^,],%[^\"]\" \n",c[i].Card_Number,c[i].Bank_Code,c[i].Expiry_Date,c[i].First_Name,c[i].Last_Name);
如果您只需要从文件中读取,您可以只使用 fscanf()
而不是从文件读取到字符数组,然后使用 sscanf()
来读取该字符串。
而且您不需要显式地强制转换 calloc()
的 return 值。参见 is it necessary to type-cast malloc and calloc。
你在做
if(fptr==NULL)
{return 0;}
在您尝试读取文件后。如果无法打开文件,程序会在控件到达此 if
语句之前崩溃。
打开文件后立即检查
FILE *fptr = fopen("file", "r");
if(fptr==NULL)
{
return EXIT_FAILURE;
}
和return值0
通常被认为是成功的意思。由于未找到输入文件是错误,请尝试 returning EXIT_FAILURE
。
最后 %[^,]" in the format string of sscanf function in your program, there is no comma for the last entry of each line in the input file. So change it to read till the last
"` 被发现。
此外,在格式字符串的末尾,有一个 space,后跟一个 \n
。 \n
在这里是多余的,因为 space 将匹配“One white-space character in format-string matches any combination of white-space characters in the input”
所以最终的格式字符串可以是
"\"%[^,],%[^,],%[^,],%[^,],%[^\"]\" "
并且不要忘记关闭您打开的文件并释放您在程序结束前分配的内存,例如
free(c); //for the Card pointer
fclose(fptr);
使用 fscanf()
和正确的格式,您可以从每一行中检索所需的元素:
"\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n"
With the previous format, the opening quote is ignored (
\"
), and the strings separated by commas are captured (%[^,]%*c
). Finally the the closing quote is discarded (%[^\"]%*c
), and the line break considered (\n
), to let next line to be read.
这是将其集成到代码中的方法:
while (fscanf(file, "\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name) != -1 ) i++;
用于测试目的的完整代码片段:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char Card_Number[20];
char Bank_Code[6];
char Expiry_Date[8];
char First_Name[30];
char Last_Name[30];
}Card;
int main(){
FILE *file;
file = fopen("data.csv", "r");
int i=0;
Card *c = (Card*)calloc(10,sizeof(Card));
while (fscanf(file, "\"%[^,]%*c %[^,]%*c %[^,]%*c %[^,]%*c %[^\"]%*c\n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name) != -1 ) {
printf("%s | %s | %s | %s | %s \n", c[i].Card_Number, c[i].Bank_Code, c[i].Expiry_Date, c[i].First_Name, c[i].Last_Name);
i++;
}
fclose(file);
return 0;
}