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

  发布于 2023-02-13 15:43

我正在尝试从文件中读取字符串并将其读取到结构中,但是当我遇到两个或多个单词的字符串时,我似乎尝试的所有操作均不起作用

文件中的数据

“ K300”“键盘”“美国通用” 150.00 50

“ R576”“ 16英寸轮辋”“ Toyota Verossa” 800.00 48

#include 
#include 
#include 

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;
}

但是当我尝试使用

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

它复制了我在这上面停留了两天的行的其余部分,有人可以帮我吗,如果可能的话,我还应该如何消除双引号,我为此尝试了另一套代码,并且出现了更多错误: (

1 个回答
  • 在中scanf,表达式%[chars]读取最长的字符串,该字符串包含括号中的字符(或字符范围)。插入号作为第一个字符将扭转这种情况:%[^chars]读取不包含任何字符的最长字符串。因此,%[^ ]读取内容直到下一个空间,并且%[^\n]读取内容直到下一个新行。

    在您的情况下,字符串用双引号分隔,您应该阅读开头的引号,然后填充到下一个引号,最后是结尾的引号:

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

    这种格式以空格开头,因此会在第一个引号之前放弃空格。格式字符串看起来很难看,因为双引号本身已转义。为了说明这一点,如果您的字符串用单引号引起来,则命令的外观如下。

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

    仅当您的字符串始终 用引号引起来时,即使它们没有空格,此方法也有效。

    读取整行fgets然后sscanf从该行中捕获不匹配的引号可能更干净。这样,您还可以多次扫描行-一次扫描带引号的字符串,第二次扫描未引号的字符串-无需多次访问磁盘。

    编辑:纠正了格式语法,该格式语法包含乱码,s并更新了第一段中字符串括号语法的描述。

    编辑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;
    }
    

    在这里,该行从文件中读入forst。然后,对该行(buf)进行扫描以获取所需的格式。当然sscanf必须用代替fscanf这里。错误时,将显示一条简单的错误消息。此消息包括行号和读取错误的字段条目,因此可以在输入文件中找到错误。

    请注意sscanf包括如何包括最大字段长度,以避免溢出部件的字符串缓冲区。当加引号的字符串太长时,将发生扫描错误。sscanf读取所有字符并仅存储前5个字符会更好,例如,但这不是这样的sscanf。这样的解决方案需要另一种方法,可能是自定义扫描功能。

    2023-02-13 15:45 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有