2015-06-10 189 views
2

我想在c中寫一個讀取mtx文件的程序(mtx代表midi到文本,它實際上是一個txt文件),並且只存儲我需要的信息(特別是只有音符開/關和音調 - 彎曲消息)這裏是一個例子: mtx file example如何正確使用fscanf只在數組中存儲所需的信息?

我需要的信息是:時間(第一個數字),類型(On,Off和Pb),「n =」值和「v =」值(在彎音消息中只有「v =」值)。我不是C語言的專家,我知道基礎知識,並基於我的編程 this guidethis guide

這是我寫的代碼:

FILE * read_from; 
char status[3]; 
int u = 0; 
int ctrl,ct; 
read_from = fopen(nomesong, "r"); 
if (!read_from) 
    printf("NO WAY\n"); 
else{ 
while (1){ 
    ct = fscanf(read_from, "%d", array[u][0]); 
    if (ct == 1){ 
     ctrl = fscanf(read_from, " %s", &status); 
     if (ctrl == 1){ 
      if (status[1] == 'n'){ 
       array[u][1] = 1; 
       fscanf(read_from, " ch=1 n=%d v=%d", array[u][2], array[u][3]); 
      } 
      else if (status[1] == 'f'){ 
       array[u][1] = 0; 
       fscanf(read_from, " ch=1 n=%d v=%d", array[u][2], array[u][3]); 
      } 
      else if (status[1] == 'b'){ 
       array[u][1] = 2; 
       fscanf(read_from, " ch=1 v=%d", array[u][3]); 
      } 
     } 
     else if (errno != 0) { 
      perror("scanf:"); 
      break; 
     } 
     else { 
      printf("No match.\n"); 
     } 

    } 
    else if (errno != 0) { 
     perror("scanf:"); 
     break; 
    } 
    else if (ctrl == EOF) { 
     break; 
    } 
    printf("%d %d %d %d\n", array[u][0], array[u][1], array[u][2], array[u][3]); 
    u++; 
} 
}return; 

由於其輸出打印每行四個零(數組[] []初始化爲0),然後開始噴涌而出隨機大的數字,然後保持印刷零,然後停止和VS(2013)發出「未處理的豁免」警報消息。我究竟做錯了什麼?任何幫助將不勝感激。

+0

'狀態[3];' - >'狀態[4];','的fscanf(read_from, 「%S」,&狀態);' - >'的fscanf(read_from, 「%3S」 ,&status);' – chux

+0

我嘗試了你的建議,輸出相同。 –

+1

'status'變量是一個大小爲3的字符數組,但在'ctrl = fscanf(read_from,「%s」,&status);'中,讀取'Off'的概率很大,需要4個字節的空間額外字節爲NULL字符)。這會導致分段錯誤。 – Pratap

回答

2

OP代碼的問題包括:

1)傳遞的變量,而不是可變的在fscanf(read_from, " ch=1 n=%d v=%d", array[u][2], array[u][3]);

2)的空間不足讀取"Off"char status[3]; ... ctrl = fscanf(read_from, " %s", &status);

地址的更好的方法是不使用fscanf()。使用fgets()getline()閱讀行,然後使用掃描sscanf()strtol()

// Read line by line until EOF 
while (fgets(buf, sizeof buf, read_from)) { 
    // Clear entry 
    memset(&array[u], 0, sizeof (array[u])); 

    if (3 == sscanf(buf, "%d Off ch=1 n=%d v=%d", 
     &array[u][0], &array[u][2], &array[u][3])) { 
    array[u][1] = 1; 
    } else if (3 == sscanf(buf, "%d On ch=1 n=%d v=%d", 
     &array[u][0], &array[u][2], &array[u][3])) { 
    array[u][1] = 0; 
    } else if (2 == sscanf(buf, "%d Pb ch=1 v=%d", 
     &array[u][0], &array[u][3])) { 
    array[u][1] = 2; 
    } 

注:如ch=1很可能不是一個常數1,代碼可以使用"%*d"掃描並丟棄ch數。

if (3 == sscanf(buf, "%d Off ch=%*d n=%d v=%d", 
     &array[u][0], &array[u][2], &array[u][3])) { 
    array[u][1] = 1; 
    } 
+0

好吧,你寫的代碼有效,但是隻能在2387行的第2000行開始讀取文件。這是爲什麼發生? –

+0

@Febio Mosca肯定代碼在第一行開始_read_,但可能不會傳遞各種'sscanf()'測試,直到後面。建議在2000行之前和之後發佈一些行。還要確保足夠的緩衝區大小,如'char buffer [1000];'也發佈'array []'定義。 – chux

+0

對不起,實際上數組是完整的所有信息,它只是打印控制它的最後一部分。我不知道爲什麼,但我也不在乎,我只是需要將信息正確保存,並且確實如此,所以......非常感謝您的大力幫助! –

相關問題