2017-09-02 115 views
-2

日安分离字符串和整数,使用分隔符

所以目前我有这个文件,包含:实际文件是这样

1,name A. lname2,Das F. Esd3,Frsas A. Casdfre4,Rsadna P. Tsdaas5,Asadla C. Toasdtino6,Aasdel P. Gasdla7,Masda Isable A. Milasdroso8,Niasdkie T. Niasdemus9,Evasdn A. Vasdueva10,Geasdlyn C. Iasdncio11,Aasdr Leasdma12,Neasdio A. Maasdbale 

我有麻烦做输出,这里是我当前的代码

printf("\nID\tName\n");  
while(fscanf(load, "%[^,],%[^1-9]", faculty[counter].id, faculty[counter].name)!=EOF) { 
    printf("%s\t%s", faculty[counter].id, faculty[counter].name); 

output
和输出是这样的:

ID Name  
1 asdasd  
2 asdas 
3 asdsad4  othername  
5 asdsad 
6 asdasda  
7 sdfsdf  
8 sadsad 
9 asdsad  
10 asdas  
11 asdsad12 asdas  
4,12 has invalid position. 

输出应该是人气指数:

1 ID Name  
1 asdasd  
2 asdas 
3 asdsad  
4 othername  
5 asdsad 
6 asdasda  
7 sdfsdf  
8 sadsad 
9 asdsad  
10 asdas  
11 asdsad  
12 asdas  

可能是什么问题呢?这是我第一次使用这种分隔符,你能解释一下这个问题吗?谢谢!

+2

请对代码块,输出和文件内容使用适当的格式。 @Someprogrammerdude试图修复它,但你的编辑改变了它。 Eimantas应用的最新修补程序。 – Myst

+0

代码固定,对不起 –

+0

你在'fscanf'中使用正则表达式;这是不正确的,它只能理解格式字符串。 –

回答

0

更改格式如下:

printf("\nID\tName\n");  
while (fscanf(load, " %[0-9], %[^0-9]", faculty[counter].id, faculty[counter].name) == 2) { 
    printf("%s\t%s\n", faculty[counter].id, faculty[counter].name); 
    ... 
    counter++; 
} 

请注意,您也应该通过的最大字符数存储到目标阵列以避免潜在的缓冲区溢出。

但请注意,发布在问题中的示例输出与代码片段不一致:您不会输出格式为printf的换行符,并确认数据文件中没有换行符,输出中的换行符来自哪里从?

你可以制作一个带有假名称的测试文件来显示问题吗?还发布失败的完整代码。结构定义也很重要。没有精确的数据和代码就很难设置诊断。

+0

只有1个输出与此一起显示 –

+0

您显示的输出与您发布的文件内容不一致。数字后面总是有逗号?该文件是否包含换行符? – chqrlie

+0

是的,就是这样,在数字后面有一个逗号,但在姓氏后面没有逗号,没有换行符 1,fistname A. lastname2,firstname F. lastname 我刚添加了一些随机字符,因为它包含真实姓名,对不起, –

0

这是一种情况,其中有fscanf阅读单独可以工作,但通过阅读完整的行一次,然后解析符合或者sscanf或者干脆走路一对字符指针的上下行采摘缺乏稳健性就可以实现出idname对。

要在已发布的输入线路上使用fscanf,您可以使用格式说明的"%d,%[^0-9]"在重复调用fscanf。 (如果名称长于数组大小,则应提供字段宽度修饰符以防止发生溢出)。例如,你可以这样做以下操作以获取每个idname对(这只是输出在下面的例子):

#include <stdio.h> 

enum { MAXNM = 64 }; /* constant for max characters in name */ 

int main (int argc, char **argv) { 

    int id; 
    char name[MAXNM] = ""; 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    /* read each 'id,name' pair (name cannot include digits) */ 
    while (fscanf (fp, "%d,%63[^0-9]", &id, name) == 2) 
      printf ("%3d %s\n", id, name); 

    if (fp != stdin) fclose (fp);  /* close file if not stdin */ 

    return 0; 
} 

示例使用/输出

$ ./bin/rd_num_name <dat/num_names.txt 
    1 name A. lname 
    2 Das F. Esd 
    3 Frsas A. Casdfre 
    4 Rsadna P. Tsdaas 
    5 Asadla C. Toasdtino 
    6 Aasdel P. Gasdla 
    7 Masda Isable A. Milasdroso 
    8 Niasdkie T. Niasdemus 
    9 Evasdn A. Vasdueva 
10 Geasdlyn C. Iasdncio 
11 Aasdr Leasdma 
12 Neasdio A. Maasdbale 

如果你想使用面向行的输入与fgetsgetline读取整个行,然后分析每个idname从缓冲器保持整行,则可以做如下的事情。读取整行,然后解析的好处是,它将读取与解析分离开来,从而可以验证两者。此外,您的阅读不受匹配失败输入格式的轻微变化。

在这里,用sscanf以及利用所述%n格式说明以确定由每一次调用sscanf消耗的字符数,可以步行指针向下行挑选出idname双,例如

#include <stdio.h> 

enum { MAXNM = 64, MAXLN = 512 }; /* max name & line constants */ 

int main (int argc, char **argv) { 

    int id; 
    char name[MAXNM] = "", 
     line[MAXLN] = "", 
     *p = line;   /* pointer to line to walk string */ 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); 
     return 1; 
    } 

    while (fgets (line, sizeof line, fp)) /* read each line/validate */ 
    { 
     int offset = 0;      /* number of char processed */ 
     while (sscanf (p, "%d,%63[^0-9]%n", &id, name, &offset) == 2) { 
      printf ("%3d %s\n", id, name); 
      p += offset;     /* advance to next id,name */ 
     } 
    } 

    if (fp != stdin) fclose (fp);  /* close file if not stdin */ 

    return 0; 
} 

注:输出是一样的。