Question: char buf_cns[] = "早上好";

引用 14 楼 dbzhang800 的回复:[quote=引用 11 楼 r_Jimy 的回复:] 在编译的时候，char buf_cns[] = "早上好" 其实是被解释为char buf_cns[] = "XX XX XX XX"; 这些打X的东东就二进制字节，是在编译前决定好了的  这个理解真的不对。可以看看我前面给出的blog [/quote]  感谢指出，你的BLOG写得很好，顶下 执行字符集的提出，增加了问题的复杂性，UTF-8方案很好

引用 2 楼 oldmtn 的回复:[quote=引用 1 楼 truelance 的回复:] 定义了一个数组，大小是"早上好"这个字符串的长度(包含结尾的\0), 然后对这个数组初始化，把字符串的内容填进去。 如果是全局变量，那么是编译器做的这些工作。 如果是局部变量，那么是在运行期执行执行操作。  但为什么当我页面编码为unicode和Ascii的时候出现不同的结果呢？[/quote]因为这时候 "早上好" 是不同的字符串 所以结果不一样

书名：<Windows程序设计> 第2章Unicode简介

引用 11 楼 r_Jimy 的回复:在编译的时候，char buf_cns[] = "早上好" 其实是被解释为char buf_cns[] = "XX XX XX XX"; 这些打X的东东就二进制字节，是在编译前决定好了的  这个理解真的不对。可以看看我前面给出的blog

我写过一篇blog，专门介绍这个问题。  http://blog.csdn.net/dbzhang800/article/details/7540905  注意：里面提到的是C++，不过对C完全适用。

引用 7 楼 edward_bian 的回复:从C规范讲，这样的写法是undefined的 如果不谈中文符号，这句话定义了一个字符串数组，并且在常量区有一个“早上好”的拷贝 这个写法应该是没有问题的吧。

看一下内存是什么不就知道了么。

手上没有VS2010的环境，用DEV C++测试了下，          对于char buf_cns[] = "早上好"，系统在编译时，不论定义成全局变量，静态变量还是局部变量，“早上好”这几个初始化用的 数据都放在目标同一段位置，也就是说，如果按这种方式分别初始化全局变量，静态变量，局部变量，这些用于初始化的数据的 物理地址是在连续的区域的（实际可能会有一点点间隔）          当然程序执行时，全局变量和静态变量是常驻在内存全局数据区的，局部变量在函数被调用时加载到内存分配给该函数的栈 空间的。全局变量和静态变量是在程序开始执行时，就随程序从物理地址一并加载到内存，局部变量是其所在函数运行时才加 载，运行完了这块空间也就释放了，但正常情况不影响这些参数所在物理空间，除非代码非法修改物理空间的这些初始化数据的 区域。                有趣的是，如果初始化时，指定大小，比如如下初始化：        char buff[200] = {0xa 0xb};        这时，如果buff是全局或静态，它的物理存放位置不变，你会发现整个目标文件随着buff的增大而增大，但如果定义成局部 变量，这时，buff的位置就跑到代码那一块去了，此时，再加大buff，对整个目标文件的影响不大，只有加大初始化的内容，目 标文件才会加大。

引用 10 楼 zhao4zhong1 的回复:对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A 顶！ 源文件写好后，假设使用的是编译器未知编码的A编码写的，编译是绝对通不过的 假设使用的是编译器认可的编译一，在编译的时候，char buf_cns[] = "早上好" 其实是被解释为char buf_cns[] = "XX XX XX XX"; 这些打X的东东就二进制字节，是在编译前决定好了的

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 4 楼 oldmtn 的回复:[quote=引用 3 楼 FightForProgrammer 的回复:] 这个是字符编码的问题，不同字符集表示当然不一样 就是这个问题啊  加入当前VS2010使用UNICODE，或者GB183030,或者JIS50220的情况下。 会出现什么结果呢？[/quote] 看编译实现了。 有两种可以能： 1 "早上好"的编码和源码的编码一致， 那么编码不同时， "早上好"的值和长度可能不同。  2. 编译器可能将源码中"早上好"转码为一个内部编码（比如ansi). 这种情况， "早上好"的值和长度都一样。  自己试试就知道了。

引用 3 楼 FightForProgrammer 的回复:这个是字符编码的问题，不同字符集表示当然不一样 就是这个问题啊  加入当前VS2010使用UNICODE，或者GB183030,或者JIS50220的情况下。 会出现什么结果呢？

这个是字符编码的问题，不同字符集表示当然不一样

引用 1 楼 truelance 的回复:定义了一个数组，大小是"早上好"这个字符串的长度(包含结尾的\0), 然后对这个数组初始化，把字符串的内容填进去。 如果是全局变量，那么是编译器做的这些工作。 如果是局部变量，那么是在运行期执行执行操作。  但为什么当我页面编码为unicode和Ascii的时候出现不同的结果呢？


Question: 对于一个文本文件（包含中英文、全角、半角标点符号），请将其分为两栏（用空格分隔）重新保存。

你打开文件，按行读数据 对每一行数据，从头到尾遍历，发现空格时就停止，把前面的部分输出的文件1中，后面部分加上\n。后面的部分输出的文件2中。空格不要，就OK了

对于这样的提问，只能呵呵了


Question: 求一个JNI c调用java的demo，java使用可第三方jar库的。

引用 2 楼 wgmhj328 的回复:网上找找一大把。我最近正做这方面的项目 调用顺序为 JAVA ->JNI->C 第三库并没有什么，将JAVA编译成jar包，这个再由其他程序调 即其他java程序->jar包->JNI->C  我做了个试验。你看下哪里有问题？    /**    * File Name : add.java public class add { 	public static int myAdd(int a, int b){ 		return a + b; 	} }     /**    * File Name : show.java   */   public class show { 	 	@SuppressWarnings("static-access") 	public static void myShow()throws Exception{ 		add padd = new add(); 		int result = padd.myAdd(3, 4); 		System.out.print(result); 	} }  分别打成 jar 包   /**    * File Name : test.c   */  #include <jni.h> #include <stdio.h>   int main(int argc, char * * argv) {     JavaVM * jvm = (JavaVM *)0;     JNIEnv * env = (JNIEnv *)0;       jclass cls;     jmethodID mid;          JavaVMInitArgs vm_args;            JavaVMOption options[1];              options[0].optionString = "-Djava.class.path = -classpath ./show.jar;./add.jar";             vm_args.version = JNI_VERSION_1_6;      vm_args.nOptions = 1;     vm_args.options = options;     vm_args.ignoreUnrecognized = JNI_FALSE;      if(  JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args)  != JNI_OK )     {         printf("create JVM error!\n");         return ;     }      cls = (*env)->FindClass(env, "show");     if(cls == 0)     {         printf("find class failed!\n");         return ;     }       mid = (*env)->GetStaticMethodID(env, cls, "myShow", "()V");     if(mid != 0)     {         printf("find method [myShow] !\n");                          (*env)->CallStaticObjectMethod(env, cls, mid);     }      if(jvm)     {         (*jvm)->DestroyJavaVM(jvm);     } }    root@wx:/home/jni_wx# ls add.jar  make.sh    show.jar  test  test.c    root@wx:/home/jni_wx# ./test  find class failed!    是这个参数 options[0].optionString = "-Djava.class.path = -classpath ./show.jar;./add.jar";    有问题吗？

java使用了第三方jar库的。

实际中会把jni 和c编译成库，即测试程序->jar包->c库


Question: 这个怎么计算天数？！！！我一点不会

太长了

参考一下

没明白在干啥！！

仅供参考#include <afxdisp.h> #include <stdio.h> #include <stdlib.h> int main(int argc, TCHAR* argv[]) {     COleDateTime t;     COleDateTimeSpan ts;     CString s,fmt;     int nYear;     int nMonth;     int nDay;     int nHour;     int nMin;     int nSec;     int lDays;     int nHours;     int nMins;     int nSecs;     int i,N;     // initialize MFC and print and error on failure     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {         printf("Fatal Error: MFC initialization failed\n");         return 1;     }     if (argc<13) {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 2;     }     if (stricmp(argv[12],"SQL")==0) fmt="%Y-%m-%d %H:%M:%S";     else if (stricmp(argv[12],"YYYY")==0) fmt="%Y%m%d %H%M%S";     else if (stricmp(argv[12],"YY")==0) fmt="%y%m%d %H%M%S";     else {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 3;     }     nYear =atoi(argv[ 1]);     nMonth=atoi(argv[ 2]);     nDay  =atoi(argv[ 3]);     nHour =atoi(argv[ 4]);     nMin  =atoi(argv[ 5]);     nSec  =atoi(argv[ 6]);     lDays =atoi(argv[ 7]);     nHours=atoi(argv[ 8]);     nMins =atoi(argv[ 9]);     nSecs =atoi(argv[10]);     N     =atoi(argv[11]);     if (N<=0) {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 4;     }     t=COleDateTime( nYear, nMonth, nDay, nHour, nMin, nSec);     ts=COleDateTimeSpan( lDays, nHours, nMins, nSecs );     for (i=1;i<=N;i++) {         s=t.Format(fmt);         printf("%08d %s\n",i,s);         t=t+ts;     }     return 0; }


Question: 学c语言不久，遇到一道题，求解。

明白了，谢谢各位的解答

只有做函数的参数时，数组名才和指针等价。泛泛的讲数组名可以做指针用的书都可以烧掉了

引用 3 楼 lian_d 的回复:数组名不是可以当做指针用的吗？ 数组名和指针不是一回事。 某些情况下，数组名可以转换成指针，但不是所有情况都可以。

数组名不是可以当做指针用的吗？

char str[100]; strcpy(str, "Hello!");  // 调用库函数把"Hello!"复制给str

char *str;   str="Hello!"; // str是个指针，指针可以这样赋值 char str[];  str="Hello!"; // str是个数组，数组不能这样赋值，或者像书上说的，数组名不能作为左值 char str[] = "Hello!"; // 这个可以，初始化


Question: 每一个scanf后面都要加一个getchar来吸收换行符吗？

