给出4行的文本文件:用逗号(,)作为分隔符分隔。我通过使用fgets获取每一行并将ISBN(978-xxxxxxxxxx)与用户提供的ISBN进行比较来查找特定的ISBN。这很好用。
即使fgets()到文件的最后一行。它仍然返回正确的信息。但是,因为我试图将字符串的每个元素过滤到其受尊重的struct成员中以通过套接字发送。最后一个元素返回所有正确的内容,直到最后4个元素/字段。除了文件的最后一行之外,不会发生此错误。
我认为这是一个EOF错误,但是我并不精通sscanf()来理解为什么会这样。
如果我要打印 linebuf ,它会返回正确的(未解析的)行。 但是,如果我打印出我的所有数据。它返回第三行数据的一部分。具体而言,版,份数,可用副本
9780132126953,Andrew Tanenbaum & David Wetherall,Computer Networks,5,2011,Prentice-Hall,5,2
9780123745408,Michael Donahoo & Kenneth Calvert,TCP/IP Sockets in C,2,2009,Morgan Kaufman,3,0
9780133354690,William Stallings,Cryptography and Network Security,6,2014,Prentice-Hall,3,3
9780072467505,Yale Patt & Sanjay Patel,Introduction to Computing Systems from bits & gates to C & beyond 2,2004,McGraw-Hill,1,0
我的代码:
while (fgets(linebuf, 1024, file) != NULL) {
sscanf(linebuf, "%[^,], %[^,], %[^,], %u, %u, %[^,], %u, %u\n",
bufferISBN, bufferAuthor, bufferTitle,
&bufferEdition, &bufferYear, bufferPublisher,
&bufferInventory, &bufferAvailable
);
if (strcmp(temp->isbn, bufferISBN) == 0) { // found correct line, add data to struct
mssg.respType = Okay; // enum
mssg.requestID = temp->requestID;
strcpy(mssg.isbn, bufferISBN); // needs fixing
strcpy(mssg.authors, bufferAuthor);
strcpy(mssg.title, bufferTitle);
strcpy(mssg.publisher, bufferPublisher);
mssg.edition = bufferEdition;
mssg.year = bufferYear;
mssg.inventory = bufferInventory;
mssg.available = bufferAvailable;
}
注意sscanf()的格式,我不确定这是否正确:
"%[^,], %[^,], %[^,], %u, %u, %[^,], %u, %u\n"
我也知道我正在使用的大量缓冲区变量。
编辑:当我限制标题的长度时。它返回正常。这是为什么?
答案 0 :(得分:0)
有时,换行符不在文本文件的最后一行。要检查,请执行od -t x1 <filename>
,最后一个字符应为0a
如果不是,您可以使用文本编辑器清理文件并添加换行符。
或者,您可以稍微更改代码以处理此问题:
while (fgets(linebuf, 1024, file) != NULL) {
char *cp = strchr(linebuf, '\n');
if (cp != NULL)
*cp = 0;
sscanf(linebuf, "%[^,], %[^,], %[^,], %u, %u, %[^,], %u, %u",
答案 1 :(得分:0)
在检查返回值
之前,请勿使用sscanf()
的结果
if (8 != sscanf(linebuf, "%[^,], %[^,], %[^,], %u, %u, %[^,], %u, %u\n",
bufferISBN, bufferAuthor, bufferTitle,
&bufferEdition, &bufferYear, bufferPublisher,
&bufferInventory, &bufferAvailable
)) Handle_Error();
在这种情况下,返回值不受最后"%u"
之后扫描的内容的影响。为确保按预期扫描所有内容,请使用"%n"
,如果达到该格式说明符,则会保存扫描的char
个数。
int n = 0;
sscanf(linebuf, "%[^,], %[^,], %[^,], %u, %u, %[^,], %u, %u %n",
bufferISBN, bufferAuthor, bufferTitle,
&bufferEdition, &bufferYear, bufferPublisher,
&bufferInventory, &bufferAvailable,
&n);
if (n == 0) Handle_Scan_Incomplete();
if (linebuf[n] != '\0') Handle_Scan_Extra();
请注意,'\n'
和' '
作为格式指令执行相同操作:扫描0或更多空格。
注意:非"%c"
,"%n"
,"%[]"
之前的空格通常不需要,因为其他说明符占用了前导空格。可以使用:
"%[^,], %[^,], %[^,],%u,%u, %[^,],%u,%u %n"
为了保持一致性,建议在开始和宽度限制处使用空格(我只做了bufferISBN
)
char bufferISBN[14];
" %13[^,], %[^,], %[^,],%u,%u, %[^,],%u,%u %n"