使用分隔符分隔字符串和整数

时间:2017-09-02 14:03:37

标签: c scanf delimiter

美好的一天,

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

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 个答案:

答案 0 :(得分: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格式输出换行符并确认数据文件中没有换行符,换行符在何处输出来自?

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

答案 1 :(得分:0)

这种情况下单独使用fscanf进行阅读可以起作用,但缺乏通过一次读取整行然后使用sscanf解析该行或仅仅走一对来实现的稳健性选择idname对的字符指针。

要在您作为输入发布的行上使用fscanf,您可以在重复调用"%d,%[^0-9]"时使用fscanf格式说明符。 (如果name超过数组大小,则应提供 field-width 修饰符以防止溢出)。例如,您可以执行以下操作来获取每个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面向行的输入来阅读整行,然后解析每个id和{{1}从保存整行的缓冲区中,您可以执行以下操作。读取整行,然后解析的好处是它将读取与解析分离,允许您验证两者。此外,在输入格式略有不同的情况下,您的阅读不受匹配失败的影响。

此处,使用name并使用sscanf 格式说明符来确定每次调用%n所消耗的字符数,您可以使用指针选择sscanfid对,例如

name

注意:输出相同。