C语言编程_常见的问题解决办法和案例(2022)

71 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情

介绍的C语言知识如下:宽字符定义使用、gtk图像框架安装与测试、动态数组定义、switch的...符号用法、windows下操作目录相关函数、可变形参的函数定义方式以及数据的提取办法,scanf函数在widows下vs里的使用问题、windows下system执行命令调用系统可执行文件运行。

一、Linux下C语言代码定义宽字符问题

用多个字节来代表的字符称之为宽字符。 宽字符是双字节多语言字符代码。在当今的全球计算业内使用的大多数字符(包括技术符号和特殊的发布字符),都可以根据 Unicode 规范表示为宽字符形式。无法以 1 个宽字符表示的字符可以通过 Unicode 的代理项功能以 Unicode 对表示。由于每个宽字符总是以固定的 16 位大小表示,因此使用宽字符可以简化使用国际字符集进行的编程。

#include <stdio.h>
#include <string.h>
#include <wchar.h>
int main(void)
{
	
	/*文本编辑器必须是在UTF-8编码下才可以正常编译*/
	char *p="1234567890中国"; //16
	char *p2="中国中国"; //12    UTF-8编码下一个中文3个字节
	
	wchar_t *wp=L"1234567890中国"; //12
	wchar_t *wp2=L"中国中国"; //4  
	
	printf("strlen p:%d\n",strlen(p));
	printf("strlen p2:%d\n",strlen(p2));
	
	printf("wcslen p:%d\n",wcslen(wp));    //返回值是12
	printf("wcslen p2:%d\n",wcslen(wp2));  //返回值是4
	return 0;
}

二、C语言动态数组定义示例(C99)

C99支持一种名为变长数组的结构来方便程序员。C++也提供了一种长度可在程序运行时确定的数组类型:动态数组。
声明格式为:(声明 int 类型的数组)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
	   
//ls /456/789/*
int main(int argc,char **argv)
{
	if(argc!=2)
	{
		printf("正确参数:./a.out <目录路径>\n");
		return 0;
	}
	/*1. 打开目录*/
	DIR *dir;
	struct dirent *dir_info;
	dir=opendir(argv[1]);
	if(dir==NULL)
	{
		printf("%s目录打开失败!\n",argv[1]);
		return 0;
	}
	/*2. 遍历目录*/
	while(dir_info=readdir(dir))
	{
		if(strcmp(dir_info->d_name,".")==0||strcmp(dir_info->d_name,"..")==0)
		{
			continue;
		}
		//1. 定义动态数组,存放完整路径
		char str[strlen(dir_info->d_name)+strlen(argv[1])+1];
		//2. 拷贝目录路径
		strcpy(str,argv[1]);
		//3. 拼接文件名称
		strcat(str,dir_info->d_name);
		//4. 执行正常程序
		printf("%s\n",str);
		/*..视频播放器(str)、音乐播放器、数码相册.......*/
	}
	/*3. 关闭目录*/
	closedir(dir);
	return 0;
}

三、switch多分支结构新特性(C99)

ANSI于1989年制定了C编程语言的官方标准,并于1990年成为国际标准,C语言规范在一段时间内保持相对静态,而C ++继续发展,主要是在其自身的标准化工作中。规范修正案1在1995年为C制定了一个新标准,但只是为了纠正1989年标准的一些细节,并为国际字符集增加了更广泛的支持。该标准在20世纪90年代后期进行了进一步修订,导致1999年出版了ISO / IEC 9899:1999,并于2000年5月作为ANSI标准采用。该标准版本定义的语言通常称为“ C99" 。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
	   
//ls /456/789/*
int main(int argc,char **argv)
{
	if(argc!=2)
	{
		printf("正确参数:./a.out <数字>\n");
		return 0;
	}
	int num=atoi(argv[1]);
	switch(num)
	{
		case 1 ... 5:
			printf("你输入的是1到5的范围数据!\n");
			break;
		case 10 ... 50:
			printf("你输入的是10到50的范围数据!\n");
			break;
		case 60 ... 80:
			printf("你输入的是60到80的范围数据!\n");
			break;
		case 'a' ... 'z':
			printf("你输入的是a到z的范围数据!\n");
			break;
		default:
			printf("范围不满足!\n");
			break;
	}
	return 0;
}

四、GTK库安装说明

在linux下想使用C语言做一个图形化的界面可以选择GTK。

1、安装gcc/g++/gdb/make 等基本编程工具

sudo apt-get install build-essential

2、安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件

sudo apt-get install gnome-core-devel

3、用于在编译GTK程序时自动找出头文件及库文件位置

sudo apt-get install pkg-config

4、安装 devhelp GTK文档查看程序

sudo apt-get install devhelp

5、安装 gtk/glib 的API参考手册及其它帮助文档

sudo apt-get install libglib2.0-doc libgtk2.0-doc

6、安装基于GTK的界面GTK是开发Gnome窗口的c/c++语言图形库

sudo apt-get install glade libglade2-dev

7、安装gtk2.0 或者 将gtk+2.0所需的所有文件统通下载安装完毕

sudo apt-get install libgtk2.0-dev

