扫描文本文件中的数据,每项数据之间没有空格

时间:2018-12-26 21:20:10

标签: c text scanf

我的作业遇到了问题。我需要将一些数据从文本文件扫描到结构。 文本文件如下所示。

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 first_name =丹尼 等等...

现在我不能使用fscanf,因为没有间距,并且fget会扫描所有行。

我找到了%[^;] s的一些解决方案,但随后我将需要编写一个代码块,并为每一项数据复制并粘贴9次。

如果每一项数据之间都有间隔,是否还有其他选项不更改文本文件,类似于我用fscanf编写的代码?

*************更新**************

嘿,首先,感谢大家的帮助。 我听不懂您的回答,但这里确实使用了一些东西。

这是我的代码:

#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变量,此后它什么也不扫描,并且出现了错误。

非常感谢。

2 个答案:

答案 0 :(得分:2)

如评论中所述,fscanf可能是最短的选择(尽管fgets后跟strtok,并且手动解析是可行的选择)。

您需要对字符串字段使用%[^;]说明符(意思是:除了 ;以外的字符串,{{1} }消耗实际的分号(我们明确要求不要使用它作为字符串字段的一部分)。最后一个字段应为;,以消耗掉换行符,因为输入没有终止分号。

您还应该(始终)将通过%[^\n]系列函数读取的每个字符串字段的长度限制为小于可用空间的长度(终止NUL字节为+1)。因此,例如,如果第一个字段最多为9个字符长,则需要scanf,格式为char field1[10]

通常最好在格式字符串的开头放置一个空格以使用任何空格(例如前一个换行符)。

当然,您应该检查%9[^;]的返回值,例如,如果根据示例,您有9个字段,则它应该返回fscanf

因此,最终结果将类似于:

9

(或者,用逗号分隔数字的字段也可以读为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; } 的四个独立字段,在这种情况下,计数最多为12。)

答案 1 :(得分:1)

这里有简单的令牌生成器。如我所见,您在这里有多个定界符(;,

str-要标记的字符串

del-包含定界符的字符串(仅在您使用";,"";"的情况下)

allowempty-如果为true,则如果存在两个或多个连续的定界符

,则允许空标记

返回值是指向令牌的NULL终止表。

char **mystrtok(const char *str, const char *del, int allowempty)
{
  char **result = NULL;
  const char *end = str;
  size_t size = 0;
  int extrachar;

  while(*end)
  {
    if((extrachar = !!strchr(del, *end)) || !*(end + 1))
    {
        /* add temp variable and malloc / realloc checks */
        /* free allocated memory on error */
        if(!(!allowempty && !(end - str)))
        {
            extrachar = !extrachar * !*(end + 1);
            result = realloc(result, (++size + 1) * sizeof(*result));
            result[size] = NULL;
            result[size -1] = malloc(end - str + 1 + extrachar);
            strncpy(result[size -1], str, end - str + extrachar);
            result[size -1][end - str + extrachar] = 0;
        }
        str = end + 1;
    }
    end++;
  }
  return result;
}

要释放令牌生成器分配的内存:

void myfree(char **ptr)
{
    char **savedptr = ptr;
    while(*ptr)
    {
        free(*ptr++);
    }
    free(savedptr);
}

功能很简单,但是您可以使用任何分隔符和任意数量的分隔符。

相关问题