2015-04-19 81 views
1

我想修复我的C程序,忽略名称前的多余空格。如何从文本文件读取时忽略空格?

例如,当从stdin读取输入是:

11, Alan Turing,3.20 

存在第一逗号和名字之间的空间。我想忽略这个空间,下面一行追加到student.txt

11,Alan Turing,3.20 

这里是我的代码:

#include <stdio.h> 
#include <string.h> 
typedef struct student { 
    int id; 
    char name[300]; 
    float grade; 
}Student; 

int main() { 
    Student s; 
    FILE *fp; 
    fp = fopen("student.txt","a+"); 
    scanf("%d",&s.id); 
    scanf("%[^1234567890]s",&s.name); 
    s.name[strlen(s.name) - 1] = '\0'; 
    scanf("%f",&s.grade); 
    fprintf(fp,"%d,%s,%.2f\n",s.id,s.name,s.grade); 
    fclose(fp); 
    return 0; 
} 
+0

我不明白输入是来自文件还是来自stdin? –

+0

我将数据输入到名为student.txt的文本文件中,如何删除显示在帖子中的额外空间。 –

+3

请更清晰地定义您的需求。文件中还有其他空格。那么你需要删除哪些?其他地方是否可以有不需要的空间?它恰恰是一个空间还是可以更多/更少/没有空间?等这些答案将改变最好的解决方案。 – kaylum

回答

0

你在第二scanf扫描集读取所有的非数字字符。这不是你想要做的。你想读取所有字符到下一个逗号。

试着用替换你的三个scanf电话:

scanf("%d, ", &s.id); 
scanf("%[^,]", &s.name); 
scanf(",%f", &s.grade); 

,并消除你在之间的分配。

请注意,它是第一个scanf中的空格字符,用于删除不需要的空间。

+0

不明白你的答案先生,我试过这个,但程序没有退出后,我输入数据。 –

+0

'“%[^,] s”' - >这是不正确的。 '“,%f \ n”'不适合'stdin'后缀空格。 – chux

+0

@chux你说得对第一个,'s'应该被删除。它在原代码中,我忘记删除它。有趣的是,它甚至在我拥有它时(clang,而不是gcc)都有效。我有点不同意你的第二个陈述,但是我看到你的观点,并且我也从答案中删除了尾部的'\ n'。第一个尾随空格(在'“%d”,')当然不能删除,建议或不要。 ''中的那个,%f \ n“'(正如我原来那样)可以被删除。如果线路正常结束并且用户耐心等待EOF,则不会造成伤害。然而,这可能是混淆了Maher ... – nickie

0

我已经写了一个快速的解析器,这读取一个int跳过非字母字符,存储所有字符,直到找到那么数字解析浮动

我已经后stdin解析做任何修改。 标准输入:

45 foo bar 45.69 
45, toto, 78.5 

标准输出:

文件内容:

45,foo bar,45.69 
45,toto,78.50 

PROG:

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

typedef struct student {              
    int id;                  
    char name[256]; /* use aligned structures*/         
    float grade;                
} Student;                  

int main() {                 
    Student s;                 
    FILE *fp;                 
    char buf[BUFSIZ];               
    char *p;                 
    int i = 0;                 

    fp = fopen("student.txt", "a+");           
    printf("Give id name and grade\n");           
    fgets(buf, sizeof(buf), stdin);            


    p = buf;                 
    /* get id */                
    s.id = strtol(p, &p, 10);             
    if (!s.id) {                
     fprintf(stderr, "Bad id");            
     return -1;                
    }                   
    /* skip non alpha char between int and name*/        
    while (!isalpha(*p)) {              
     p++;                 
    }                   

    /*copy name */                
    while (!isdigit(*p)) {              
     s.name[i++] = *p++;              
    }                   
    if (i == 0) {                
     fprintf(stderr, "Bad name");           
     return -1;                
    }                   
    s.name[i] = '\0';               
    i--;                  
    /*remove trailing char at the end of the name */       
    while(!isalpha(s.name[i])) {            
     s.name[i--] = '\0';              
    }                   
    /* parse grade */               
    s.grade = strtof(p, &p);             


    fprintf(fp,"%d,%s,%.2f\n",s.id,s.name,s.grade);        
    fclose(fp);                 
    fp = fopen("student.txt","r");            
    if(fp != NULL) {               
     while((fscanf(fp,"%d,%299[^,],%f", &s.id,s.name,&s.grade)) == 3) {  
      printf("ID:%d\n",s.id);            
      printf("NAME:%s\n",s.name);           
      printf("GRADE:%.2f\n",s.grade);          
     }                  
     fclose(fp);                
    } else {                 
     perror("student.txt");             
    }                   
    return 0;                 
} 
0

