简体   繁体   English

如何从C中的文件中的双引号之间读取多个单词

[英]how to read more than one word between double quotes from a file in C

i'm trying to read strings from a file and into a struct but when i reach strings with two or more words everything i seem to try does not work我正在尝试从文件中读取字符串并读取到结构中,但是当我到达带有两个或更多单词的字符串时,我似乎尝试的所有内容都不起作用

data in file文件中的数据

"K300" "Keyboard" "US Generic" 150.00 50 “K300” “键盘” “美国通用” 150.00 50

"R576" "16-inch Rims" "Toyota Verossa" 800.00 48 "R576" "16 英寸轮辋" "Toyota Verossa" 800.00 48

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct partInfo {
  char number[6];
  char name[20];
  char description[30];
  double price;
  int qty;
}Part;

int main() {

char num[6], name[20], desc[30];
int i=0;
int q;
double p;
char ch;


FILE * in = fopen("input.txt", "r");

Part part1;
fscanf(in, " %[^ ]s", &num);
printf("%s\n", num);

fscanf(in, " %[^ ]s", &name);
printf("%s\n", name);

fscanf(in, " %[^ ]s", &desc); //right here only copy "US and not the Generic"
printf("%s\n", desc);

strcpy(part1.number, num);
strcpy(part1.name, name);
strcpy(part1.description, desc);

fclose(in);
return 0;
}

however when i try to use但是当我尝试使用

 fscanf(in, " %[^\n]s", &desc); 

it copies the rest of the line i've been stuck on this for two days can someone please help me and also how to get rid of the double quotes if that is possible i tried a different set of code for that and more errors arise :(它复制了我已经坚持了两天的行的其余部分,有人可以帮助我,以及如何摆脱双引号,如果可能的话,我为此尝试了一组不同的代码,但出现了更多错误: (

In scanf , the expression %[chars] reads the longest string that contains the characters (or character ranges) in the bracket. scanf ,表达式%[chars]读取包含括号中字符(或字符范围)的最长字符串。 A caret as first character reverses this: %[^chars] reads the longest string that does not contain any of the characters. 插入号作为第一个字符将与此相反: %[^chars]读取不包含任何%[^chars]的最长字符串。 Hence, %[^ ] reads stuff up to the next space, and %[^\\n] reads stuff up to the next new line. 因此, %[^ ]读取内容直到下一个空格, %[^\\n]读取内容直到下一个新行。

In your case, where the string is delimited by double quotes, you should read the opening quote, then stuff up to the next quote and finally the closing quote: 在您的情况下,字符串用双引号分隔,您应该阅读开头的引号,然后填充到下一个引号,最后是结尾的引号:

res = fscanf(in, " \"%[^\"]\"", name);

This format starts with a space and so discards white space before the first quote. 这种格式以空格开头,因此会在第一个引号之前放弃空格。 The format string looks ugly because the double quote itself is escaped. 格式字符串看起来很难看,因为双引号本身已转义。 To illustrate, this is how the command would look like if your strings were delimited by single quotes. 为了说明这一点,如果您的字符串用单引号引起来,则命令的外观如下。

res = fscanf(in, " '%[^']'", name);

This approach works only if your strings are always enclosed in quotes, even if they don't have spaces. 仅当您的字符串始终用引号引起来时,即使它们没有空格,此方法也有效。

It is probably cleaner to read a whole line with fgets and then sscanf from that line to catch unmatched quotes. 读取带有fgets的整行,然后从该行中sscanf以捕获不匹配的引号,可能更干净。 That way you could also scan the line several times - once for a string with quotes, a second time for an unquoted string, say - without accessing the disk more than once. 这样,您还可以多次扫描行-一次扫描带引号的字符串,第二次扫描未引号的字符串-无需多次访问磁盘。

Edit: Corrected the format syntax, which containes a spurious s and updated the description of the bracket syntax for strings in the first paragraph. 编辑:纠正了格式语法,该格式语法包含乱码s并更新了第一段中字符串括号语法的描述。

Edit II: Because the OP seems to be confused about how fscanf works, here's a small example that reads parts from a file line by line: 编辑II:因为OP似乎对fscanf工作方式感到困惑,所以下面是一个小示例,它逐行从文件中读取部分:

#define MAX 10
#define MAXLINE 240

int main(int argc, char *argv[])
{
    FILE *in;
    int nline = 0;

    Part part[MAX];
    int npart = 0;
    int res, i;

    in = fopen(argv[1], "r"); // TODO: Error checking

    for (;;) {
        char buf[MAXLINE];
        Part *p = &part[npart];

        if (fgets(buf, MAXLINE, in) == NULL) break;
        nline++;

        res = sscanf(buf, 
            " \"%5[^\"]\" \"%19[^\"]\" \"%29[^\"]\" %lf %d", 
            p->number, p->name, p->description, &p->price, &p->qty);

        if (res < 5) {
            static const char *where[] = {
                "number", "name", "description", "price", "quantity"
            };

            if (res < 0) res = 0;
            fprintf(stderr, 
                "Error while reading %s in line %d.\n",
                where[res], nline);
            break;
        }

        npart++;
        if (npart == MAX) break;
    }
    fclose(in);

    // ... do domething with parts ...

    return 0;
}

Here, the line is read in forst from the file. 在这里,该行从文件中读入forst。 Then, that line ( buf ) is scanned for the required format. 然后,对该行( buf )进行扫描以获取所需格式。 Of course, sscanf must be used instead of fscanf here. 当然,这里必须使用sscanf代替fscanf On error, a simple error message is printed. 错误时,将显示一条简单的错误消息。 This message includes the line number and the field entry where reading went wrong, so the error can be located in the input file. 此消息包括行号和读取错误的字段条目,因此可以在输入文件中找到错误。

Note how the sscanf includes maximum field lengths to avoid overflowing the string buffers of the part. 注意sscanf如何包括最大字段长度,以避免溢出部件的字符串缓冲区。 A scanning error occurs when the quoted string is too long. 当加引号的字符串太长时,将发生扫描错误。 It would be nicer to have sscanf read all characters and only store the first 5, say, but that's not how sscanf works. 最好使sscanf读取所有字符并仅存储前5个字符,但这不是sscanf工作方式。 Such a solution requires another approach, probably a custom scanning function. 这样的解决方案需要另一种方法,可能是自定义扫描功能。

very helpful.很有帮助。 thank you, writing a comment to save this post for later, cant figure out this godforsakens ite谢谢你,写一条评论来保存这篇文章以备后用,无法弄清楚这个上帝遗弃的网站

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM