2015-04-19 79 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); 
} 

無論你想忽略空格,你都可以調用這個函數。

相關問題