要删除一个字符串中的字符,你必须取代以下逗号后的ng个字符。

一个可能会像下面这样的函数结束,而他们有很多其他方法来解决这个问题,我觉得这个方法简单而高效。

void 
trim_comma_spaces(char *string) 
{ 
     char *tmp; 
     char *ptr = string; 
     int i; 
     size_t len; 

     ptr = string; 
     while(1) { 
       tmp = strchr(ptr, ','); 

       if(!tmp) 
         break; 

       for(i=0, tmp++; isspace(*(tmp+i)); i++); 

       if(!i) { 
         ptr = tmp + 1; 
         continue; 
       } 

       len = strlen(tmp); 

       /* memory areas may overlap? Use memmove */ 
       memmove(tmp, tmp+i, len - i); 

       *(tmp + len - i) = '\0'; 

       ptr = tmp; 
     } 
} 

例如

int 
main(void) 
{ 
     char *ptr; 
     char *tmp; 
     char string[] = "11,  \n\n\r\v\f  Alan Turing, 3.20\n12, \n\v\fJohn Doe, 3.19"; 

     printf("Before:\n%s\n", string); 
     trim_comma_spaces(string); 

     printf("after:\n%s\n", string); 
     return 0; 
} 

输出:

Before: 
11, 



     Alan Turing, 3.20 
12, 


John Doe, 3.19 
after: 
11,Alan Turing,3.20 
12,John Doe,3.19 
0

建议从读取线fgets()

现在使用"%d , %299[A-Za-z ] ,%f"扫描缓冲区。一定要测试ssscanf()的结果。

"%d"阅读任何空格,阅读int
" , "阅读任何空格,逗号,任何空格
"%299[A-Za-z ]"最多可读取299个字符串的alpha或空格。
或者其他char(如-'.)在名称中发现需要"%299[-A-Za-z '.]"@BLUEPIXY
" ,"阅读任何空格,逗号。
"%f"读取任何空格,读取浮点数。

#include <stdio.h> 
#include <string.h> 
typedef struct student { 
    int id; 
    char name[300]; 
    float grade; 
} Student; 

int main(void) { 
    Student s; 
    FILE *fp; 
    fp = fopen("student.txt", "a+"); 

    // Read line, =uses a buffer about twice expected need 
    char buf[sizeof s * 2]; 
    fgets(buf, sizeof buf, stdin); 

    // 11, Alan Turing,3.20 
    int cnt = sscanf(buf, "%d , %299[A-Za-z ] ,%f", &s.id, s.name, &s.grade); 
    if (cnt != 3) { 
    fprintf(stderr, "Unexpected input, cnt = %d\n", cnt); 
    fclose(fp); 
    return 1; 
    } 
    fprintf(fp, "%d,%s,%.2f\n", s.id, s.name, s.grade); 
    fclose(fp); 
    return 0; 
} 
+0

注:名称包含空格。 '[A-ZA-Z]'是不允许的空间。 – BLUEPIXY

+0

@BLUEPIXY Oops -meant'[A-Za-z]'纠正了 – chux

+0

好,以下人不能输入。 “塔图姆奥尼尔”,“温斯顿伦纳德斯宾塞丘吉尔爵士”,“哈里杜鲁门”...... – BLUEPIXY

0

我写了一个跳过空白的函数。

//function to skip space while reading from file 
void skip_space(FILE *fp) 
{ 
    char tmp; 
    do 
    { 
     fscanf(fp, "%c", &tmp); 
    } while (isspace(tmp) || feof(fp)); 

    fseek(fp, -1, SEEK_CUR); 
} 

无论你想忽略空格,你都可以调用这个函数。

相关问题