fread()中的空字符和c中的strncpy()

Tha*_*nos 0 c fread strncpy id3v2

我是一名新的程序员,现在我已经开始使用c了.我正在尝试解码IDEv3 mp3标签,我遇到了各种各样的问题.当我使用fread()和strncpy()命令时,我注意到两者都需要将\n字符作为结束参考点.(也许我错了,这只是观察)

当我打印输出时,它们产生一个不可读的字符.作为解决问题的解决方案我使用fread()4字节而不是3字节来生成(8)\n字符(整个字节),第二步我使用strncpy()和3字节分配给分配然后我用于打印的记忆.理论上,当我使用fread()时,我不应该遇到这个问题.

代码示例:

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

typedef struct{
  unsigned char header_id[3]; /* Unsigned character 3 Bytes (24 bits) */
}mp3_Header;

int main (int argc, char *argv[]) {

mp3_Header first;
unsigned char memory[4];

FILE *file = fopen( name.mp3 , "rb" );

if ( (size_t) fread( (void *) memory , (size_t) 4 , (size_t) 1 , (FILE *) file) !=1 ) {
  printf("Could not read the file\n");
  exit (0);
} /* End of if condition */

strncpy( (char *) first.header_id , (char *) memory , (size_t) 3);

printf ("This is the header_ID: %s\n", first.header_id);

fclose(file);

} /* End of main */
return 0;
Run Code Online (Sandbox Code Playgroud)

Gun*_*ica 5

使用'\n'终止字符串的观察结果不正确.C中的字符串需要以0字节(\ 0)结束.但是,一些函数如fgets(),它们应该从文件读取行,将行尾的\n作为终止符.

您的代码的问题是fread()就绪二进制数据,并且不会尝试将该数据解释为字符串,这意味着它不会将\ 0放在最后.但是字符串函数strcpy需要这个0字节来识别字符串的结尾.strncpy复制\ 0后也会停止,但它不会在接收字符串中放入更多字节以防止缓冲区溢出.所以它会复制你的3个字节,但它不会将\ 0放到字符串的末尾,就像字符串短于length参数一样.

所以你应该做的是用一个MORE元素声明header_id,你实际需要的是什么,在strcpy之后,将这个额外的元素设置为\ 0.像这样:

strncpy( first.header_id , memory , 3);
first.header_id[3] = '\0';
Run Code Online (Sandbox Code Playgroud)

请记住,3个头字节将转到数组元素0..2,因此元素3需要终结符.当然,你需要声明header_id [4]以获得额外\ 0的空间.

另请注意,我省略了类型转换 - 如果您的类型无论如何都不需要它们.将数组传递给函数无论如何都会将指针传递给第一个元素,因此不需要将数组header_id强制转换为指针strncpy( (char *) first.header_id , (char *) memory , (size_t) 3);.