2015-06-10 195 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

对不起,实际上数组是完整的所有信息,它只是打印控制它的最后一部分。我不知道为什么,但我也不在乎,我只是需要将信息正确保存,并且确实如此,所以......非常感谢您的大力帮助! –

相关问题