【问题标题】:String parsing from a file从文件中解析字符串
【发布时间】:2021-06-23 15:23:40
【问题描述】:

我有一个文件customers.txt,它在“--”之间的一行包含客户姓名、购物日期和市场名称;

customers.txt

Yusuf Sevki Gunaydin--11/02/2018--MARKS AND SPENCER
Mert Lacinkaya--24/02/2018--VAKKO
Elif Gul--13/05/2017--TEKIN ACAR
Hatice Cataloluk--12/07/2017--SIEMENS

我想从文件中读取它并存储在结构中并查看。添加了所有细节。

typedef struct customer
{
    const char *name;
    const char *date;
    const char *marketPlace;

}customer;

int main( void ){
   FILE * file = fopen("customers.txt","r");
   customer wcustomers[25];

   if (file == NULL){
      puts("File not found !!!");
   }
   else{
    readFile(file,wcustomers);
   }
    for(int i=0; i<3 ; ++i){
       printf("%s  %s  %s\n",
          wcustomers[i].name,
          wcustomers[i].date,
          wcustomers[i].marketPlace);
    }

   return 0;
 }

 void readFile(FILE *fp, customer wcustomers[]){
   char a[50],b[50],c[50];
   size_t i=0;

   while(fscanf(fp ,"%[^--]%*s%[^--]%*s%[^\n]%*s",a,b,c) != EOF){
       wcustomers[i].name = a;
       wcustomers[i].date = b;
       wcustomers[i].marketPlace = c;
       i++;  
   }
}

但是while循环程序的每次迭代都只是读取第一行并且有一个混乱。我可以在扫描文件时处理它或扫描后是否可以进行条带更改?

输出

��J'�   1 SUPERSTORE
Yusuf Evren Aykac   JEAN'S COFFEES
��J'�   1 SUPERSTORE
Yusuf Evren Aykac   JEAN'S COFFEES
��J'�   1 SUPERSTORE
Yusuf Evren Aykac   JEAN'S COFFEES

提前致谢

【问题讨论】:

  • 到目前为止您尝试了哪些方法,遇到了哪些具体问题?
  • 您好,如果您能添加更多有关您正在做什么的详细信息,将不胜感激?直接要求解决方案是不好的。

标签: c string struct


【解决方案1】:

您可以使用 fgets 逐行读取文件,并使用 strtok 分割每一行:

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

typedef struct customer
{
    const char *name;
    const char *date;
    const char *marketPlace;

}customer;

int main(int argc, char* argv[])
{
    char const* const fileName = argv[1];
    FILE* file = fopen(fileName, "r");
    char line[256];

    while (fgets(line, sizeof(line), file)) {
        const char s[2] = "--";
        char *token;
        customer c;

        token = strtok(str, s);
        if (token == NULL){
            printf("parsing error/n");
            exit(1);
        }
        c.name = malloc(strlen(token)+1);
        strcpy(c.name, token);

        token = strtok(str, s);
        if (token == NULL){
            printf("parsing error/n");
            exit(1);
        }
        c.date = malloc(strlen(token)+1);
        strcpy(c.date, token);

        token = strtok(str, s);
        if (token == NULL){
            printf("parsing error/n");
            exit(1);
        }
        c.marketPlace = malloc(strlen(token)+1);
        strcpy(c.marketPlace, token);
        
        processCustomer(&c);
    }

    fclose(file);
}

在此示例中,Customer c 变量仅在 while 循环的范围内,因此它存在的时间足以调用一些外部函数,如 processCustomer(),但您也可以创建一个客户结构数组并填充它们每次循环迭代加一。

【讨论】:

    【解决方案2】:

    可以通过多种方式完成。

    例如,您可以使用mmap 将文件的全部内容加载到内存中,然后使用strtok 遍历内存映射并对其进行解析。

    【讨论】:

    • 如果你使用mmap,那么strtok会将没有特殊选项的原始文件更改为mmap
    【解决方案3】:

    我认为您应该可以使用strtok 来做到这一点。您可以使用 fgets 逐行扫描文件,然后使用 strtok 拆分 get namedatemarketPlace 以下是在逐行扫描文件时填充 customer 数组的示例:

    // Read File
    FILE *pFile = fopen("customers.txt", "r");
    if(pFile == NULL) {
        perror("Unable to open file!");
        exit(1);
    }
    
    char line[100];
    customer customers[100];
    char delim[3] = "--";
    int nCustomers = 0;
    while(fgets(line, sizeof(line), pFile) != NULL) {
        // Trim trailing newline added by fgets
        line[strcspn(line, "\n")] = 0;
        
        // Name
        char *token = strtok(line, delim);
        char *name = (char *) malloc(strlen(token) + 1);
        strcpy(name, token);
    
        // Date
        token = strtok(NULL, delim);
        char *date = (char *) malloc(strlen(token) + 1);
        strcpy(date, token);
    
        // MarketPlace
        token = strtok(NULL, delim);
        char *marketPlace = (char *) malloc(strlen(token) + 1);
        strcpy(marketPlace, token);
    
        customers[nCustomers].name = name;
        customers[nCustomers].date = date;
        customers[nCustomers].marketPlace = marketPlace;
        nCustomers++;
    }
    

    【讨论】:

    • 分配固定的 50 字节会浪费空间,如果字符串超过 49 个字符,则会中断。最好使用 malloc(strlen(token)+1) 分配您需要的确切大小。
    • 你是对的。非常感谢您的评论。我已经更新了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多