问题描述
我的作业遇到了问题.我需要将文本文件中的一些数据扫描到结构中.文本文件看起来像这样.
I have encountered a problem with my homework. I need to scan some data from a text file, to a struct.The text file looks like this.
012345678;danny;cohen;22;M;danny1993;123;1,2,4,8;Nice person
223325222;or;dan;25;M;ordan10;1234;3,5,6,7;Singer and dancer
203484758;shani;israel;25;F;shaninush;12345;4,5,6,7;Happy and cool girl
349950234;nadav;cohen;50;M;nd50;nadav;3,6,7,8;Engineer very smart
345656974;oshrit;hasson;30;F;osh321;111;3,4,5,7;Layer and a painter
每个数据项与其匹配的变量.id = 012345678名字 = 丹尼等等...
Each item of data to its matching variable.id = 012345678first_name = dannyetc...
现在我不能使用 fscanf,因为没有间距,并且 fgets 扫描所有行.
Now I can't use fscanf because there is no spacing, and the fgets scanning all the line.
我用 %[^;]s 找到了一些解决方案,但是我需要编写一个代码块,然后为每一项数据复制并传递 9 次.
I found some solution with %[^;]s, but then I will need to write one block of code and, copy and past it 9 times for each item of data.
如果每个数据项之间有间距,是否还有其他选项而不更改文本文件,类似于我用 fscanf 编写的代码?
Is there any other option without changing the text file, that similar to the code I would write with fscanf, if there was spacing between each item of data?
**************** 更新 **************
************* UPDATE **************
嘿,首先,感谢大家的帮助,真的很感激.我不明白你所有的答案,但我确实使用了一些东西.
Hey, First of all, thanks everyone for the help really appreciating.I didn't understand all your answers, but here something I did use.
这是我的代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char *idP, *firstNameP, *lastNameP;
int age;
char gender, *userNameP, *passwordP, hobbies, *descriptionP;
}user;
void main() {
FILE *fileP;
user temp;
char test[99];
temp.idP = (char *)malloc(99);
temp.firstNameP = (char *)malloc(99);
temp.lastNameP = (char *)malloc(99);
temp.age = (int )malloc(4);
temp.gender = (char )malloc(sizeof(char));
temp.userNameP = (char *)malloc(99);
fileP = fopen("input.txt", "r");
fscanf(fileP, "%9[^;];%99[^;];%99[^;];%d;%c", temp.idP,temp.firstNameP,temp.lastNameP,&temp.age, temp.gender);
printf("%s\n%s\n%s\n%d\n%c", temp.idP, temp.firstNameP, temp.lastNameP, temp.age, temp.gender);
fgets(test, 60, fileP); // Just testing where it stop scanning
printf("\n\n%s", test);
fclose(fileP);
getchar();
}
一切正常,直到我扫描 int 变量,之后它没有扫描任何东西,我得到一个错误.
It all works well until I scan the int variable, right after that it doesn't scan anything, and I get an error.
非常感谢.
推荐答案
正如评论中所讨论的,fscanf
可能是最短的选项(尽管 fgets
后跟 strtok
和手动解析是可行的选择).
As discussed in the comments, fscanf
is probably the shortest option (although fgets
followed by strtok
, and manual parsing are viable options).
您需要对字符串字段使用 %[^;]
说明符(意思是:一串字符 other than ;
), 用 ;
分隔字段以使用实际的分号(我们特别要求不要将其作为字符串字段的一部分使用).最后一个字段应该是 %[^\n]
以消耗到换行符,因为输入没有终止分号.
You need to use the %[^;]
specifier for the string fields (meaning: a string of characters other than ;
), with the fields separated by ;
to consume the actual semicolons (which we specifically requested not to be consumed as part of the string field). The last field should be %[^\n]
to consume up to the newline, since the input doesn't have a terminating semicolon.
您还应该(始终)将使用 scanf
系列函数读取的每个字符串字段的长度限制为比可用空间少 1(终止 NUL 字节是 +1).因此,例如,如果第一个字段的长度最多为 9 个字符,则需要 char field1[10]
,格式为 %9[^;]
.
You should also (always) limit the length of each string field read with a scanf
family function to one less than the available space (the terminating NUL byte is the +1). So, for example, if the first field is at most 9 characters long, you would need char field1[10]
and the format would be %9[^;]
.
在格式字符串的开头放置一个空格以消耗任何空格(例如前一个换行符)通常是个好主意.
It is usually a good idea to put a single space in the beginning of the format string to consume any whitespace (such as the previous newline).
而且,当然你应该检查fscanf
的返回值,例如,如果你按照示例有9个字段,它应该返回9
.
And, of course you should check the return value of fscanf
, e.g., if you have 9 fields as per the example, it should return 9
.
因此,最终结果将类似于:
So, the end result would be something like:
if (fscanf(file, " %9[^;];%99[^;];%99[^;];%d;%c;%99[^;];%d;%99[^;];%99[^\n]",
s.field1, s.field2, s.field3, &s.field4, …, s.field9) != 9) {
// error
break;
}
(或者,用逗号分隔的数字字段可以读作四个单独的字段,如 %d,%d,%d,%d
,在这种情况下,计数将达到 12.)
(Alternatively, the field with numbers separated by commas could be read as four separate fields as %d,%d,%d,%d
, in which case the count would go up to 12.)
这篇关于从文本文件扫描数据,每个数据项之间没有间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!