程序碰到scanf函数时，不是直接要用户输入！而是先看缓冲区里面有没有东西，有的话，就读取一个字符出来(空格，换行，这些不可见的都属于被读取之列)。 所以如果你使用scanf("%c",&X), 那么，第一次X确实就是你输入的字符，但如果你的程序结构如下： scanf("%c",&X) while {   scanf("%c",&X); } 对于这种情况，那么你需要注意了，第二个scanf，直接从你上次输入的缓冲去读X的下一个字符(有可能是回车，如果你输入了一串的话，那就是第二个字符)。所以这时候，你只需要在第二个scanf后面加一句 if(X=='\n') scanf("%c",&X)，即程序结构改为： scanf("%c",&X) while {   scanf("%c",&X);   if(X=='\n') scanf("%c",&X); }  这样就基本满足你的程序需要了。 因为我们知道了scanf("%c"... 从缓冲区读数据的原理,所以变成的时候，刻意的把不需要的不可见字符去掉就可以，不管是换行还是空格之类的。。。

引用 1 楼 zhao4zhong1 的回复:永远不要scanf("%c",...即可。为什么啊 老师

某些情况不需要

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

永远不要scanf("%c",...即可。


Question: 有一个长度不大于40的字符串，已知其中共包含两个字符“A”，求处于两个字符“A”中间的字符个数，及这些字符

2楼代码声明变量不在函数开头，也就这算C++吧。

全贴中我都没看到哪句是C++

以C++的方法来写，完全看不懂。我只是个学C语言的学生。。。。。java都学不好

谁让我最近很无聊呢？ #include <stdio.h> #include <stdlib.h> char a[40],b[40];int n=0; //1.定义字符数组a[40],b[40]，计数器n=0; /*用户自定义函数 */ void myfun() {     int i;      for (i=0;i<40;i++) if (a[i]=='A') break; //3.定位第一个字符’A’的位置;     if (i>=40) {printf("error1\n");exit(1);}     i++;     while (1) { //4.从’A’的后一个字符开始为字符数组b赋值,同时计数器加一，直到遇到第二个字符’A’;         if (a[i]=='A') break;         if (a[i]=='\n') {printf("error2\n");exit(2);}         b[n]=a[i];         n++;         i++;     }     b[n]=0; //5.修正字符数组b； } int main() {     fgets(a,40,stdin); //2.接收字符数组a；     myfun();     printf("b:[%s],n:%d\n",b,n); //6.输出字符数组b和计数器n。     return 0; } //123A456A789 //b:[456],n:3 //

闲着没事，给你写了一个，仅供参考。 int fun(char * src ,char * des) { 	int num = 0; 	if (src == NULL || des == NULL) 	{ 		return 0; 	} 	char *pStart = src; 	char *pEnd = src; 	bool bFlag = false; 	while (*pEnd != '\0')  	{ 		if (bFlag) 		{ 			if (*pEnd != 'A') 			{ 				num++; 				pEnd++; 			} 			else 			{ 				break; 			} 		} 		else 		{  			if (*pStart == 'A') 			{ 				bFlag = true; 				pStart++; 				pEnd = pStart; 				continue; 			} 			else 				pStart++; 		} 	} 	strncpy(des ,pStart ,num); 	return num; }  int main(int argc, _TCHAR* argv[]) { 	char src[40] = {0}; 	char des[40] = {0};  	scanf("%s" ,src); 	int n = fun(src ,des); 	printf("%s ,%d\n" ,des ,n); 	return 0; }

这么明确要求，很容易实现啊


Question: 《C和指针》一书中第6章查找指针数组里字符的程序是不是有问题

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

printf("%d",find_char(vp,'f', sizeof(vp)/sizeof(vp[0])));  int find_char(char **strings,int value, int size ) {     char *string;     int i;     for (i = 0; i < size; i++)     {         string = strings[i];

改成这样可以解决  char *vp[]={"ab","cd","ef", NULL }; 更好的办法是给find_char加个参数，表示指针数组的大小

确实有问题 while ((string=*strings++)!=NULL)  // 这个结束条件不对。 循环的过程是string依次为vp[0]，vp[1]，vp[2]，vp[3]，但是这个vp[3]越界了，是不是NULL就不一定了


Question: strcpy_s ,strcat_s 微软提出的所谓的CRT安全函数有没有MAC版本 或 Linux版本？ 有没有人实现过？

引用 楼主 mcf330 的回复:strcpy_s ,strcat_s 微软提出的所谓的CRT安全函数有没有MAC版本 或 Linux版本？ 有没有人实现过？ 尽量不要让函数来做一些隐藏工作，因为你是C程序员。 在我看来 名符其实的字符串就用str族函数，不是就用mem系列。

楼上所言极是。安全版本并不见得就一定安全，碰上烂水平的程序员，安全版本也没用。如果你自己足够的熟练，普通的函数就能满足要求了。这些带 _s 的版本应该是只有 MSVC 有的，其他的编译期不一定提供。

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\strcpy_s.c /*** *strcpy_s.c - contains strcpy_s() * *   Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *   strcpy_s() copies one string onto another. * *******************************************************************************/  #include <string.h> #include <internal_securecrt.h>  #define _FUNC_PROLOGUE #define _FUNC_NAME strcpy_s #define _CHAR char #define _DEST _Dst #define _SIZE _SizeInBytes #define _SRC _Src  #include <tcscpy_s.inl>  C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\tcscpy_s.inl /*** *tcscpy_s.inl - general implementation of _tcscpy_s * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       This file contains the general algorithm for strcpy_s and its variants. * ****/  _FUNC_PROLOGUE errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC) {     _CHAR *p;     size_t available;      /* validation section */     _VALIDATE_STRING(_DEST, _SIZE);     _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);      p = _DEST;     available = _SIZE;     while ((*p++ = *_SRC++) != 0 && --available > 0)     {     }      if (available == 0)     {         _RESET_STRING(_DEST, _SIZE);         _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE);     }     _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1);     _RETURN_NO_ERROR; }   C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\strcat_s.c /*** *strcat_s.c - contains strcat_s() * *   Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *   strcat_s() concatenates (appends) a copy of the source string to the *   end of the destination string. * *******************************************************************************/  #include <string.h> #include <internal_securecrt.h>  #define _FUNC_PROLOGUE #define _FUNC_NAME strcat_s #define _CHAR char #define _DEST _Dst #define _SIZE _SizeInBytes #define _SRC _Src  #include <tcscat_s.inl>  C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\tcscat_s.inl/*** *tcscat_s.inl - general implementation of _tcscpy_s * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       This file contains the general algorithm for strcat_s and its variants. * ****/  _FUNC_PROLOGUE errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC) {     _CHAR *p;     size_t available;      /* validation section */     _VALIDATE_STRING(_DEST, _SIZE);     _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);      p = _DEST;     available = _SIZE;     while (available > 0 && *p != 0)     {         p++;         available--;     }      if (available == 0)     {         _RESET_STRING(_DEST, _SIZE);         _RETURN_DEST_NOT_NULL_TERMINATED(_DEST, _SIZE);     }      while ((*p++ = *_SRC++) != 0 && --available > 0)     {     }      if (available == 0)     {         _RESET_STRING(_DEST, _SIZE);         _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE);     }     _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1);     _RETURN_NO_ERROR; }

linux下有strncpy 不能过于依赖这些函数，还是要自己把长度算清楚才好，否则程序执行结果就不是你想要的


Question: 函数指针

恰恰相反，函数调用只作用于函数指针。f()将f先转为指针再调用，等于(&f)()。pf()直接调用，(*pf)()纯属多余。

这些概念在数学中有提到： 可以写出y=f(x)的叫显示解  只能写出f(x,y)=C的叫隐式解

我的意思是说对于函数指针指针调用函数是用p()函数指针直接调用函数的时候，编译器会不会自动加上*进行隐式解引用

不知道LZ想问什么 除sizeof、_Alignof和&作用下，函数名自动转换为函数指针


Question: C语言中关于“统计数”的函数

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

fopen之后一定要检查他的返回值是不是NULL

fscanf是读取文件，为什么要等你输入呢？


Question: 为什么printf不能输出多个字符串

# include <stdio.h>  int main(void) { 	char c;     scanf("%c",&c); 	while(c!='#') 	{ 		if(c>='a'&&c<='z') 		{ 			c-=32; 		} 		else if(c>='A'&&c<='Z') 		{ 			c+=32; 		} 		printf("%c",c); 		scanf("%c",&c);//不加这个， c只是个字符，你输入字符串当然不行了 ,这样是循环输入一个个字符  	} 	 	return 0; //最好加上这个  }

引用 3 楼 fzx6393 的回复:[quote=引用 1 楼 user-2 的回复:]    scanf("%c",&c);  while(c!='#')  -->     while( scanf("%c",&c) == 1 && c !='#')   while( scanf("%c",&c) == 1 && c !='#')[/code][/quote]这句话输出结果不对[/quote] http://ideone.com/2yilRg

引用 1 楼 user-2 的回复:   scanf("%c",&c);  while(c!='#')  -->     while( scanf("%c",&c) == 1 && c !='#')   while( scanf("%c",&c) == 1 && c !='#')[/code][/quote]这句话输出结果不对

while( scanf("%c",&c) == 1 && c !='#') 这句话 输入


Question: C语言点滴程序3-8问题，求解

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

初学者最好不要使用具有联想功能的IDE，使用editplus或者sublime text都是很好的选择

因为对内存数据，不同的数据类型解释不同。 我用的Codeblocks

噢噢，知道了。为什么上面的i用 f %输出就会成了这结果. PS：你用的是什么编程软件？

#include<stdio.h>  int main () {     int i=123456789;     float f=123456789.0f;     f+=20;     printf("%f\n",f);     f=(float)i;     printf("%f\n",f); }

你的程序打错了，printf应该输出f


Question: 线性表的基本操作

仅供参考//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

DelList(L,h,e); // 这个e是个未经初始化的野指针，在DelList里面直接给*e赋值是要出问题的。 而且我没看懂DelList里面这一行是干什么的*e=L->elem[i-1]; 直接改成DelList(SeqList *L,int i)不就很好吗，多个参数是什么作用呢？

不是的，删除的是上一个被调函数找到的位置

这边删除的是第0个数据？ int DelList(SeqList *L,int i,ElemType *e)//删除指定的数据 {  int k;     *e=L->elem[i-1];  //如果i等于0的话，对数据取下标-1 越界了 for(k=i;k<=L->last;k++)    L->elem[k-1]=L->elem[k];    L->last--;    return OK; }


Question: malloc and realloc

引用 6 楼 baijiaheizhiganmao 的回复:动态存储空间分配在堆中进行，一般使用三个函数：  malloc：分配制定字节数的存储区，此存储区中的初始值不确定；  calloc：为指定数量指定长度的对象分配存储空间，该空间中的每一位都初始化为0  realloc:增加或减少以前分配存储区的长度，旧的内容会复制到新的存储区，新存储区增加的部分初始值未指定。  void *mallco(size_t size);  void *calloc (size_t nobj,size_t size);  void *realloc(void *ptr,size_t newsize); 你malloc之后，p的值是未定义的，和具体的实现有关（平台和编译环境）。

realloc根本不是你这么用嘀——！参考下面： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; }

//	for(int i=0;i<20;i++) //	{ //	*(p+i) = i; //	} 应该是这段语句会赋值 sizeof(int)*20大小的字节空间，有可能会覆盖掉 p指针一些数据头之类的部分，导致后续realloc失败。

感谢楼上的，可是为什么会输入0呢，为什么realloc分配不成功?

你分配的空间不够，所以那个循环是有问题的int *p = (int*)malloc(sizeof(int) * 20);还有realloc出来的起始地址不一定就是上面malloc分配出来的起始地址……这两个地址没有太大关联！

初始化的问题？


Question: 调用字符串型子函数返回值开头有乱码,求解决

#include<time.h> #include<stdio.h> char *timerec() {     static char tt[15];     time_t rawtime;     struct tm *timeinfo;      time(&rawtime);     timeinfo=localtime(&rawtime);     sprintf(tt,   "%4d",   1900+timeinfo->tm_year);     sprintf(tt,"%s%02d",tt,   1+timeinfo->tm_mon );     sprintf(tt,"%s%02d",tt,     timeinfo->tm_mday);     sprintf(tt,"%s%02d",tt,     timeinfo->tm_hour);     sprintf(tt,"%s%02d",tt,     timeinfo->tm_min );     return tt; } int main() {     char *s;     s=timerec();     printf("%s\n",s);     return 0; }

#include<time.h> #include<stdio.h> #include<string.h> char *timerec() {     static char tt[15];     time_t rawtime;     struct tm *timeinfo;      time(&rawtime);     timeinfo=localtime(&rawtime);     sprintf(tt,   "%4d",   1900+timeinfo->tm_year);     sprintf(tt,"%s%02d",tt,   1+timeinfo->tm_mon );     sprintf(tt,"%s%02d",tt,     timeinfo->tm_mday);     sprintf(tt,"%s%02d",tt,     timeinfo->tm_hour);     sprintf(tt,"%s%02d",tt,     timeinfo->tm_min );     return tt; } int main() {     char *s;     s=timerec();     printf("%s\n",s);     return 0; }

传二级指针和返回指针并无实质区别。如果要解决问题，按楼上的，用 static 限定，或者内部分配内存，外部释放。

额，其实这个题不需要传人二级指针，一个指针就可以的……

//返回堆指针 #include<memory.h> #include<stdlib.h> #include<time.h> #include<stdio.h> #include<string.h>  char *timerec() { 	char y[5],mon[3],d[3],h[3],mins[3],tt[15]; 	char *temp = (char* ) malloc(sizeof(char) * 15); 	 	time_t rawtime; 	struct tm *timeinfo; 	time(&rawtime); 	timeinfo=localtime(&rawtime); 	sprintf(y,"%4d",1900+timeinfo->tm_year); 	sprintf(mon,"%02d",1+timeinfo->tm_mon); 	sprintf(d,"%02d",timeinfo->tm_mday); 	sprintf(h,"%02d",timeinfo->tm_hour); 	sprintf(mins,"%02d",timeinfo->tm_min); 	strcpy(tt,y); 	strcat(tt,mon); 	strcat(tt,d); 	strcat(tt,h); 	strcat(tt,mins); 	strcat(tt,"\0"); 	memcpy(temp, tt,15); 	//temp=tt;//到这里为止用printf检查还都是正确的 	return temp; }  main() {     char *s;     s=timerec();//传下来就是乱码     printf("%s\n",s);     free(s);     s = NULL;     getchar(); }  //传入二级指针 #include<memory.h> #include<stdlib.h> #include<time.h> #include<stdio.h> #include<string.h>  void timerec(char** nowtime) { 	char y[5],mon[3],d[3],h[3],mins[3],tt[15]; 	//char *temp = new char[15]; 	time_t rawtime; 	struct tm *timeinfo; 	time(&rawtime); 	timeinfo=localtime(&rawtime); 	sprintf(y,"%4d",1900+timeinfo->tm_year); 	sprintf(mon,"%02d",1+timeinfo->tm_mon); 	sprintf(d,"%02d",timeinfo->tm_mday); 	sprintf(h,"%02d",timeinfo->tm_hour); 	sprintf(mins,"%02d",timeinfo->tm_min); 	strcpy(tt,y); 	strcat(tt,mon); 	strcat(tt,d); 	strcat(tt,h); 	strcat(tt,mins); 	strcat(tt,"\0"); 	memcpy(*nowtime, tt,15); 	//temp=tt;//到这里为止用printf检查还都是正确的 	//return temp; }  main() {     char *s = (char*)malloc(sizeof(char) * 15);     //s=timerec();//传下来就是乱码     timerec(&s);     printf("%s\n",s);  	free(s);      s = NULL;     getchar(); }

我现在改成这样,干脆输出<null>了 void timerec(char **s) { char y[5],mon[3],d[3],h[3],mins[3],tt[15]; char *pt; time_t rawtime; struct tm *timeinfo; time(&rawtime); timeinfo=localtime(&rawtime); sprintf(y,"%4d",1900+timeinfo->tm_year); sprintf(mon,"%02d",1+timeinfo->tm_mon); sprintf(d,"%02d",timeinfo->tm_mday); sprintf(h,"%02d",timeinfo->tm_hour); sprintf(mins,"%02d",timeinfo->tm_min); strcpy(tt,y); strcat(tt,mon); strcat(tt,d); strcat(tt,h); strcat(tt,mins); pt=tt;printf("%s",pt); s=&pt;printf("%s",*s); }  main() {     char *s;     timerec(&s);     printf("%s",*s); }

看不懂呢,2级指针返回的也出错了

引用 2 楼 bastamon 的回复:传入2j指针前面看懂了,但是销毁是什么意思 额，你可以在函数里new出一个指针，并且返回这个指针……完成后就记得销毁你new出来的这个指针……new/delete  malloc/free

传入2j指针前面看懂了,但是销毁是什么意思

不要试图去返回局部变量的指针，因为跳出函数，这个栈也没有了，所以返回指针肯定是有问题的，你可以传入指针的指针也就是所谓的二级指针，或者返回new出来的指针，记得销毁……


Question: 用c语言写出程序

仅供参考//运用C语言开发一个“小学生算术四则运算测试系统”。该系统是让计算机充当一位给小学生布置作业的算术老师，为学生出题并阅卷。该系统要求实现下列功能： //①为小学生出题（分别进行+、-、*、/等不同运算）。 //②学生做题后，进行评阅。学生每做一题后，评阅给出“答题正确，很好”或“答题错误，重做”等信息。 //③加、减、乘、除运算功能可以自由选择实现。 //④运算数值可控制在两位数的四则运算范围内。 #include <stdio.h> #include <stdlib.h> #include <time.h> int c,a,b,r,ri; void main() {     srand( (unsigned)time( NULL ) );     system("cls");     printf("小学生算术四则运算测试系统\n");     while (1) {         printf("1加法 2减法 3乘法 4除法 0退出:");fflush(stdout);         rewind(stdin);         scanf("%d",&c);         if (0==c) break;         switch (c) {         case 1:             a=rand()%100;             b=rand()%100;             r=a+b;             while (1) {                 printf("%d+%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 2:             a=1+rand()%99;             b=rand()%a;             r=a-b;             while (1) {                 printf("%d-%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 3:             a=rand()%99;             b=rand()%99;             r=a*b;             while (1) {                 printf("%d*%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 4:             a=2+rand()%998;             b=1+rand()%(a/2);             while (1) {                 if (0==a%b) break;                 b--;             }             r=a/b;             while (1) {                 printf("%d/%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         }     } }

这种活，就是费时间，自己写吧！

其实这种问题的难度不大，就是麻烦而已，说白了就是体力活。。。

好写是好写 就是麻烦点  30分够呛 30元肯定有。。。

自己慢慢写吧，这事找别人帮忙不好


Question: mmap映射文件的问题。

把后面内容全部复制上来，然后截断。

这和一般的文件操作是一样的。 文件没有删除一行的功能，只能把后面的内容前移过来覆盖掉。然后在文件尾加EOF截掉不要的部分。

可以memset为0，然后还能读到空的文件，有定义EOF吗？将文件第一个字符改为EOF


Question: 如和用C语言将汉字转化成unicode编码

好的，多谢啦

好吧，给你代码，环境是DEV C++，根据你自己的需要自己调整吧  #include <stdio.h> #include <stdlib.h> #include <Windows.h>  int main(int argc, char *argv[]) { 	char *testStr = "中"; 	unsigned short outputStr[20] = {0}; 	int  unicodeLen = 0; 	int i = 0; 	 	unicodeLen = MultiByteToWideChar( CP_ACP,             0,             testStr,             -1,             NULL,             0 ); 	 	 	 	MultiByteToWideChar( CP_ACP,          0,          testStr,          -1,          (LPWSTR)outputStr,          unicodeLen );                for (i=0;i<unicodeLen/2;i++) 	{ 		printf("[%d]%x\r\n",i,outputStr[i]); 	} 	 	return 0; }

我的目的不是为了得到某个字的unicode值，所以用C语言以外的方法是行不通的， 有谁知道如何用C语言将 某个字转化为unicode值呢

第1种方法，如楼上所说，调用WINDOWS API，直接转换 第2种方法，可以将汉字写入文本文件中，保存为unicode，以二进进方式读，取值

这是我们的作业。 我不需要讲所有的汉字都转化成unicode编码，我只需要将我需要转化 的字符变为unicode编码，所以不需要考虑工作量的问题， 我要的只是转化的方法 只能用于Windows或者linux的方法是行不通的

所以，你要做的就是调用API来完成。windows下有对应的转换函数，MultibyteToWideChar、WideCharToMultibyte，查MSDN吧。其他平台不知道，应该也是有资料的。

这个工作比较艰巨，光是unicode就有好几个标准：utf8、utf16le、utf16be、utf32等等。你要一一实现的话，不知道几年能做完。而且更重要的是，这个别人早都做好了，为什么还要重复呢。


Question: 请问一个用指针交换字符串中两个字符的问题

void reverse(char *p1 ,char *p2) { char temp = *p1; *p1 = *p2; *p2 = temp; }  void main() { char s[]="i am a student"; char *pstart = s; char *pend=s; while(*pend!='\0') { pend++; } pend--; reverse(pstart,pend); printf("c=%s\n",s); }

char *S="i am a student"; 这个应该定义为  char const *S="i am a student";  这个 BUG 是因为历史原因。

把char *S="i am a student";改成char S[]="i am a student";

楼上感谢！想了半天

定义成数组吧，字符串常量只读


Question: C语言

Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript   Visual Basic C# Visual C++ J# JScript Run-Time Library Reference  printf_s, _printf_s_l, wprintf_s, _wprintf_s_l  Example  See Also  Send Feedback     Print formatted output to the standard output stream. These are versions of printf, _printf_l, wprintf, _wprintf_l with security enhancements as described in Security Enhancements in the CRT.    int printf_s(    const char *format [,       argument]...  ); int _printf_s_l(    const char *format,    locale_t locale [,       argument]...  ); int wprintf_s(    const wchar_t *format [,       argument]...  ); int _wprintf_s_l(    const wchar_t *format,    locale_t locale [,       argument]...  );    Parameters format Format control.  argument Optional arguments.  locale The locale to use.  Return Value Returns the number of characters printed, or a negative value if an error occurs.   Remarks The printf_s function formats and prints a series of characters and values to the standard output stream, stdout. If arguments follow the format string, the format string must contain specifications that determine the output format for the arguments.  The main difference between printf_s and printf is that printf_s checks the format string for valid formatting characters, whereas printf only checks if the format string is a null pointer. If either check fails, an invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns -1 and sets errno to EINVAL.  For information on errno and error codes, see _doserrno, errno, _sys_errlist, and _sys_nerr.  printf_sandfprintf_s behave identically except that printf_s writes output to stdout rather than to a destination of type FILE. For more information, see fprintf_s, _fprintf_s_l, fwprintf_s, _fwprintf_s_l.  wprintf_s is a wide-character version of printf_s; format is a wide-character string. wprintf_s and printf_s behave identically if the stream is opened in ANSI mode. printf_s doesn't currently support output into a UNICODE stream.   The versions of these functions with the _l suffix are identical except that they use the locale parameter passed in instead of the current thread locale.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _unicode defined   _tprintf_s  printf_s  printf_s  wprintf_s   _tprintf_s_l  _printf_s_l  _printf_s_l  _wprintf_s_l    The format argument consists of ordinary characters, escape sequences, and (if arguments follow format) format specifications. The ordinary characters and escape sequences are copied to stdout in order of their appearance. For example, the line    Copy Code  printf_s("Line one\n\t\tLine two\n");     produces the output    Copy Code  Line one         Line two    Format specifications always begin with a percent sign (%) and are read left to right. When printf_s encounters the first format specification (if any), it converts the value of the first argument after format and outputs it accordingly. The second format specification causes the second argument to be converted and output, and so on. If there are more arguments than there are format specifications, the extra arguments are ignored. The results are undefined if there are not enough arguments for all the format specifications.  Security Note:  Ensure that format is not a user-defined string.    Requirements Routine  Required header   printf_s, _printf_s_l  <stdio.h>   wprintf_s, _wprintf_s_l  <stdio.h> or <wchar.h>    For additional compatibility information, see Compatibility in the Introduction.  Example   Copy Code  // crt_printf_s.c /* This program uses the printf_s and wprintf_s functions  * to produce formatted output.  */  #include <stdio.h>  int main( void ) {    char   ch = 'h', *string = "computer";    int    count = -9234;    double fp = 251.7366;    wchar_t wch = L'w', *wstring = L"Unicode";     /* Display integers. */    printf_s( "Integer formats:\n"            "   Decimal: %d  Justified: %.6d  Unsigned: %u\n",            count, count, count, count );     printf_s( "Decimal %d as:\n   Hex: %Xh  C hex: 0x%x  Octal: %o\n",             count, count, count, count );     /* Display in different radixes. */    printf_s( "Digits 10 equal:\n   Hex: %i  Octal: %i  Decimal: %i\n",             0x10, 010, 10 );     /* Display characters. */     printf_s("Characters in field (1):\n%10c%5hc%5C%5lc\n", ch, ch, wch, wch);    wprintf_s(L"Characters in field (2):\n%10C%5hc%5c%5lc\n", ch, ch, wch, wch);     /* Display strings. */     printf_s("Strings in field (1):\n%25s\n%25.4hs\n   %S%25.3ls\n",    string, string, wstring, wstring);    wprintf_s(L"Strings in field (2):\n%25S\n%25.4hs\n   %s%25.3ls\n",        string, string, wstring, wstring);     /* Display real numbers. */    printf_s( "Real numbers:\n   %f %.2f %e %E\n", fp, fp, fp, fp );     /* Display pointer. */    printf_s( "\nAddress as:   %p\n", &count);  }    Sample Output   Copy Code  Integer formats:    Decimal: -9234  Justified: -009234  Unsigned: 4294958062 Decimal -9234 as:    Hex: FFFFDBEEh  C hex: 0xffffdbee  Octal: 37777755756 Digits 10 equal:    Hex: 16  Octal: 8  Decimal: 10 Characters in field (1):          h    h    w    w Characters in field (2):          h    h    w    w Strings in field (1):                  computer                      comp    Unicode                      Uni Strings in field (2):                  computer                      comp    Unicode                      Uni Real numbers:    251.736600 251.74 2.517366e+002 2.517366E+002  Address as:   0012FF78     .NET Framework Equivalent System::Console::Write  System::Console::WriteLine  See Also Concepts Floating-Point Support Stream I/O Locale fopen, _wfopen fprintf, _fprintf_l, fwprintf, _fwprintf_l scanf, _scanf_l, wscanf, _wscanf_l sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l vprintf Functions Send feedback on this topic to Microsoft.

printf_s有可能是自己声明的函数！ 你用whatis printf_s查询的话是没有的

没见过ptintf ，不过 printf 是标准库中的函数，printf_s是MSVC特有的


Question: 还是功能机实例

建议楼主先研读一下《编译原理》中的词法分析和有限状态自动机。

引用 8 楼 u010030181 的回复:可以定义两个数组么？ A数组控制A操作，B数组控制B操作，当A和B操作的数字满足条件时就进行显示……A操作和B操作都是更复杂的代码，不能改变吧，不过可以将switch拆开试试，谢谢你给了个思路，还是大清早的，比较有精神^_^

引用 10 楼 zhao4zhong1 的回复:建议楼主先研读一下《编译原理》中的词法分析和有限状态自动机。多谢赵老师赐教，编译原理是这本么，作者为Alfred V. Aho / Monica S.Lam / Ravi Sethi / Jeffrey D. Ullman

引用 6 楼 lovesmiles 的回复:[quote=引用 5 楼 liaocao2010 的回复:] [quote=引用 3 楼 lovesmiles 的回复:]  for(i = 0; i < 18; i++) { 	if(s[i]) 	{ 		switch(s[i]) 		{ 			case 0: 				显示空白；break; 			case 1:                                {                              				显示Mute On; break;//A发生了                              f(s[9]==5)                                  显示来电；break;//A发生时，B同时也发生了。                                 } 			case 5: 				显示来电；break; 		} 	} } 我说了两种情况下的s数组每个值不一样的，if（s[9]）这个时候不等于5[/quote]  我现在需要的就是当我进行A操作的时候，显示Mute On，在此基础上，再进行B操作，又显示来电，注意  是两者同时发生，都显示  那你这句话是什么意思？两者不同时发生？[/quote]两者是同时发生，但是我代码写的简单，不代表case 1:break之后一直停在这里等你按B操作啊，这一段函数都是重复在运行着，case1之后，你再进行B操作就已经是开始进行又一轮的switch了，不可能刚好你按的时候就是case1break的那一瞬间

引用 5 楼 liaocao2010 的回复:[quote=引用 3 楼 lovesmiles 的回复:]  for(i = 0; i < 18; i++) { 	if(s[i]) 	{ 		switch(s[i]) 		{ 			case 0: 				显示空白；break; 			case 1:                                {                              				显示Mute On; break;//A发生了                              f(s[9]==5)                                  显示来电；break;//A发生时，B同时也发生了。                                 } 			case 5: 				显示来电；break; 		} 	} } 我说了两种情况下的s数组每个值不一样的，if（s[9]）这个时候不等于5[/quote]  我现在需要的就是当我进行A操作的时候，显示Mute On，在此基础上，再进行B操作，又显示来电，注意  是两者同时发生，都显示  那你这句话是什么意思？两者不同时发生？

引用 3 楼 lovesmiles 的回复: for(i = 0; i < 18; i++) { 	if(s[i]) 	{ 		switch(s[i]) 		{ 			case 0: 				显示空白；break; 			case 1:                                {                              				显示Mute On; break;//A发生了                              f(s[9]==5)                                  显示来电；break;//A发生时，B同时也发生了。                                 } 			case 5: 				显示来电；break; 		} 	} } 我说了两种情况下的s数组每个值不一样的，if（s[9]）这个时候不等于5

引用 2 楼 r_Jimy 的回复:现在你进行A操作，会显示MUTE ON 然后进行B操作，MUTE ON消失，显示来电对吗？ 首先确定MUTE ON与来电显示位置不冲突，接着要实现的话，只能去看下显示来电的相关代码 里，哪里把MUTE ON关掉了，把它干掉就可以了 关掉MUTE ON就是case0啊，显示位置不会冲突，来电的代码就是在CASE2里面，我简化了

既然 A操作s[4]=1，其他值为0 B操作s[9]=5，其他值为0 那怎么可能“当我进行A操作的时候，显示Mute On，在此基础上，再进行B操作，又显示来电”呢？？？ 你这种要求得要s[4]、s[5]可以同时不为0才可以。


Question: c语言select 写集有什么作用

引用 5 楼 luotuo44 的回复:考虑这样一个情景：一个客户端sockfd被设置成非阻塞了，现在它要connect服务器，因为非阻塞，所以它可能没有连接上服务器就返回了。那么之后怎么判断这个sockfd连上了服务器呢？ 此时可把这个sockfd放到select的写集中，监听这个sockfd是否可写。如果从select返回了，那么该sockfd就可能连接上了，因为变成可写了。当然也有可能是发生了错误。所以还需要用getsockopt函数做进一步的判断。 代码就不出给了。谷歌一下“非阻塞connect”， 代码一大堆  windows  linux都有这种用法  没感觉出什么优势来，  select + 非堵塞 ，增加代码复杂性， 因为你的判断条件更多了。  select+ 堵塞 用起来方便。  select本来就是为了解决 堵塞套接字的某些函数 堵塞 线程的问题而出现。

引用 2 楼 mymtom 的回复:当接收方缓冲区和发送方缓冲区都满的时候，send会阻塞的，用select可以判断到这种情况并进行处理(比如超时控制)  #include <sys/types.h> #include <sys/time.h> #include <sys/select.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h>  #include <unistd.h>  #include <stdio.h> #include <string.h>  #define SERV_PORT   8000  #define info(fmt, ...)  printf("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) int serv(void) {     int ret;     int servfd, clntfd;     struct sockaddr_in servaddr;     int optval;     ssize_t len;     char buf[1024];      servfd = socket(PF_INET, SOCK_STREAM, 0);      optval = 1;     setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));      memset(&servaddr, 0, sizeof(servaddr));     servaddr.sin_family = AF_INET;     servaddr.sin_port = htons(SERV_PORT);     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);      bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));     listen(servfd, 5);      clntfd = accept(servfd, NULL, NULL);      for (;;) {         getchar();         memset(buf, 0, sizeof(buf));         len = recv(clntfd, buf, sizeof(buf), 0);     } }  int clnt(void) {     int ret;     int fd;     struct sockaddr_in addr;     fd_set wfds;     struct timeval tv;     int n;     ssize_t len;     char s[] = "0123456789ABCDEF";      fd = socket(PF_INET, SOCK_STREAM, 0);      memset(&addr, 0, sizeof(addr));     addr.sin_family = AF_INET;     addr.sin_port = htons(SERV_PORT);     addr.sin_addr.s_addr = inet_addr("127.0.0.1");      ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));      int count = 0;     for (;;) {         FD_ZERO(&wfds);         FD_SET(fd, &wfds);         tv.tv_sec = 10;         tv.tv_usec = 0;         /* 如果这里不进行select, 接收方缓冲区和发送方缓冲区都满的情况下send会阻塞          * 使用select可以判断这种情况, 进行相应的处理(例如超时控制) */         n = select(fd + 1, NULL, &wfds, NULL, &tv);         if (n == 0) {             info("select n=%d: %s\n", n, "timeout");             continue;         }         len = send(fd, s, strlen(s), 0);         count += len;         info("send count=%d\n", (int)count);     }      return 0; }  int main(int argc, char *argv[]) {     pid_t pid;      pid = fork();     if (pid == 0) {         (void)serv();     } else {         sleep(1);         (void)clnt();     }      return 0; }   select最神奇 地方，   fd_set后，  call  select调用，额也是会返回>1的值，这样，你就可以 直接send了了。  可惜的是，很多书籍都不讲解， 导致， 读者以为，必须先send，后select。

引用 2 楼 mymtom 的回复:当接收方缓冲区和发送方缓冲区都满的时候，send会阻塞的，用select可以判断到这种情况并进行处理(比如超时控制)  #include <sys/types.h> #include <sys/time.h> #include <sys/select.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h>  #include <unistd.h>  #include <stdio.h> #include <string.h>  #define SERV_PORT   8000  #define info(fmt, ...)  printf("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) int serv(void) {     int ret;     int servfd, clntfd;     struct sockaddr_in servaddr;     int optval;     ssize_t len;     char buf[1024];      servfd = socket(PF_INET, SOCK_STREAM, 0);      optval = 1;     setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));      memset(&servaddr, 0, sizeof(servaddr));     servaddr.sin_family = AF_INET;     servaddr.sin_port = htons(SERV_PORT);     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);      bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));     listen(servfd, 5);      clntfd = accept(servfd, NULL, NULL);      for (;;) {         getchar();         memset(buf, 0, sizeof(buf));         len = recv(clntfd, buf, sizeof(buf), 0);     } }  int clnt(void) {     int ret;     int fd;     struct sockaddr_in addr;     fd_set wfds;     struct timeval tv;     int n;     ssize_t len;     char s[] = "0123456789ABCDEF";      fd = socket(PF_INET, SOCK_STREAM, 0);      memset(&addr, 0, sizeof(addr));     addr.sin_family = AF_INET;     addr.sin_port = htons(SERV_PORT);     addr.sin_addr.s_addr = inet_addr("127.0.0.1");      ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));      int count = 0;     for (;;) {         FD_ZERO(&wfds);         FD_SET(fd, &wfds);         tv.tv_sec = 10;         tv.tv_usec = 0;         /* 如果这里不进行select, 接收方缓冲区和发送方缓冲区都满的情况下send会阻塞          * 使用select可以判断这种情况, 进行相应的处理(例如超时控制) */         n = select(fd + 1, NULL, &wfds, NULL, &tv);         if (n == 0) {             info("select n=%d: %s\n", n, "timeout");             continue;         }         len = send(fd, s, strlen(s), 0);         count += len;         info("send count=%d\n", (int)count);     }      return 0; }  int main(int argc, char *argv[]) {     pid_t pid;      pid = fork();     if (pid == 0) {         (void)serv();     } else {         sleep(1);         (void)clnt();     }      return 0; }    请问：   linux select的，下，会不会把套接字自动设置为 非堵塞？  套接字有2种模式： 堵塞，非堵塞。

MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\IOCTL.C /******************************************************************************\ * ioctl.c - TCP server * *       This is a part of the Microsoft Source Code Samples. *       Copyright 1996-1997 Microsoft Corporation. *       All rights reserved. *       This source code is only intended as a supplement to *       Microsoft Development Tools and/or WinHelp documentation. *       See these sources for detailed information regarding the *       Microsoft samples programs. \******************************************************************************/    #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  #define DEFAULT_PORT 5001  int ReadAndEcho(SOCKET , char *,int ) ; int WriteMessage(SOCKET , char *,int ) ;  void Usage(char *progname) {     fprintf(stderr,"Usage\n%s -e [endpoint] -i [interface]\n",         progname);     fprintf(stderr,"Where:\n");     fprintf(stderr,"\tendpoint is the port to listen on\n");     fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");     fprintf(stderr," to bind to\n");     fprintf(stderr,"Defaults are 5001 and INADDR_ANY\n");     WSACleanup();     exit(1); } int main(int argc, char **argv) {      char Buffer[128];     char *interface= NULL;     unsigned short port=DEFAULT_PORT;     int fromlen;     int i, ioctl_opt =1;     struct sockaddr_in local, from;     WSADATA wsaData;     SOCKET listen_socket, msgsock;     fd_set readfds, writefds, exceptfds;      /* Parse arguments */     if (argc >1) {         for(i=1;i <argc;i++) {             if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {                 switch(tolower(argv[i][1])) {                     case 'i':                         interface = argv[++i];                         break;                     case 'e':                         port = atoi(argv[++i]);                         break;                     default: 						Usage(argv[0]); 						break; 				} 			} 			else 				Usage(argv[0]); 		} 	}  	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) { 		fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError()); 		WSACleanup(); 		return -1; 	}  	if (port == 0){ 		Usage(argv[0]); 	}  	// 	// The fd sets should be zeroed out before using them to prevent errors. 	FD_ZERO(&readfds); 	FD_ZERO(&writefds); 	FD_ZERO(&exceptfds); 	memset(Buffer,0,sizeof(Buffer));  	local.sin_family = AF_INET;  	// 	// bind to specific interface if desired.  	local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface);  	/* 	 * Port MUST be in Network Byte Order 	 */ 	local.sin_port = htons(port);  	listen_socket = socket(AF_INET, SOCK_STREAM,0); // TCP socket 	if (listen_socket == INVALID_SOCKET){ 		fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError()); 		WSACleanup(); 		return -1; 	} 	// 	// bind() associates a local address and port combination with the 	// socket just created.  	if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) ) 		== SOCKET_ERROR) { 		fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError()); 		WSACleanup(); 		return -1; 	}  	// 	// start listening on the socket for incoming connections 	// 	if (listen(listen_socket,5) == SOCKET_ERROR) { 		fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError()); 		WSACleanup(); 		return -1; 	} 	printf("%s: Listening on port %d\n",argv[0],port);  	// 	// Set the socket to non-blocking mode. 	// 	if (ioctlsocket(listen_socket,FIONBIO,&ioctl_opt) == SOCKET_ERROR) { 		fprintf(stderr,"ioctlsocket failed %d\n",WSAGetLastError()); 		WSACleanup(); 		return -1; 	} 	// 	// The structure of the loop below is very simple. We only accept one 	// connection at a time. As soon as another client connects, we 	// disconnect the first one, and start talking to the new client. 	// All this server does is to echo the data received on the socket 	// back to the client. 	// 	// This is not a very realistic server, but it does serve to show that 	// select() does not scale very well on win32. If we were dealing 	// with more than one client, we would have to have a list of sockets 	// that are in each fdset to be able to check them when select() 	// returns. 	// 	while(1) {  		// 		// A socket in the listen() state becomes ready to read when a 		// client connects to it. An accept() will complete without 		// blocking. 		// Since select sets the sockets that are ready to be read from or 		// written to, we have to include listen_socket in the fdset each time 		// through the loop. 		//  		FD_SET(listen_socket,&readfds);  		i = select(0,&readfds,&writefds,&exceptfds,NULL); 		if (i == SOCKET_ERROR) { 			fprintf(stderr,"select failed %d\n",WSAGetLastError()); 		} 		if (i==0){ 			fprintf(stderr,"Select returned no fds ready\n"); 		}  		if (FD_ISSET(listen_socket, &readfds)){ 			// 			// close the previous client socket. 			// We must also clear it from the fdset to prevent select() 			// from failing. 			// 			closesocket(msgsock); 			FD_CLR(msgsock,&readfds); 			FD_CLR(msgsock,&writefds); 			fromlen = sizeof(from); 			msgsock= accept(listen_socket,(struct sockaddr*)&from,&fromlen); 			if (msgsock == INVALID_SOCKET) { 				fprintf(stderr,"accept failed %d\n",WSAGetLastError()); 				WSACleanup(); 				return -1; 			} 			FD_SET(msgsock,&writefds); 			FD_SET(msgsock,&readfds); 			continue; 		} 		if (FD_ISSET(msgsock,&readfds) ) { 			// 			// socket is ready to read, i.e., there is data on the socket. 			// 			if (ReadAndEcho(msgsock,Buffer,sizeof(Buffer))<0) { 				fprintf(stderr,"terminating connection\n"); 				FD_CLR(msgsock,&readfds); 				FD_CLR(msgsock,&writefds); 				closesocket(msgsock); 				continue; 			} 		} 		if (FD_ISSET(msgsock,&writefds)	){ 			if (WriteMessage(msgsock,Buffer,sizeof(Buffer))	<=0) { 				fprintf(stderr,"terminating connection\n"); 				FD_CLR(msgsock,&readfds); 				FD_CLR(msgsock,&writefds); 				closesocket(msgsock); 				continue; 			} 		} 		FD_SET(msgsock,&writefds); 		FD_SET(msgsock,&readfds); 	} } int	ReadAndEcho(SOCKET insock, char	*Buffer,int	size) { 	int	rc;  	rc = recv(insock,Buffer,size,0);  	if (rc == SOCKET_ERROR)	{ 		fprintf(stderr,"recv() failed with error %d\n",WSAGetLastError()); 		return -1; 	} 	if (rc ==0)	{ 		fprintf(stderr,"Connection closed by client\n"); 		return 0; 	} 	printf("Received [%s] from client\n",Buffer); 	return rc; } int	WriteMessage(SOCKET	outsock, char *Buffer,int size)	{ 	int	rc; 	int	lasterr;  	printf("Sending [%s] to client\n",Buffer); 	rc = send(outsock,Buffer,size, 0);  	if (rc == SOCKET_ERROR)	{ 	  lasterr =	WSAGetLastError(); 	  if (lasterr == WSAEWOULDBLOCK) 		return 0; 	  else { 		fprintf(stderr,"send() failed with error %d\n",lasterr); 		return -1; 	  } 	} 	if (rc ==0)	{ 		fprintf(stderr,"Connection closed by client\n"); 	} 	return rc; }


Question: Linux Posix Timer

1、启动时间是不受用户个性系统时间影响的 系统时间则会随用户修改而变化 这个的影响你测试一下应该就能明白  2、你不是测的挺明白了吗

Update


Question: C函数指针的值与指向函数的地址不同的疑惑

在debug模式下, VS会在函数头部加一些保护，用于检查代码中可能出现的内存越界等错误。 你换成release模式或者用gcc试一下，就没有这个问题了。

vc默认是打开增量链接，所以指向转跳地址，关闭增量链接再试试...

当你把这个函数地址当作数据的时候，都是偏移量。 只有当 CALL 的时候，才使用 E8 指令。

这是优化了。一个是直接的地址，一个是偏移量。 她们在 CALL 的时候，不是同一个 CALL 指令。

引用 2 楼 JiMoKuangXiangQu 的回复:给函数加上 static 限制。 这里（全局）函数调用被编译器处理成了间接调用，函数指针指向了跳转地址。 涉及到了编译链接的处理，重定位等。  个人意见，仅供参考。 打印出来的值是对的，上楼有图

引用 1 楼 user-5 的回复:我用GDB调试，发现funPtr指向函数的地址，如下所示： (gdb) print &max $10 = (int (*)(int, int)) 0x400579 <max> (gdb) print &min $11 = (int (*)(int, int)) 0x400595 <min> (gdb) print funPtr $12 = (int (*)(int, int)) 0x400579 <max>  我用vs打印了一下，出来的结果是两者相同，但是变量监控窗口的值仍然不同。如图

每个编译器的处理可能不同，多测试几个编译器试试看。


Question: 用C语言实现编写游戏

大嘴吃豆 主要就是屏幕刷新 over

搜“VC PacMan”


Question: 多线程同步问题

有没有帮我看下程序？

《Windows核心编程》  Synchronization Functions The following functions are used in synchronization.    CancelWaitableTimer   CreateEvent   CreateMutex   CreateSemaphore   CreateWaitableTimer   DeleteCriticalSection   EnterCriticalSection   GetOverlappedResult   InitializeCriticalSection   InitializeCriticalSectionAndSpinCount   InterlockedCompareExchange   InterlockedDecrement   InterlockedExchange   InterlockedExchangeAdd   InterlockedIncrement   LeaveCriticalSection   MsgWaitForMultipleObjects   MsgWaitForMultipleObjectsEx   OpenEvent   OpenMutex   OpenSemaphore   OpenWaitableTimer   PulseEvent   QueueUserAPC   ReleaseMutex   ReleaseSemaphore   ResetEvent   SetCriticalSectionSpinCount   SetEvent   SetWaitableTimer   SignalObjectAndWait   TimerAPCProc   TryEnterCriticalSection   WaitForMultipleObjects   WaitForMultipleObjectsEx   WaitForSingleObject   WaitForSingleObjectEx

我的逻辑需要，消费者线程必须要很多个，每个线程从被sem控制的buffer里面取数据，现在的主要问题就是二值信号量控制不了他们，我debug的原因就是因为里面调用了shell的命令（system（）作用是调用iptables的命令）。 还请帮忙解释下为啥会锁不住，怎么修改？同时感谢1#

我写的是linux服务器的程序。。。。

我是来默默滚粗的

仅供参考//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }


Question: float与double精度到底多少

请楼主亲自打开include\float.h查看其内容。

float的有效数字是6至7位。 最好不要超过6位。

单精度有效数字是24位 -2*2^23 --- 2*2^23 ，大小范围是 -2^128 ~ +2^128

去看《计算机组成原理》！！！


Question: 怎样用C语言设计一个类似滚动条的显示思路？

如果只有英文和字母的话，　可以讲一下我做过的一个类似的东东  1. 做成一个8X22的显示Buffer 2. 以每行22个数据计算滚动最大值，滚动到最大值时，　刚好显示最后８行数据 3. 向上或者向下时计算出滚动位置，并且向显示模块发出更新通知  4. 显示模块收到更新通知时，根据滚动位置，把数据填写到 8X22的数据buffer中 　省略号可以考虑在这个步骤做成 5. 循环8次，　以行为单位把8X22的数据buffer中的数据显示出来  PS:　如果夹杂着中文，　计算滚动最大值和滚动位置会比较麻烦。

引用 2 楼 zhao4zhong1 的回复:仅供参考//输入一个小于200的字符串，将该字符串以“_”分割成小于20的字串。请输出原串和子串。 //请注意以下测试用例： //·输入空串 //·输入长度为9的字符串 //·输入长度为19的字符串 //·输入长度为20的字符串 //·输入长度为38的字符串 //·输入长度为205的字符串 //·理论上还应该考虑输入串中包含_如何处理的逻辑（这个在我的代码中没有体现） #include <stdio.h> #include <string.h> char s[201]; char d[11][21]; int i,L,n; void main() {     fgets(s,201,stdin);     L=strlen(s);     if ('\n'==s[L-1]) {s[L-1]=0;L--;}     for (i=0;i<L;i++) {         d[i/19][i%19]=s[i];         if (i!=L-1 && 18==(i%19)) {             d[i/19][19]='_';             d[i/19][20]=0;         }     }     d[i/19][i%19]=0;     if (i>0 && 0==(i%19)) {         n=i/19;     } else {         n=i/19+1;     }     printf("s=\"%s\"\n",s);     for (i=0;i<n;i++) {         printf("d[%2d]=\"%s\"\n",i,d[i]);     } }  看不懂，把人看的眼花缭乱的

引用 1 楼 u014444402 的回复:我的语文是体育老师教的，还是楼主的体育老师是教语文的？ 是我表述得不清楚。大概意思就是：因为屏幕一次最多显示8行数据，按下键盘的“上”和“下”按键，字符串会根据按下的按钮移动（就像我们平时浏览网页时拖动滚动条所看到的的效果），这样就可以回看到所有字符串了。现在就想设计这么一个功能的模块。没有任何控件，只有显示函数。

我的语文是体育老师教的，还是楼主的体育老师是教语文的？


Question: 在VC上编译一个程序，想调用getopt（），我该怎么做才可以呢

楼上的楼上正解                              --话说用手机回帖真心蛋疼

/*****************************************************************************  *  *  MODULE NAME : GETOPT.C  *  *  COPYRIGHTS:  *             This module contains code made available by IBM  *             Corporation on an AS IS basis.  Any one receiving the  *             module is considered to be licensed under IBM copyrights  *             to use the IBM-provided source code in any way he or she  *             deems fit, including copying it, compiling it, modifying  *             it, and redistributing it, with or without  *             modifications.  No license under any IBM patents or  *             patent applications is to be implied from this copyright  *             license.  *  *             A user of the module should understand that IBM cannot  *             provide technical support for the module and will not be  *             responsible for any consequences of use of the program.  *  *             Any notices, including this one, are not to be removed  *             from the module without the prior written consent of  *             IBM.  *  *  AUTHOR:   Original author:  *                 G. R. Blair (BOBBLAIR at AUSVM1)  *                 Internet: bobblair@bobblair.austin.ibm.com  *  *            Extensively revised by:  *                 John Q. Walker II, Ph.D. (JOHHQ at RALVM6)  *                 Internet: johnq@ralvm6.vnet.ibm.com  *  *****************************************************************************/  /******************************************************************************  * getopt()  *  * The getopt() function is a command line parser.  It returns the next  * option character in argv that matches an option character in opstring.  *  * The argv argument points to an array of argc+1 elements containing argc  * pointers to character strings followed by a null pointer.  *  * The opstring argument points to a string of option characters; if an  * option character is followed by a colon, the option is expected to have  * an argument that may or may not be separated from it by white space.  * The external variable optarg is set to point to the start of the option  * argument on return from getopt().  *  * The getopt() function places in optind the argv index of the next argument  * to be processed.  The system initializes the external variable optind to  * 1 before the first call to getopt().  *  * When all options have been processed (that is, up to the first nonoption  * argument), getopt() returns EOF.  The special option "--" may be used to  * delimit the end of the options; EOF will be returned, and "--" will be  * skipped.  *  * The getopt() function returns a question mark (?) when it encounters an  * option character not included in opstring.  This error message can be  * disabled by setting opterr to zero.  Otherwise, it returns the option  * character that was detected.  *  * If the special option "--" is detected, or all options have been  * processed, EOF is returned.  *  * Options are marked by either a minus sign (-) or a slash (/).  *  * No errors are defined.  *****************************************************************************/  #include <stdio.h>                  /* for EOF */ #include <string.h>                 /* for strchr() */   /* static (global) variables that are specified as exported by getopt() */ char *optarg = NULL;    /* pointer to the start of the option argument  */ int   optind = 1;       /* number of the next argv[] to be evaluated    */ int   opterr = 1;       /* non-zero if a question mark should be returned                            when a non-valid option character is detected */  /* handle possible future character set concerns by putting this in a macro */ #define _next_char(string)  (char)(*(string+1))  int getopt(int argc, char *argv[], char *opstring) {     static char *pIndexPosition = NULL; /* place inside current argv string */     char *pArgString = NULL;        /* where to start from next */     char *pOptString;               /* the string in our program */       if (pIndexPosition != NULL) {         /* we last left off inside an argv string */         if (*(++pIndexPosition)) {             /* there is more to come in the most recent argv */             pArgString = pIndexPosition;         }     }      if (pArgString == NULL) {         /* we didn't leave off in the middle of an argv string */         if (optind >= argc) {             /* more command-line arguments than the argument count */             pIndexPosition = NULL;  /* not in the middle of anything */             return EOF;             /* used up all command-line arguments */         }          /*---------------------------------------------------------------------          * If the next argv[] is not an option, there can be no more options.          *-------------------------------------------------------------------*/         pArgString = argv[optind++]; /* set this to the next argument ptr */          if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */             ('-' != *pArgString)) {             --optind;               /* point to current arg once we're done */             optarg = NULL;          /* no argument follows the option */             pIndexPosition = NULL;  /* not in the middle of anything */             return EOF;             /* used up all the command-line flags */         }          /* check for special end-of-flags markers */         if ((strcmp(pArgString, "-") == 0) ||             (strcmp(pArgString, "--") == 0)) {             optarg = NULL;          /* no argument follows the option */             pIndexPosition = NULL;  /* not in the middle of anything */             return EOF;             /* encountered the special flag */         }          pArgString++;               /* look past the / or - */     }      if (':' == *pArgString) {       /* is it a colon? */         /*---------------------------------------------------------------------          * Rare case: if opterr is non-zero, return a question mark;          * otherwise, just return the colon we're on.          *-------------------------------------------------------------------*/         return (opterr ? (int)'?' : (int)':');     }     else if ((pOptString = strchr(opstring, *pArgString)) == 0) {         /*---------------------------------------------------------------------          * The letter on the command-line wasn't any good.          *-------------------------------------------------------------------*/         optarg = NULL;              /* no argument follows the option */         pIndexPosition = NULL;      /* not in the middle of anything */         return (opterr ? (int)'?' : (int)*pArgString);     }     else {         /*---------------------------------------------------------------------          * The letter on the command-line matches one we expect to see          *-------------------------------------------------------------------*/         if (':' == _next_char(pOptString)) { /* is the next letter a colon? */             /* It is a colon.  Look for an argument string. */             if ('\0' != _next_char(pArgString)) {  /* argument in this argv? */                 optarg = &pArgString[1];   /* Yes, it is */             }             else {                 /*-------------------------------------------------------------                  * The argument string must be in the next argv.                  * But, what if there is none (bad input from the user)?                  * In that case, return the letter, and optarg as NULL.                  *-----------------------------------------------------------*/                 if (optind < argc)                     optarg = argv[optind++];                 else {                     optarg = NULL;                     return (opterr ? (int)'?' : (int)*pArgString);                 }             }             pIndexPosition = NULL;  /* not in the middle of anything */         }         else {             /* it's not a colon, so just return the letter */             optarg = NULL;          /* no argument follows the option */             pIndexPosition = pArgString;    /* point to the letter we're on */         }         return (int)*pArgString;    /* return the letter that matched */     } }

Windows上没有这个接口，需要自己实现，到网上找一个就行


Question: C 语言问题，求大神指导

引用 1 楼 litao31415 的回复:楼主希望实现冒泡排序，但该程序有多处错误  麻烦大大指出错误在哪儿，求大神指导

楼主希望实现冒泡排序，但该程序有多处错误

引用 5 楼 user-2 的回复: #include <stdio.h> #include <malloc.h>   void input(int *,int); void sort(int *,int); void output(int *,int); void main() {     int *p = NULL;                    //指向空的記憶體位置     int len = 0,i = 0;       printf("請輸入長度：\nlenth = ");       scanf("%d",&len);           p = (int *)malloc(len * sizeof(int)); //動態配置記憶體       input(p,len);       sort(p,len);       output(p,len);   }  void input(int * p, int len) {     int i = 0;     for(i=0;i<len;i++)     {         printf("請為第%d個數組元素賦值:\np[%d] = ",i+1, i); 		scanf("%d",&p[i]);     } }  void sort(int * pArr, int len) {     int i,j,k; 	for(j=len-1;j>=0;j--) 	{         for(i=0;i<j;i++)         {             if(*(pArr+i) > *(pArr+i+1))             {                 k = *(pArr+i);                 *(pArr+i) = *(pArr+i+1);                 *(pArr+i+1) = k;             }         } 	}   }   void output(int * p,int len) {     int i; 	printf("After sort: \n");     for(i=0;i<len;i++)     {         printf("p[%d] = %d\n", i,p[i]);     } }    感谢大神指导，谢谢

引用 3 楼 litao31415 的回复:1.分清楚指向数组的指针和指向数组内部元素的指针，scanf("%d",p[i]);应改正为scanf("%d",&p[i]); 2.for(i=0;i<len-1;i++)         for(j=0;j<len-1-i;j++)             {                 if(*(pArr+i) > *(pArr+i+1))             {                 k = *(pArr+i);                 *(pArr+i) = *(pArr+i+1);                 *(pArr+i+1) = k;             }              } 应该改为： for(i=0;i<len-1;i++)         for(j=i;j<len-1;j++)//修改             {          if(*(pArr+j) > *(pArr+j+1))             {                 k = *(pArr+j);// i修改为j                 *(pArr+j) = *(pArr+j+1);// i修改为j                 *(pArr+j+1) = k;// i修改为j             }              } 才符合逻辑。 3.还有显示时最好加空格或者换行才能区分出具体数据  感谢大神，成功了，都是一些初级错误，唉！惭愧，我愣是半天都没找到


Question: GetPrivateProfileString 访问冲突

你的代码问题： 1. 很多的 new 没有对应 delete； 2. 字符集不统一。LPTSTR 是一个通用类型，可能是 char 也可能是 WCHAR，包括 API； 不知道你为什么那么喜欢用 new 呢，又不是未知大小。用 TCHAR lpPath[MAX_PATH]; 岂不更好？int main(int argc, char *argv[]) {     TCHAR lpPath[MAX_PATH] = TEXT("..\\") CONF_FILE_PATH;     TCHAR Path[32];     int Port;           //端口号     TCHAR Ip[16];       //ip地址     TCHAR Username[32]; //用户名     TCHAR Password[32]; //密码 //  UINT num; //  lstrcpy(lpPath, TEXT("..\\config.ini"));     Port = GetPrivateProfileInt(TEXT("config"), TEXT("port"), 80000, lpPath);     GetPrivateProfileString(TEXT("config"), TEXT("username"), TEXT("admin"), Username, _countof(Username), lpPath);     GetPrivateProfileString(TEXT("config"), TEXT("path"), NULL, Path, _countof(Path), lpPath);     GetPrivateProfileString(TEXT("config"), TEXT("ip"), TEXT("192.168.99.182"), Ip, _countof(Ip), lpPath);     GetPrivateProfileString(TEXT("config"), TEXT("password"), TEXT("12345"), Password, _countof(Password), lpPath);       _tprintf(TEXT("%s%d%s%s%s"), Path, Port, Ip, Username, Password);          return 0; }

是在这里提示错误 GetPrivateProfileString("config", "username", "admin", "Username", 20, lpPath);


Question: 一个C语言疑问

引用 11 楼 zhao4zhong1 的回复:栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，…… 赵老师从事什么行业？ 为什么csdn的引用没有消息提醒呢？

你是什么系统啊 什么编译器啊，我怎么玩不出你这效果。

i 的存储位置开始时未初始化，输出随机，第二次调用时i 分配的还是同一空间，输出是上次留下的值

把printf去掉，栈上的数据在第一次foo之后没有被破坏，foo返回只是栈顶指针修改了，第二次foo，i的栈地址不是刚好，而是肯定与第一次相同，所以是999

当你第一次向一块内存写入一个数，然后把这块内存刚好分给了另一个变量，那个变量没有赋值来改变这块内存，所以就是第一个变量的值。

当你第一次向一块内存写入一个数，然后把这块变量刚好分给了另一个变量，那个变量没有赋值来改变这块内存，所以就是第一个变量的值。

第一次调用foo,　i在栈上被赋值999,第２次调用foo,i的栈地址刚好与第一次相同，所以就是９９９了。

我的问题是第二个foo为什么会出现999，而不是一个随机数

错误的代码 输出什么都不必奇怪  包括输出999

能给个详细的说法么？

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）


Question: 急啊，有人有openssh for windows的源码吗

引用 7 楼 mLee79 的回复:试了下, 在cygwin下编译 dropbear 很方便, 几分钟就编译, 配置好了, 依赖的 库也很少.. 谢谢，已参考 KpyM SSH Server搞定了

错了, 在上面移植个 dropbear 很方便..

引用 4 楼 yy175703252 的回复:[quote=引用 2 楼 mLee79 的回复:] 直接用 cygwin 版本啊.. 我要做些二次开发，所以不适合吧[/quote]  cygwin 整个都是开源的, 你编译出 libssh2.a 链接到你程序里就是了..

引用 2 楼 mLee79 的回复:直接用 cygwin 版本啊.. 我要做些二次开发，所以不适合吧

引用 1 楼 user-2 的回复:移植 openssh 不好做, 不如去修改 KpyM Telnet/SSH Server. c++ win32 cryptlib. BSD 协议. 很好. 恩貌似很不错，看看能不能为我所用，谢谢！

直接用 cygwin 版本啊..


Question: 关于删除字符串中的一段字符的问题，懂的帮看看~~~

仅供参考#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //

我自己随便写的，不一定对。楼主也可以找strstr的源码自己照着写。 int Match(char *str,char const *want) {   int offset, i;   int len1, len2;   for (len1 = 0; str[len1] != '\0'; len1++) {     ;   }   for (len2 = 0; want[len2] != '\0'; len2++) {     ;   }   for (offset = 0; offset <= len1 - len2; offset++) {     for (i = 0; i < len2; i++) {       if (str[offset+i] != want[i]) {         break;       }     }     if (i == len2) {       return offset;     }   }   return -1; }

引用 1 楼 user-2 的回复:先把所有的'/0'都改成'\0' 太丢人了~~~

引用 2 楼 user-2 的回复:Match函数没看懂，我自己写了一个 int Match(char *str,char const *want)                      //查找目标字符串 {   char *p = strstr(str, want);   return (p == NULL) ? -1 : p - str; }  Del_substr函数里面这几行改一下就好了  p+=i;  if(*cq++ != '/0')  {  i++;  } 改成  while(*cq++ != '\0')  {  i++;  }  p+=i;不好意思，人家题目不让用str库函数~~~~

先把所有的'/0'都改成'\0'


Question: unix环境高级编程是不是不适合初学者

刚刚开始看，确实，从语法上能看懂程序结构，但是代码里面很多函数不理解，各方面的基础都有待加强。

我看这本书的基础是《深入理解计算机系统 》，《c和指针》，《linux命令行大全》和一点点的数据结构只是，我觉得从头看这本书还是可以的。

《linux程序设计》我觉得挺好德的

先看两遍《C语言程序设计》和《鸟哥的Linux私房菜》，对C和Linux有了解了，就可以直接上手看apue了，然后课后的习题得去研究，对加深理解很有帮助；平时用到一些东西时得会去查，一回生二回熟。另外，得懂得用man，比如，查看函数printf的用法，man 2 printf。其实apue这本书并不难只是内容多而已，建议看第3版的英文版，里面加了一些新的东西，书里用的Ubuntu12.04也比较新

apue   引用 6 楼 user-18 的回复:apue真的说起来，其实一点都不难，因为书里面的介绍已经非常详细了。它和C primer plus这类书的最主要区别在于它不在是脱离实际的一些简单片段，而是实实在在的应用实例。当然这里很多例子，比起真正的大项目其实也算是很小了。不过对于没有做过项目经验的新手还是会比较吃力点。  当然apue的难点也不在于此，而是里面的unix文化。如果你没有这种文化的代入感，很多地方就想不通。比如unix的流和缓冲的概念，还有线程、信号、进程之间有怎样的联系与区别？其他方面，在各种uinx系统中，大部分人宁愿写命令、写脚本，也不愿在图形界面里点两下。而windows中命令行却很少有人使用，宁可开发各种复杂的图形界面工具点一下，也不会主动写几行脚本。这些文化差异，核心思想如果没有深入体会，就会很难看懂APUE。有时间的话，不仅要多看APUE，还要多接触Unix的文化，去体会一下Unix和以前接触的windows有何不同。  挣钱干活命令行(脚本) ( 包括NT )  C是给perl 做扩展用的

有两个建议： 1，先学习SHELL操作和编程，从使用者的角度多理解一下什么是进程、文件描述符；  2，C有完全标准的那部分函数库，例如 stdio等等，但是有关到操作系统的就完全不一样， 例如windows.h unistd.h等等，有时候，你如果不先学学操作系统，确实无法理解其意义。

在看这本书前可以找个简单的linux  c编程书看看，了解下基本命令，进线程，网络编程，之后看这个书你会受益匪浅！

等你学精了就明白了

看过<unix高级环境编程> 其实没有一点linux c方面的编程沉淀，还真不好看懂

建议去看人民邮电出版社的《c编程实战Linux》，挺好的一本书。

引用 楼主 u014311648 的回复:我刚刚看完《c primer plus》这本书，现在正在看《unix环境高级编程》第一章。我发现unix高级编程好难，里面编程练习使用的函数好多都是我以前没见过的，书里面也没有对函数怎么使用作解释，搞得我没看到没见过的函数就要man或百度，累觉不爱！ 比如第一章1-5  #include<apue.h> #include<sys/wait.h> int main(void) {         char buf[MAXLINE];      /*MAXLINE defined in apue.h*/         pid_t pid;         int status;         printf("%%");/*printf requires %% to print %*/         while(fgets(buf,MAXLINE,stdin)!=NULL)         {                 if(buf[strlen(buf)-1]=='\n')                         buf[strlen(buf)-1]='\0';          //replace newline with null                 if((pid=fork())<0){                         err_sys("fork error");                 }else if(pid==0)                 {                         execlp(buf,buf,(char *)0);                         err_ret("countn,t execute: %s",buf);                         exit(127);                 }                 //parent                 if((pid=waitpid(pid,&status,0))<0)                         err_sys("waitpid error");                 printf("%%");         }         exit(0); }   首先sys/wait.h头文件没见过，然后pid_t不知道是什么类型，fork()execlp()两个函数完全没见过。光是第一章的一个小程序就有这么多看不懂要man的地方，是不是《unix环境高级编程》不适合c菜鸟？？？？？？请看过apue的大神指点迷津。 的确不太适合，你还缺os原理，计算机组成原理，网络基础的一些知识， 不然涉及io的一些函数光看参数你打死都不能理解透彻。 涉及网络的也会云里雾里。 涉及系统，竞争，并发的，资源管理回收的，也会遇到相同的窘境。

《Linux C编程一站式学习》

新手《Linuc环境下C编程》

楼主，你C语言初学者吧，C语言中怎么创建进程和线程，怎么进行socket通信，还有select，再来看这本书吧。

引用 9 楼 luotuo44 的回复:刚看完《c primer plus》就学《UNIX环境高级编程》不是明智之举。假如楼主是在Windows环境下学的，那就更加不应马上看《UNIX环境高级编程》。 应该再深入学一下C语言，学一些Linux的基本命令和基础知识，再学操作系统这门课。这时再来看《UNIX环境高级编程》就觉得它很简单了。我是在linux下学的c语言

一个是C++语言，一个是环境编程，两个关系不大。  环境编程需要对系统比较熟悉。unix环境高级编程 这本书的例子貌似用的是C语言

引用 7 楼 user-18 的回复:很多内容，如果单看代码，其实会觉得很简单，不就是一堆函数组成的，了解每个函数都是干嘛的，一行行读下来，不就知道这个函数是干嘛的了么？但你有没有想过，为什么是先这样执行，再那样执行。有或者这个函数在这里有什么用？为什么要添加这样的功能？比如umask和chmod之间有什么关联等等，你都要好好思考以下。这对我貌似太高极了，我是连鸟哥私房菜都看不下去，只是随便浏览一遍的人


Question: xmlStringGetNodeList这个函数和xmlStringLenGetNodeList的区别

问题1：xmlstringgetnodelist是获取节点的list，因为xml每个节点多有对应的标签 xmlstringlengthgetnodelist获取他的总长度  xml的节点都是根据标签来获取的，不管他多深，一级级的访问，获取对应的标签的内容


Question: 实在不知道什么回事啊

引用 13 楼 jikexiyg 的回复:[quote=引用 10 楼 tyuiop1232 的回复:] [quote=引用 3 楼 jikexiyg 的回复:] float 乘以float数学上得到的结果应该是double 型的数据，但是你float add(float m,float n)函数返回的时float型数据，所以有警告信息说truncation from 'const double ' to 'float。 另外：你这两个数相乘干嘛起个名字叫add啊，这样容易引起误解，可读性差。 你说的这个我知道，但我不知道这个和我的问题有什么关系？乘后得到的是double型数23.46，但就算截断为float我想也不会变吧，真不知道这到底是怎么回事啊[/quote] 我上面只是解释了为什么会出现truncation from 'const double ' to 'float警告信息。关于为什么计算结果是23.459999而不是23.46这个问题的话就复杂了，这个是浮点数进度的问题，有很多定点数用浮点数只能近似的表示，这也是为什么浮点数不能替代定点数的一个原因，与浮点数在计算机中的存储方式等有关，这个深究的话就是计算机组成原理的知识了，这里给你推荐篇文章，详细讲解了这些问题： http://bbs.chinaunix.net/thread-3746530-1-1.html[/quote] 十分感谢

引用 10 楼 tyuiop1232 的回复:[quote=引用 3 楼 jikexiyg 的回复:] float 乘以float数学上得到的结果应该是double 型的数据，但是你float add(float m,float n)函数返回的时float型数据，所以有警告信息说truncation from 'const double ' to 'float。 另外：你这两个数相乘干嘛起个名字叫add啊，这样容易引起误解，可读性差。 你说的这个我知道，但我不知道这个和我的问题有什么关系？乘后得到的是double型数23.46，但就算截断为float我想也不会变吧，真不知道这到底是怎么回事啊[/quote] 我上面只是解释了为什么会出现truncation from 'const double ' to 'float警告信息。关于为什么计算结果是23.459999而不是23.46这个问题的话就复杂了，这个是浮点数进度的问题，有很多定点数用浮点数只能近似的表示，这也是为什么浮点数不能替代定点数的一个原因，与浮点数在计算机中的存储方式等有关，这个深究的话就是计算机组成原理的知识了，这里给你推荐篇文章，详细讲解了这些问题： http://bbs.chinaunix.net/thread-3746530-1-1.html

add怎么写return (m*n);

给大一点就会出现精度问题了。小的看不出来。

return (m*n);  4*5.865不就是23.45么？

在计算机中一般的存储方式是无法精确存储浮点数的 http://zhidao.baidu.com/link?url=vUBysZ2qfeZne7AUYqcVxDp2kvJB0xk8BXVNg7rzvA1qG4ixG-gVuBd5utiHk0jCeSRJViQ64bjOt-0MovPR8_

引用 5 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390676437 您好，谢谢你的帮助，但我才刚学，水平太次，不太能看的明白啊能告诉我怎样规避这种情形的发生吗？

引用 3 楼 jikexiyg 的回复:float 乘以float数学上得到的结果应该是double 型的数据，但是你float add(float m,float n)函数返回的时float型数据，所以有警告信息说truncation from 'const double ' to 'float。 另外：你这两个数相乘干嘛起个名字叫add啊，这样容易引起误解，可读性差。 你说的这个我知道，但我不知道这个和我的问题有什么关系？乘后得到的是double型数23.46，但就算截断为float我想也不会变吧，真不知道这到底是怎么回事啊

引用 4 楼 Indestiny 的回复:add怎么写return (m*n); 只是随手写个为了说明这个问题的，何况乘法的英语我不会

浮点数本来就有这样的问题。

float的字面常量 需要加 f 后缀  float x=5.865f; float y=4f;

引用 3 楼 jikexiyg 的回复:float 乘以float数学上得到的结果应该是double 型的数据，但是你float add(float m,float n)函数返回的时float型数据，所以有警告信息说truncation from 'const double ' to 'float。 ++


Question: 如何写程序将定义的几个变量的值放到一个指针开始的存储空间里去？C语言的

9楼 zhao4zhong1   大神，这个程序表示看不懂额，可不可以解释一下程序的思路？

说明一点，这是一个笔试题，当时完全没思路，今天看了大家居然有这么多解决方法，真心怀疑自己是不是适合写程序了。。。

非常感谢各位大神指点，最近太忙，没来看帖子，以为会沉掉，没想到会有这么多技术大牛帮我回答，再次感谢各位大神花费宝贵的时间来帮我解决问题！

楼主应该是想要序列化吧，把结构体线性存储，进行传输或存储？ typedef struct tag_param{     char *a;     int b;     float c; } PARAM_S;  char *Linear(PARAM_S *pstParam, int *pLen) { 	int strlen = strlen(pstParam->a); 	int size = strlen + 1 + sizeof(int) + sizeof(float); 	char *pcLine;  	pcLine = malloc(size); 	if (NULL == pcLine) 		return; 	memcpy(pcLine, pstParam->a, strlen + 1); 	memcpy(pcLine + strlen + 1, pstParam->b, sizeof(int); 	memcpy(pcLine + strlen + 1 + sizeof(int), pstParam->c, sizeof(float));  	*pLen = size; 	return pcLine; }   获取的时候，需要strlen(pcLine) 获取A 字符串的长度 。

指定结构体字节对齐： #include <pshpack1.h> typedef struct {     char *a;     int b;     float c; } PARAM_STRUCT; #include <poppack.h>

//将char *a = "123";  int b = 123;  float c = 1.23;   三个变量的值依次保存到void *d 开始的存储单元 #include <stdio.h> #include <stdlib.h> #include <string.h> char *a = "123";  int b = 123;  float c = 1.23f; void *d; void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } } int main() {     d=malloc(sizeof(char *)+sizeof(int)+sizeof(float));     if (NULL==d) return 1;     *((char **)d)=a;     *((int *)((char *)d+sizeof(char *)))=b;     *((float *)((char *)d+sizeof(char *)+sizeof(int)))=c;     HexDump((char *)d,sizeof(char *)+sizeof(int)+sizeof(float),(int)d);     free(d);     return 0; } //00421960 - 1c 30 41 00 7b 00 00 00 a4 70 9d 3f              .0A.{....p.? //

用结构体并不能保证内存连续，因为还有内存对齐这个东西

char buf[0x100] = {0}; char *a = "123";  int b = 123;  float c = 1.23;   memcpy(buf, a, strlen(a)); memcpy(buf+3, &b, sizeof(b));  //注意, 这里未保存\0. memcpy(buf+3+sizeof(b), &c, sizeof(float));

声明一个适合存放你结构的变量，把你自己的变量塞进一个结构体中，把你自己的变量塞进一个结构体中

使用结构体就行了 struct ss{     char* a;     int b;     float c; };  struct ss s= {"123", 123, 1.23}; void* d = (void *) &s;

弄个结构体不就行了

这些数据类型大小都不一样，你存在void*以后。如果解析的人不知道void*具体的格式，就必然出错。 我觉得不是一个好的编码风格

没有人可以保证，只自己申请一块连续内存，然后自己存放，或者定义一个结构


1. eLIBs_malloc()后，最好eLIBs_memset()。  2. eLIBs_memset(指针, sizeof(__ebook_thread_para_t));


Question: C语言初学者再次求大神抱腿

顶，楼上正解

把 scanf_s("%s",&pst[i].name); 改成 scanf_s("%s", &pst[i].name, 100);


Question: 如何将字符串转化成16进制字符数据

引用 9 楼 mymtom 的回复: #include <stdio.h> #include <string.h>  unsigned char t[256] = {      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,      0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };  int s2h(const char *s, char *h) {     int r, i, n;     char *p, q;      p = h;     n = strlen(s);     if (n % 2) {         h[0] = t[(unsigned char)s[0]];         ++p;         ++s;     }      for (i = 0; i < n; i = i + 2) {         *(p++) = (t[(unsigned char)s[i]] << 4) | t[(unsigned char)s[i + 1]];     }      return (n + 1) / 2; }  int main(int argc, char *argv[]) {     char s[] = "a4e56EF";     char h[1024];     int i, n;      n = s2h(s, h);     for (i = 0; i < n; ++i) {         printf("%02x", (unsigned char)h[i]);     }     printf("\n");      return 0; }   這麼先進樓主居然不給分不識貨

参考一下 #include <stdio.h> int main() {   char const* p = "123456";   unsigned char res[3];   sscanf(p, "%hhx%hhx%hhx", res, res + 1,res + 2);    printf("%#hhx %#hhx %#hhx", res[0], res[1], res[2]); }

忘了，所有的 TEXT('0') 改成 '0'。

也可以将函数改写为返回值的方式：#include <stdio.h> #include <stdlib.h>   /*  * lpSrcStr  : 要转换的字符串，如 “123456AbCdEf”。  * lpRetBytes: 要存放转换结果的字节数组。  * lpRetSize : lpRetBytes 数组的元素个数  * 返回：写入 lpRetBytes 的元素个数  */ size_t StrToHex(const char lpSrcStr[], unsigned char lpRetBytes[], size_t uiBuffSize) {     size_t n = 0;     if (lpSrcStr != NULL && lpRetBytes != NULL && uiBuffSize > 0) {         size_t uiLength = strlen(lpSrcStr);         if (uiLength % 2 == 0) {             size_t i = 0;             while (*lpSrcStr != 0 && (n = ((i++) >> 1)) < uiBuffSize) {                 lpRetBytes[n] <<= 4;                 if (*lpSrcStr >= TEXT('0') && *lpSrcStr <= TEXT('9')) {                     lpRetBytes[n] |= *lpSrcStr - '0';                 } else if (*lpSrcStr >= TEXT('a') && *lpSrcStr <= TEXT('f')) {                     lpRetBytes[n] |= *lpSrcStr - 'a' + 10;                 } else if (*lpSrcStr >= TEXT('A') && *lpSrcStr <= TEXT('F')) {                     lpRetBytes[n] |= *lpSrcStr - 'A' + 10;                 }                 lpSrcStr++;             }         }     }     return n; }   int main(int argc, char *argv[]) {     char str[] = "123456ABCDEF";     unsigned char ret[32];     size_t size = StrToHex(str, ret, _countof(ret));     for (int i = 0; i < size; i++) {         printf("%02X", ret[i]);     }     putchar('\n');     return 0; }

帮你写了一个： #include <stdio.h> #include <stdlib.h>  /*  * lpSrcStr  : 要转换的字符串，如 “123456ABCDEF”。  * lpRetBytes: 要存放转换结果的字节数组。  * lpRetSize : 输入时，指定 lpRetBytes 的大小；调用结束后为 lpRetBytes 的个数。  */ void StrToHex(const char lpSrcStr[], unsigned char lpRetBytes[], size_t *lpRetSize) {     if (lpSrcStr != NULL && lpRetBytes != NULL && lpRetSize != NULL) {         size_t uiLength = strlen(lpSrcStr);         if (uiLength % 2 == 0) {             size_t i = 0;             size_t n = 0;             while (*lpSrcStr != 0 && (n = ((i++) >> 1)) < *lpRetSize) {                 lpRetBytes[n] <<= 4;                 if (*lpSrcStr >= TEXT('0') && *lpSrcStr <= TEXT('9')) {                     lpRetBytes[n] |= *lpSrcStr - '0';                 } else if (*lpSrcStr >= TEXT('a') && *lpSrcStr <= TEXT('f')) {                     lpRetBytes[n] |= *lpSrcStr - 'a' + 10;                 } else if (*lpSrcStr >= TEXT('A') && *lpSrcStr <= TEXT('F')) {                     lpRetBytes[n] |= *lpSrcStr - 'A' + 10;                 }                 lpSrcStr++;             }             *lpRetSize = n;         }     } }  int main(int argc, char *argv[]) {     char str[] = "123456ABCDEF";     unsigned char ret[32];     size_t size = _countof(ret);     StrToHex(str, ret, &size);     for (int i = 0; i < size; i++) {         printf("%02X", ret[i]);     }     putchar('\n');     return 0; }

仅供参考#include <stdio.h> #include <stdlib.h> #include <conio.h> unsigned int iv,i; unsigned char BCD[5];//定长10位BCD码 unsigned char sv[11]; void main() {     iv=123456789;//最大10位无符号正整数     //INT2BCD     sprintf(sv,"%010u",iv);     for (i=0;i<10;i+=2) {         BCD[i/2]=(sv[i]<<4)|(sv[i+1]&0x0F);     }     printf("BCD=%02x%02x%02x%02x%02x\n",BCD[0],BCD[1],BCD[2],BCD[3],BCD[4]);     //BCD2INT     for (i=0;i<10;i+=2) {         sv[i]='0'|(BCD[i/2]>>4);         sv[i+1]='0'|(BCD[i/2]&0x0F);     }     sscanf(sv,"%010u",&iv);     printf("iv=%010u\n",iv);     getch(); }

const DWORD TEM_LEN = 10; 	const DWORD TEM2_LEN = 10;  	char tmp[TEM_LEN] = "1234567"; 	unsigned char tmp2[TEM2_LEN] = {0, 0, 0};  	if (TEM2_LEN > strlen(tmp) / 2) 	{ 		int i = 0; 		while (true) 		{ 			if (i < strlen(tmp)) 			{ 				if (i + 1 < strlen(tmp)) 				{ 					if ('0' <= tmp[i] && tmp[i] <= '9' &&  						'0' <= tmp[i + 1] && tmp[i + 1] <= '9') 					{ 						tmp2[i / 2] = (tmp[i] - '0') * 16 + (tmp[i + 1] - '0'); 					} 					else 					{ 						tmp2[i / 2] = 0; 						break; 					} 				} 				else 				{ 					tmp2[i / 2] = tmp[i] - '0'; 					break; 				} 			} 			else 			{ 				break; 			}  			i = i + 2; 		} 	}

如果不需要自己写转换代码，那么考虑使用库函数先转为2进制，然后把2进制数据格式化为字符串。

String2Hex(const std::string &str, unsigned char *buf, unsigned int &len) { 	unsigned char OneData = 0; 	len = 0; 	int ChL = 0; 	for (int i = 0; i < str.length(); i++) 	{ 		char C = static_cast<char>(str.at(i)); 		if (C == ' ') 		{ 			if (ChL != 0) 			{ 				buf[len++] = OneData; 				ChL = 0; 			}			 			continue; 		} 		 		OneData <<= 4; 		OneData += Char2Hex(C);		 		ChL++; 		if (ChL == 2) 		{ 			buf[len++] = OneData; 			ChL = 0; 		} 	} }   unsigned char Char2Hex(const char C) { 	unsigned char Data; 	if (C >= '0' && C <= '9') 	{     	Data = C - '0'; 	} 	else if (C >= 'A' && C <= 'Z') 	{         Data = C - 'A' + 10; 	} 	else if (C >= 'a' && C <= 'z') 	{         Data = C - 'a' + 10; 	} 	return Data; }


Question: c语言基础问题

给你个具体的例子：  5.865 > 5.865f 5.86 < 5.86f 5.0 == 5.0f


Question: 代码中有紧接着的两个独立的if语句，两个if分别判断两个按键是否被按下，是不是下面的if不会被执行？

引用 3 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 受教了

几句话的事情，自己动手比较好

if() { } if() { } 是这样的结构？这两个没有啥关系，只要上边的if没有return，下边的就会被执行到

感谢两位,又学到了点东西

如果第一个if中修改了第二个if的判断条件，则第二个if有可能不执行  如果第一个if中有流程控制语句，类似break，return，continue，goto，throw等等，则第二个if有可能不执行  如果第一个if中有越界，或者是栈溢出，恰好修改到了接下来的代码段地址，则第二个if有可能不执行  否则都是顺序执行下去的

如果第一个if语句中没有跳过或返回的话，一般是按顺序执行的。 	 if (...) 	{  //以下情况第二个if不会执行 		//goto  RET  //goto跳过了第二个if语句 		return ;   //return直接返回  	} 	if () 	{ 	} RET: 	return ;  除非是if后面用else if语句才会是第一个if执行完第二个就不执行了： 	if (...) 	{  	} 	else if (...) 	{ 	} 	return ;