C语言实用小技巧合集(持续更新)

1、几个常用的宏

#include <stdio.h> 

void main(void)
{
	printf("The file is %s.\n", __FILE__);  //打印文件名(包含路径)
	printf("The date is %s.\n", __DATE__);  //打印当前日期
	printf("The time is %s.\n", __TIME__);  //打印当前时间
	printf("This is line %d.\n", __LINE__);  //打印当前行号
	printf("This function is %s.\n", __FUNCTION__);//打印当前函数 

	system("pause");
}

这几个宏都是编译器自带的,可直接使用


2、perror函数

C 库函数 void perror(const char *str) 把一个描述性错误消息输出到标准错误 stderr。首先输出字符串 str,后跟一个冒号,然后是一个空格。常用于打开文件时的错误提示

#include <stdio.h>

int main ()
{
   FILE *fp;

   /* 首先重命名文件 */
   rename("file.txt", "newfile.txt");

   /* 现在让我们尝试打开相同的文件 */
   fp = fopen("file.txt", "r");
   if( fp == NULL ) {
      perror("Error: ");
      return(-1);
   }
   fclose(fp);
      
   return(0);
}

输出结果:

                Error: : No such file or directory


3、#define技巧

"#"用来把参数转换成字符串,是给参数加上双引号。

"##"则用来连接前后两个参数,把它们变成一个参数,

"#@"是给参数加上单引号,将参数字符化

#define CAT(x,y) x##y       /* CAT(1,"abc") => "1abc" */

#define TOCHAR(a) #@a       /* TOCHAR(1) => '1' */

#define TOSTRING(x) #x      /* TOSTRING(1) => "1" */

此条转自:C #define中的 "\,#,## #@"_#define加斜杠-CSDN博客


4、标准输出

printf可以输出固定长度的数据,使得输出的数据规范美观

对于fprintf也同样适用,保存数据也规范

printf("this is :%10d\n", 10);    //输出数字占十位宽,右对齐

printf("this is :%-10d\n", 10);   //输出数字占十位宽,左对齐

‘\n’是换行输出

'\r'在本行覆盖输出,若上次输出比本次长则会保留部分上次的输出信息


5、内存开辟

     当需要处理的数据量较大时,平时常用的数组已经不能满足要求。因为数组使用的内存空间是栈(stack),它的空间有限,直接使用普通的方式定义大数组会导致溢出。这时候需要人为开辟内存空间,人为开辟的内存空间位于堆区,它能够满足数据量较大时的计算任务

     人为开辟内存空间需要使用malloc函数,如下所示开辟了一段长度为length的char型内存空间:


char *p=NULL;

p = malloc(length*sizeof(char));

    需要注意的是malloc函数开辟的内存空间并不会对这块内存进行初始化,该内存的数据还是程序上一次使用这段内存是的数据。

    实际使用时我们往往需要将内存初始化为0,这时我们可以使用calloc函数,calloc函数和malloc函数的参数传递稍微有点区别:


char *p=NULL;

p = malloc(length,sizeof(char));

    calloc函数有两个参数,分别是最小内存单元的数量和最小内存单元的大小

    要使用calloc函数需要包含头文件

#include <malloc.h>

最后 需要重点注意的是不管是malloc还是calloc函数,在程序结束之前必须进行内存释放

free(p);

6、文件读取

为题描述:需要从一个二进制文件中读取整形数据,每个整形数据的长度是两个字节,数据量很大

    一开始想到的是使用fscanf函数,从文件中直接格式化输入整形数据 如下

int temp;
fscanf(fp,"%d",temp);

    这种读取方式最后读取出来的是乱码,因为%d格式是读取整形数据的,而文件中的数据严格来说是短整型的,然而也没有格式化读入短整型的方式,所以得另想办法

    最后想到使用fread函数读取两个字节长的内存,然后再借用一个短整型变量做中转,再进行后续处理。并且这个中转变量也必须是short类型的,如果这个变量是int类型的,最后读出来的数据也是乱码

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread 函数从 stream 所标示的文件中读取数据, 一块是 size 个字节, 共 nmemb 块, 存放到 ptr 指向的内存里

返回实际读到的块数

FILE *fp;
short temp;
fp = fopen("45000_mod.dat", "rb");
if (fp == NULL)
	printf("Can't open this file");
fseek(fp, 8150000 * 2, 0);//去掉前面无用的信号
for (i = 0; i < DAT_LEN; i++)
{
	fread(&temp, 2, 1, fp);
	data[i].real = (double)(temp);
}
fclose(fp);

7、free问题

#include <stdio.h>
#include <malloc.h>

#define FILELEN 10240

typedef struct _Complex_f_ {
	float real;
	float imag;
}Complex_f;

void main(void)
{
	Complex_f *data[10];
	
	data[0] = malloc(sizeof(Complex_f)*FILELEN);

	FILE *fp;
	fopen_s(&fp, "signal.bin", "rb");

	for (int i = 0; i < FILELEN; i++)
		fread(data[0]+i, sizeof(Complex_f), 1, fp);
	fclose(fp);

	fopen_s(&fp, "outdat.bin", "wb");
	for (int i = 0; i < FILELEN; i++)
		fwrite(data[0] + i, sizeof(Complex_f), 1, fp);
	fclose(fp);


	free(data[0]);//!!!
	getchar();
}

Complex_f *data[10];

使用这种方式定义的指针常用于保存名字等用途,在使用malloc为data分配内存的时候需要一次为data[i]分配内存

释放内存的时候也要依次释放data[i]


8、Expression: (stream != NILL)错误

Expression: (stream != NILL)错误基本都是由文件操作错误引起的,像fopen(),fread(),fprintf()等地方需要重点检查,还有就是fopen的打开方式,比如说需要读文件时候用的是wb方式而写文件用的是rb方式,这也能引发这个错误

这个错误也出现在文件夹不存在的时候,比如要往这个路径写数据时

sprintf_s(name, 100, "..\\signal\\allFrames\\%s_%03d.dat", type[i],aa[i]);

signal文件夹已经存在,但是allFrames文件夹并不存在,这样就会产生这个错误


9、#error和#warning

#error编译指示字用于生成一个编译错误消息,并让预编译器停止编译。

用法:#error Message  (Message不需要用双引号引起来)

#warning编译指示字用于生成一个编译警告,输出到编译器的消息窗口,当编译器不会停止编译。
用法:#warning Message   (Message不需要用双引号引起来)

以上两种编译提示信息通常与#if,#ifdef等配合使用

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值