安装完毕后就可以开始写第一个简单的程序了!

五、windows下改变控制台

#include "stdio.h"
int main()
{
	//printf("\33[%dm",100);
	//printf("\33[x;yH");    //将输出坐标定位在第x行,第y列
	//printf("\33[%d;%dH",10,10);//将输出坐标定位在第x行,第y列
	//printf("\33[10;10H");
	printf("hello world!\n");
} 

/*
一、设置控制台
    1、更改屏幕的背景色,字体颜色
        printf("\33[%dm", i);
        30<= i <=37  设置字体颜色
        30黑,31红,32绿,33黄,34蓝,35紫,36深绿,3740<= i <=47  设置背景颜色
        40黑,41红,42绿,43黄,44蓝,45紫,46深绿,472、任意指定屏幕的输出坐标
        printf("\33[x;yH");  将输出坐标定位在第x行,第yprintf("\33[%d;%dH", x,y);  将输出坐标定位在第x行,第y列
*/

六、strchr字符串查找函数

#include "stdio.h"
#include "string.h"
int main()
{
	char buff1[]="123 456 789";
	char buff2[]="abc,uuu,oooo";
	printf("%s\n",strchr(buff1,' '));
	printf("%s\n",strchr(buff2,','));
	return 0;
}
/*
 *
 * #include <string.h>
 * char *strchr(const char *s, int c);
 *
 * */

七、windows下C语言操作目录

获得当前工作目录
char* _getcwd( char *buffer, int maxlen );

更改当前工作目录
int _chdir( const char *dirname );

文件遍历(查找)
long _findfirst( char *filespec, struct _finddata_t *fileinfo );

int _findclose( long handle );
关闭搜寻句柄并释放相应资源

创建目录
int _mkdir( const char *dirname );

删除目录
int _rmdir( const char *dirname );

其他操作
int _access( const char *path, int mode );

int _chdrive( int drive );
 功  能 : 更改当前工作驱动器


char* _getdcwd( int drive, char *buffer, int maxlen );
 功  能 : 获得指定驱动器的当前工作路径.

八、windows下调用应用程序

#include <windows.h>

system("notepad.exe");

九、short整型的scanf正确输入格式

#pragma warning(disable:4996)

#include <stdio.h>
#include <string.h>

struct stu
{
	short  grade;  //如果这里是短整型,scanf输入必须是%hd, 不能使用%d, %d是int类型,按照4个字节输入。会导致空间溢出到下面的name数组里.
	
	char name[21];
};

int main()
{
	struct stu STU = {11,"小米"};
	printf("结构体大小:%d\n",sizeof(struct stu));
	//STU.grade = 12; //年龄
	//memcpy(STU.name,"小明",5); //姓名

	printf("输入姓名:");
	scanf("%s", STU.name);

	printf("输入年龄:");
	scanf("%hd",&STU.grade);
	

	printf("年龄:%hd\n", STU.grade);
	printf("姓名:%s\n", STU.name);
	return 0;
}

十、C语言结构体位段

位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。

位段的定义格式为:  type  [var]: digits

其中type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数)。位段名称var是可选参数,即可以省略。digits表示该位段所占的二进制位数。
那么定义一个位段结构可以像下面这段代码去定义:

struct node
{
    unsigned int a:4;     //位段a,占4位
    unsigned int  :0;     //无名位段,占0位
    unsigned int b:4;     //位段b,占4位
    int c:32;             //位段c,占32位
    int  :6;              //无名位段,占6位
};

十一、C语言可变形参示例代码

(1)示例代码

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdarg.h>

void func(int a,...);
int main(int argc,char **argv)
{	
	//func(123,456,789,"8888");
	func(123);
	return 0;
}

//可变形参一般都是约定个数 或者根据第一个参数,决定个数
void func(int a,...)
{
	int b=0,c=0;
	char *p=NULL;
	va_list ap;
	va_start(ap,a);
	b=va_arg(ap,int);
	c=va_arg(ap,int);
	p=va_arg(ap,char*);
	printf("a=%d,b=%d,c=%d,p=%s\n",a,b,c,p);
	va_end(ap);
}

(2)示例代码

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdarg.h>
 
void foo(char *fmt, ...);
int main(int argc,char **argv)
{	
	foo("%d,%s,%f,%c\n",123,"456",789.123,'A');
	return 0;
}

void foo(char *fmt, ...)
{
   va_list ap;
   int d;
   char c, *s;
   double f;
   /*1. 初始化形参列表*/
   va_start(ap, fmt);
   while(*fmt)
    switch(*fmt++)
	{
	   case 's':              /* string */
		   s = va_arg(ap,char *);
		   printf("string %s\n", s);
		   break;
	   case 'd':              /* int */
		   d = va_arg(ap, int);
		   printf("int %d\n", d);
		   break;
	   case 'c':              /* char */
		   c = (char) va_arg(ap, int);
		   printf("char %c\n", c);
		   break;
	   case 'f':             /* char */
		   f = (char) va_arg(ap,double);
		   printf("double %f\n",f);
		   break;
   }
   /*释放参数列表,结束读取*/
   va_end(ap);
}