Question: 请教，静态(全局变量)和栈变量有什么区别吗？

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

理解和讨论之前请先学会如何观察！  VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

引用 10 楼 startstop2015 的回复:[quote=引用 9 楼 adlay 的回复:] [quote=引用 6 楼 startstop2015 的回复:] [quote=引用 5 楼 sholber 的回复:] [quote=引用 4 楼 adlay 的回复:] 全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。[/quote] 请教，怎样指定栈的大小 ?[/quote]    自己创建线程的话：  HANDLE CreateThread(   LPSECURITY_ATTRIBUTES lpThreadAttributes,   SIZE_T dwStackSize,   LPTHREAD_START_ROUTINE lpStartAddress,   LPVOID lpParameter,   DWORD dwCreationFlags,   LPDWORD lpThreadId );   里面的第二个参数 dwStackSize[/quote] 多谢，如果要指定栈的大小，必须自己创建线程吗？[/quote] 不是啊，主线程栈的大小就在截图那里设置  新线程是你有需要才创建，创建的时候可以指定大小。

引用 9 楼 adlay 的回复:[quote=引用 6 楼 startstop2015 的回复:] [quote=引用 5 楼 sholber 的回复:] [quote=引用 4 楼 adlay 的回复:] 全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。[/quote] 请教，怎样指定栈的大小 ?[/quote]    自己创建线程的话：  HANDLE CreateThread(   LPSECURITY_ATTRIBUTES lpThreadAttributes,   SIZE_T dwStackSize,   LPTHREAD_START_ROUTINE lpStartAddress,   LPVOID lpParameter,   DWORD dwCreationFlags,   LPDWORD lpThreadId );   里面的第二个参数 dwStackSize[/quote] 多谢，如果要指定栈的大小，必须自己创建线程吗？

引用 6 楼 startstop2015 的回复:[quote=引用 5 楼 sholber 的回复:] [quote=引用 4 楼 adlay 的回复:] 全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。[/quote] 请教，怎样指定栈的大小 ?[/quote]    自己创建线程的话：  HANDLE CreateThread(   LPSECURITY_ATTRIBUTES lpThreadAttributes,   SIZE_T dwStackSize,   LPTHREAD_START_ROUTINE lpStartAddress,   LPVOID lpParameter,   DWORD dwCreationFlags,   LPDWORD lpThreadId );   里面的第二个参数 dwStackSize

引用 5 楼 sholber 的回复:[quote=引用 4 楼 adlay 的回复:] 全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。[/quote] 他说的是所有全局变量的大小，并不指单个

全局静态变量的作用域只在本文件内，生存期为变量定义到结束 栈变量的作用域只在函数内，生存期为变量定义到函数结束

引用 5 楼 sholber 的回复:[quote=引用 4 楼 adlay 的回复:] 全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。[/quote] 请教，怎样指定栈的大小 ?

引用 4 楼 adlay 的回复:全局变量理论上大小是不受限制的，但实际上内存空间有限，你不能说弄几个 G 的全局变量出来。如果是带初始化的全局变量，最终是会保存到生成的可执行文件里面的，影响 exe 的大小。  栈的空间是每个线程一个的，创建线程的时候有参数可以指定大小。主线程的大小可以在连接器中设置，默认是 1~2M 左右吧。  “全局变量理论上大小是不受限制”？哪个理论？ 标准已经规定，对象的大小不能超过65535个字节，对象包括（但不限于）数组、结构、联合、枚举、指针，等等。也许可以超过，但那未必是安全的。

静态区/全局区大小是编译/链接时确定的，你有多少东西, 它就多大, 超过平台限制就不能编译或者运行,

静态变量和栈变量的生命周期不同，一个是永生的一个是临时的；他们在内存中的位置不同，一个在静态变量 区，一个是函数执行时调整栈大小来容纳栈变量。静态变量那个区域多大我也没研究过，不懂

你问的这些术语没听说过。而且也和C语言无关。


Question: TI NDK编程中UDP socket使用MSG_DONTWAIT flag调用recvfrom无法接收数据，求解如何破？

自己试验出来了，虽然原理上不太懂，解决方法是： 去掉代码中的设置SOL_BLOCKING的setsockopt函数调用，这个TI NDK自定义的属性似乎影响NDK的底层工作流程，去掉之后无论是否使用MSG_DONTWAIT调用recvfrom都可以成功读取报文。


Question: 运行时出现乱码

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

printf("%c\n", data[i].name);//%c换成%s

乱码截个图。 你是什么环境？换字符集GBK.UTF8试试


Question: const的问题，我照超书上的为什么还有错

就很快就好

书上的肯定有错呀

另外，按照你的要求“我的本意是指针作为函数变元时，传递值时，不改变指针的值”，函数声明应该为：  bool siblings(Family* const pmember1, Family* const pmember2) { //…… }  因为 Family const *pmember1 和 const  Family *pmember1 是一样的，都是保护指针指向的对象，Family* const pmember1才是保护指针本身

参数类型为指针类型，你调用时传入 *pmember1,*pmember2 相当于传递了值类型，吧星号去掉就可以了，如下形式：  if(siblings(pmember1,pmember2))      //这里编译时出错，


Question: 好久没问问题了，研究半天了

恭喜恭喜恭喜

感谢前辈们的解答 疑惑已经解决了 深切体会了C语言的规则

你看看我这个够不够清晰？  #define UINT_TO_POINTER(v) ((void *)(v)) #define POINTER_TO_UINT(v) ((unsigned int)(v))  struct slist {     struct slist *next;     void *data; };  struct slist *slist_prepend (struct slist *head, void *data) {     struct slist *p = malloc (sizeof (*p));      p->next = head;     p->data = data;      return p; }  struct slist *slist_delete_link (struct slist *head, struct slist *link) {     struct slist *tmp = head, *prev = NULL;      while (tmp) {         if (tmp == link) {             if (prev)                 prev->next = tmp->next;             else                 head = head->next;             tmp->next = NULL;             break;         }          prev = tmp;          tmp = tmp->next;     }      free (link);      return head; }  int main () {     unsigned int i, v;     struct slist *head = NULL;      scanf ("%u", &i);     while (i--) {         scanf ("%u", &v);         head = slist_prepend (head, UINT_TO_POINTER (v));     }      while (head) {         v = POINTER_TO_UINT (head->data);         printf ("%u ", v);         head = slist_delete_link (head, head);     }     putchar ('\n');      return 0; }

修改如下：  typedef struct node { 	int data; 	struct node *next; }Lnode, *Linklist; Linklist Creat() { 	Lnode *p, *s; 	int x; 	Linklist H = (Linklist)malloc(sizeof(Lnode));  //头节点 	H->next = NULL; 	p = H; 	scanf("%d", &x); 	while (x != -1) 	{ 		s = (Linklist)malloc(sizeof(Lnode)); 		s->data = x; 		p->next = s; 		p = s; 		scanf("%d", &x); 	} 	p->next = NULL; 	return H; } void PrintList(Linklist list) { 	if (NULL == list->next) return; 	Lnode *p = list->next; 	while (p->next) 	{ 		printf("%d->", p->data); 		p = p->next; 	} 	printf("%d\n", p->data); } int main(void) { 	Linklist X, Y; 	Lnode *temp; 	//X = (Linklist)malloc(sizeof(Lnode)); 	//Y = (Linklist)malloc(sizeof(Lnode)); 	printf("Enter the A line data :\n"); 	X = Creat(); 	PrintList(X); 	printf("Enter the B line data :\n"); 	Y = Creat(); 	PrintList(Y); 	return 0; } //Enter the A line data: //1 //2 //3 //4 //-1 //1->2->3->4 //Enter the B line data: //9 //8 //7 //6 //-1 //9->8->7->6  节点未释放，注意添加释放函数

Lnode是普通类型 Linklist是指针类型


Question: 怎么确保红黑树的根节点总是黑色的？

黑根只是为了实现方便，的确不影响功能和复杂度。 有红根的话就不能假设红点必有父了，那块需要改写。

红结点要求子结点必须是黑的, 黑的没这要求, 要保证根是红的,原来的调整算法就有问题了,

红黑树插入节点 #include <iostream> #include <queue> using namespace std; static int _rb_black_node = 0; static int _rb_red_node   = 1; template<typename T> struct RBNode { 	RBNode():left(NULL),right(NULL),parent(NULL),val(T()),color(_rb_red_node){} 	RBNode(const T &v1):left(NULL),right(NULL),parent(NULL),val(v1),color(_rb_red_node){} 	RBNode	*left; 	RBNode	*right; 	RBNode	*parent; 	int		color; 	T		val; };  template<typename T> class RBTree { public: 	RBTree():root(NULL){} 	~RBTree() 	{ 		if(root) 		{ 			Destroy(root); 		} 	} 	void	print(); 	void	Search(const T &v1, RBNode<T> *&node); 	bool	InsertUnique(const T &v1); 	void	DeleteValue(const T &v1); 	void	Destroy(RBNode<T> *p); 	void	InsertReBalance(RBNode<T> *node); 	RBNode<T>*	_rbtree_rotate_left(RBNode<T> *node); 	RBNode<T>*  _rbtree_rotate_right(RBNode<T> *node); private: 	RBNode<T>	*root; };  /* * * 打印红黑树的节点信息 * */ template<typename T> void RBTree<T>::print() { 	RBNode<T> *p; 	queue<RBNode<T> *> Q; 	Q.push(root); 	while(!Q.empty()) 	{ 		p = Q.front(); 		Q.pop(); 		cout<<"节点: "<<p->val<<" "; 		if(p->left) 		{ 			cout<<"left:"<<p->left->val<<"->color:"<<p->left->color<<" "; 			Q.push(p->left); 		} 		if(p->right) 		{ 			cout<<"right:"<<p->right->val<<"->color:"<<p->right->color<<" "; 			Q.push(p->right); 		} 		cout<<endl<<endl; 	} }  /* * * 搜索v1在红黑树中出现的位置，如果v1在红黑树中则node节点为 * 值为v1所在红黑树中的节点。 * 否则node节点为如果将v1插入到红黑树中的父节点 * */ template<typename T> void RBTree<T>::Search(const T &v1,RBNode<T> *&node) { 	RBNode<T> *p = root; 	node = NULL; 	while(p) 	{ 		if(p->val == v1) 		{ 			node = p; 			break; 		} 		else if(p->val < v1) 		{ 			node = p; 			p = p->right; 		} 		else 		{ 			node = p; 			p = p->left; 		} 	} }  template<typename T> bool RBTree<T>::InsertUnique(const T &v1) { 	RBNode<T> *parent = NULL; 	RBNode<T> *newNode = new RBNode<T>(v1); 	Search(v1, parent); 	if(parent == NULL) 	{//红黑树为空，当前插入的节点为根节点。插入后将根颜色变为黑 		root = newNode; 		root->color = _rb_black_node; 		return true; 	} 	if(parent->val == v1)//v1已经存在红黑树中。不再插入 		return false; 	 	if(v1 < parent->val) 	{ 		parent->left = newNode; 	} 	else 	{ 		parent->right = newNode; 	} 	newNode->parent = parent; 	InsertReBalance(newNode); 	return true; }  /* * * 插入节点后进行调整， * 使所有节点满足红黑树的性质 * */ template<typename T> void RBTree<T>::InsertReBalance(RBNode<T> *node) { 	RBNode<T> *parent = node->parent; 	RBNode<T> *grandParent = NULL; 	while(parent && parent->color==_rb_red_node) 	{ 		grandParent = parent->parent; 		if(parent == grandParent->left) 		{//父节点为祖父节点的左儿子 			RBNode<T> *uncle = grandParent->right; 			if(uncle && uncle->color == _rb_red_node) 			{//情形1 父节点与叔节点都为红 				//解决方法父与叔变黑，祖父变黑。祖父变为新的当前节点重新进入算法 				parent->color = _rb_black_node; 				uncle->color  = _rb_black_node; 				grandParent->color = _rb_red_node; 				node = grandParent; 				parent = grandParent->parent; 			} 			else 			{ 				if(node == parent->right) 				{//情形2，叔为黑，当前节点为其父节点的右子节点 					//解决方法：以父节点为根进行左旋 					//操作后将转换为情形3 					node = _rbtree_rotate_left(parent); 					parent = node->parent; 					grandParent = parent->parent; 				} 				//情形3父为红，当前节点为父节点的左子节点 				//解决方法：父节点变黑，祖父节点变红，以 				//祖父节点为根节点进行右旋 				parent->color = _rb_black_node; 				grandParent->color = _rb_red_node; 				_rbtree_rotate_right(grandParent); 			} 		} 		else 		{//父节点为祖父节点的右子节点，情况与上面相同 			RBNode<T> *uncle = grandParent->left; 			if(uncle && uncle->color == _rb_red_node) 			{ 				uncle->color = _rb_black_node; 				parent->color = _rb_black_node; 				grandParent->color = _rb_red_node; 				node = grandParent; 				parent = node->parent; 			} 			else 			{ 				if(node == parent->left) 				{ 					node = _rbtree_rotate_right(parent); 					parent = node->parent; 					grandParent = parent->parent; 				} 				parent->color = _rb_black_node; 				grandParent->color = _rb_red_node; 				_rbtree_rotate_left(grandParent); 			} 		} 	} 	root->color = _rb_black_node; }  /* * * 左旋 * */ template<typename T> RBNode<T> *RBTree<T>::_rbtree_rotate_left(RBNode<T> *x) { 	RBNode<T> *y = x->right; 	if(y == NULL) 	{ 		return x; 	} 	//x的右节点为y的左节点 	x->right = y->left; 	if(y->left)//如果y的左节点存在，其父节点为y 		y->left->parent = x; 	if(root == x) 	{//x为root，旋转后y为新的root根节点 		root = y; 	} 	else 	{ 		if(x == x->parent->left) 		{//如果x为其父节点的左子节点。 			//x的父节点的新左子节点为y 			x->parent->left = y; 		} 		else 		{ 			x->parent->right = y; 		} 		//y的父节点为x的父节点 		y->parent = x->parent; 	} 	//y的左子节点为x 	y->left = x; 	//x的父节点为y 	x->parent = y; 	return x; }  /* * * 右旋 * 分析其逻辑与左旋代码类似 * */ template<typename T> RBNode<T>* RBTree<T>::_rbtree_rotate_right(RBNode<T> *x) { 	RBNode<T> *y = x->left; 	if(y == NULL) 	{ 		return x; 	} 	x->left = y->right; 	if(y->right) 		y->right->parent = x; 	if(root == x) 	{ 		root = y; 	} 	else 	{ 		if(x == x->parent->left) 		{ 			x->parent->left = y; 		} 		else 		{ 			x->parent->right = y; 		} 		y->parent = x->parent; 	} 	y->right = x; 	x->parent = y; 	return x; }  /* * * 销毁整棵红黑树 * */ template<typename T> void RBTree<T>::Destroy(RBNode<T> *p) { 	if(p->left) 	{ 		Destroy(p->left); 	} 	if(p->right) 	{ 		Destroy(p->right); 	} 	delete p; }  红黑树删除节点 template<typename T> void RBTree<T>::DeleteValue(const T &v1) { 	RBNode<T>		*p = NULL; 	RBNode<T>		*nextNode = NULL; 	Search(v1,p); 	if(p==NULL) 	{ 		cout<<"删除的值不存在"<<endl; 		return; 	} 	if(p->left && p->right) 	{ 		RBNode<T> *tempNode = p->right; 		while(tempNode) 		{//中序序列的后继节点 			nextNode = tempNode; 			tempNode = tempNode->left; 		} 		p->val = nextNode->val; 		p = nextNode; 	} 	if(p->left) 	{ 		//直接用后继节点的值替换 		RBNode<T> *temp = p->left; 		p->val = temp->val; 		p->left = NULL; 		delete temp; 	} 	else if(p->right) 	{ 		//直接用后继节点的值替换 		RBNode<T> *temp = p->right; 		p->val = temp->val; 		p->right = NULL; 		delete temp; 	} 	else 	{ 		//左右子树都不存在，需要进入删除调整算法 		DeleteReblance(p); 		if(p==root) 		{ 			root = NULL; 		} 		else if(p==p->parent->left) 		{//父节点的指针域需要修改 			p->parent->left = NULL; 		} 		else if(p==p->parent->right) 		{//父节点的指针域需要修改 			p->parent->right = NULL; 		} 		delete p; 	} }  template<typename T> void RBTree<T>::DeleteReblance(RBNode<T> *node) { 	RBNode<T> *parent = NULL; 	RBNode<T> *other = NULL; 	while(node->color==_rb_black_node && node->parent) 	{ 		parent = node->parent; 		if(node == parent->left) 		{ 			other = parent->right; 			if(other->color==_rb_red_node) 			{//情形1兄弟节点为红 				parent->color = _rb_red_node; 				other->color = _rb_black_node; 				_rbtree_rotate_left(parent); 				other = parent->right; 			} 			if( (other->left==NULL || other->left->color==_rb_black_node) 				&& (other->right==NULL || other->left->color==_rb_black_node)) 			{//情形2兄弟为黑，且兄弟的两个孩子也为黑 				other->color=_rb_red_node; 				node = parent; 				continue; 			} 			if( other->right==NULL || other->right->color==_rb_black_node) 			{//情形3兄弟节点的右孩子为黑，左为红 				other->left->color=_rb_black_node;//此时左孩子一定存在且颜色为红，如果不满足就不会进入这个条件 				other->color = _rb_red_node; 				_rbtree_rotate_right(other); 				other = parent->right; 			} 			//情形4兄弟节点的右孩子为红 			other->right->color=_rb_black_node; 			other->color = parent->color; 			parent->color = _rb_black_node; 			_rbtree_rotate_left(parent); 			break; 		} 		else 		{ 			other = parent->left; 			if(other->color==_rb_red_node) 			{//情形1兄弟节点为红 				parent->color = _rb_red_node; 				other->color = _rb_black_node; 				_rbtree_rotate_right(parent); 				other = parent->left; 			} 			if( (other->left==NULL || other->left->color==_rb_black_node) 				&& (other->right==NULL || other->left->color==_rb_black_node)) 			{//情形2兄弟为黑，且兄弟的两个孩子也为黑 				other->color=_rb_red_node; 				node = parent; 				continue; 			} 			if( other->left==NULL || other->left->color==_rb_black_node) 			{//情形3兄弟节点的右孩子为黑，左为红 				other->right->color=_rb_black_node;//此时左孩子一定存在且颜色为红，如果不满足就不会进入这个条件 				other->color = _rb_red_node; 				_rbtree_rotate_left(other); 				other = parent->left; 			} 			//情形4兄弟节点的右孩子为红 			other->left->color=_rb_black_node; 			other->color = parent->color; 			parent->color = _rb_black_node; 			_rbtree_rotate_right(parent); 			break; 		} 	} 	node->color = _rb_black_node; }


Question: 请教如何为C语言的结构体数组分配/释放内存？谢谢

如果结构体中有一个char类型的指针，请问怎么释放这个结构体中的内存，需要保证内存不被泄漏

引用 19 楼 startstop2015 的回复:[quote=引用 18 楼 u013470052 的回复:] 大神我这样定义似乎可以了，这样定义，我没法根据表的记录数来分配内存了，必须写死记录数了？ struct emp  {   char name[1000000][10];   float salary[1000000];  }; 但是和如下定义有什么区别马？ struct emp_record   {   char name[10];   float salary;  }; 个人感觉本质上来说没区别，但是一般不选择上面的，不方便。[/quote] 下面的不能用，除非是静态变量[/quote] 为什么：？？？

引用 5 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;      array_emp=malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     strcpy(array_emp[999999].name,"123456789");     array_emp[999999].salary=50000.0f;     free(array_emp);     return 0; }  看到5w的salary，其它的就不想看了，人生的差距最大不过如此……

吹牛不犯法，吹牛不用上税，你吹我吹大家吹！

引用 21 楼 zhao4zhong1 的回复:[quote=引用 20 楼 zhangxiangDavaid 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;      array_emp=malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     strcpy(array_emp[999999].name,"123456789");     array_emp[999999].salary=50000.0f;     free(array_emp);     return 0; }  看到5w的salary，其它的就不想看了，人生的差距最大不过如此……[/quote] 现在人不都和余佳文一样嘛！[/quote] 他说分一亿，我说：给我5w就行！

引用 20 楼 zhangxiangDavaid 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;      array_emp=malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     strcpy(array_emp[999999].name,"123456789");     array_emp[999999].salary=50000.0f;     free(array_emp);     return 0; }  看到5w的salary，其它的就不想看了，人生的差距最大不过如此……[/quote] 现在人不都和余佳文一样嘛！

引用 18 楼 u013470052 的回复:大神我这样定义似乎可以了，这样定义，我没法根据表的记录数来分配内存了，必须写死记录数了？ struct emp  {   char name[1000000][10];   float salary[1000000];  }; 但是和如下定义有什么区别马？ struct emp_record   {   char name[10];   float salary;  }; 个人感觉本质上来说没区别，但是一般不选择上面的，不方便。[/quote] 下面的不能用，除非是静态变量

大神我这样定义似乎可以了，这样定义，我没法根据表的记录数来分配内存了，必须写死记录数了？ struct emp  {   char name[1000000][10];   float salary[1000000];  }; 但是和如下定义有什么区别马？ struct emp_record   {   char name[10];   float salary;  }; [/quote] 个人感觉本质上来说没区别，但是一般不选择上面的，不方便。

引用 11 楼 zhao4zhong1 的回复:每弄过→没弄过 大神我这样定义似乎可以了，这样定义，我没法根据表的记录数来分配内存了，必须写死记录数了？ struct emp  {   char name[1000000][10];   float salary[1000000];  }; 但是和如下定义有什么区别马？ struct emp_record   {   char name[10];   float salary;  };

引用 15 楼 u014749886 的回复:[quote=引用 14 楼 startstop2015 的回复:] [quote=引用 11 楼 zhao4zhong1 的回复:] 每弄过→没弄过 static struct emp     {         char name[10];         float salary;     };      static struct emp array_emp[1000000]; 大神，如果这样定义，是可以SELECT INTO :array_emp 100万条记录的 但是您的定义方法不行，没法SELECT INTO 100万行，只能INTO 1条记录 [/quote]是因为只有1条数据的缘故吧[/quote]  有100多万行记录

引用 14 楼 startstop2015 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 每弄过→没弄过 static struct emp     {         char name[10];         float salary;     };      static struct emp array_emp[1000000]; 大神，如果这样定义，是可以SELECT INTO :array_emp 100万条记录的 但是您的定义方法不行，没法SELECT INTO 100万行，只能INTO 1条记录 [/quote]是因为只有1条数据的缘故吧

引用 11 楼 zhao4zhong1 的回复:每弄过→没弄过 static struct emp     {         char name[10];         float salary;     };      static struct emp array_emp[1000000]; 大神，如果这样定义，是可以SELECT INTO :array_emp 100万条记录的 但是您的定义方法不行，没法SELECT INTO 100万行，只能INTO 1条记录

来看看11楼的回答

struct Point{ int x; int y; }  Point* pt; pt = (Point*)malloc(10 * sizeof(Point)); //do sth free(pt);   然后就可以用下标来操作了 pt[0].x = 12;

每弄过→没弄过

也许PRO*C和标准C不同。每弄过PRO*C，爱莫能助。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;     int i;      array_emp=(struct emp *)malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     for (i=0;i<1000000;i+=10000) {         sprintf(array_emp[i].name,"%d",i);         array_emp[i].salary=(float)i;     }     for (i=0;i<1000000;i+=10000) {         printf("%d %s %f\n",i,array_emp[i].name,array_emp[i].salary);     }     free(array_emp);     return 0; } //0 0 0.000000 //10000 10000 10000.000000 //20000 20000 20000.000000 //30000 30000 30000.000000 //40000 40000 40000.000000 //50000 50000 50000.000000 //60000 60000 60000.000000 //70000 70000 70000.000000 //80000 80000 80000.000000 //90000 90000 90000.000000 //100000 100000 100000.000000 //110000 110000 110000.000000 //120000 120000 120000.000000 //130000 130000 130000.000000 //140000 140000 140000.000000 //150000 150000 150000.000000 //160000 160000 160000.000000 //170000 170000 170000.000000 //180000 180000 180000.000000 //190000 190000 190000.000000 //200000 200000 200000.000000 //210000 210000 210000.000000 //220000 220000 220000.000000 //230000 230000 230000.000000 //240000 240000 240000.000000 //250000 250000 250000.000000 //260000 260000 260000.000000 //270000 270000 270000.000000 //280000 280000 280000.000000 //290000 290000 290000.000000 //300000 300000 300000.000000 //310000 310000 310000.000000 //320000 320000 320000.000000 //330000 330000 330000.000000 //340000 340000 340000.000000 //350000 350000 350000.000000 //360000 360000 360000.000000 //370000 370000 370000.000000 //380000 380000 380000.000000 //390000 390000 390000.000000 //400000 400000 400000.000000 //410000 410000 410000.000000 //420000 420000 420000.000000 //430000 430000 430000.000000 //440000 440000 440000.000000 //450000 450000 450000.000000 //460000 460000 460000.000000 //470000 470000 470000.000000 //480000 480000 480000.000000 //490000 490000 490000.000000 //500000 500000 500000.000000 //510000 510000 510000.000000 //520000 520000 520000.000000 //530000 530000 530000.000000 //540000 540000 540000.000000 //550000 550000 550000.000000 //560000 560000 560000.000000 //570000 570000 570000.000000 //580000 580000 580000.000000 //590000 590000 590000.000000 //600000 600000 600000.000000 //610000 610000 610000.000000 //620000 620000 620000.000000 //630000 630000 630000.000000 //640000 640000 640000.000000 //650000 650000 650000.000000 //660000 660000 660000.000000 //670000 670000 670000.000000 //680000 680000 680000.000000 //690000 690000 690000.000000 //700000 700000 700000.000000 //710000 710000 710000.000000 //720000 720000 720000.000000 //730000 730000 730000.000000 //740000 740000 740000.000000 //750000 750000 750000.000000 //760000 760000 760000.000000 //770000 770000 770000.000000 //780000 780000 780000.000000 //790000 790000 790000.000000 //800000 800000 800000.000000 //810000 810000 810000.000000 //820000 820000 820000.000000 //830000 830000 830000.000000 //840000 840000 840000.000000 //850000 850000 850000.000000 //860000 860000 860000.000000 //870000 870000 870000.000000 //880000 880000 880000.000000 //890000 890000 890000.000000 //900000 900000 900000.000000 //910000 910000 910000.000000 //920000 920000 920000.000000 //930000 930000 930000.000000 //940000 940000 940000.000000 //950000 950000 950000.000000 //960000 960000 960000.000000 //970000 970000 970000.000000 //980000 980000 980000.000000 //990000 990000 990000.000000 //

引用 7 楼 zhao4zhong1 的回复:第12行array_emp=malloc(1000000*sizeof(struct emp)); 应改为 array_emp=(struct emp *)malloc(1000000*sizeof(struct emp)); 大神，按照您说的，这样我只保存了一条记录到这个结构体数组 EXEC SQL Select name, salary into :array_emp from t where rownum<=1000000;

引用 5 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;      array_emp=malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     strcpy(array_emp[999999].name,"123456789");     array_emp[999999].salary=50000.0f;     free(array_emp);     return 0; }  大神，我用的是PRO*C，这样写，保存到结构体数组里的记录只有1条，不是100万条

引用 5 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> struct emp {     char name[10];     float salary; }; int main() {     struct emp *array_emp;      array_emp=malloc(1000000*sizeof(struct emp));     if (NULL==array_emp) {         printf("Can not malloc 1000000 emp!\n");         return 1;     }     strcpy(array_emp[999999].name,"123456789");     array_emp[999999].salary=50000.0f;     free(array_emp);     return 0; }  谢谢大神，这样就算是定义了这个数组的元素个数了？


Question: 请问int *p[][]与int **p1这两个是一样的吗？

int *p[][]中的p是一个二维数组，数组的元素师int型指针，int **p是一个双重指针，它有可能指向一个二维数组，不过数组的元素类型是int，而不是int*

//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

楼主是想说二级指针和二维数组？

int *p[][] 通不过编译的


Question: VS中scanf的问题

都宏定义_CRT_SECURE_NO_WARNINGS了，不用鸟微软的_s函数, 用_s函数的人有多少检查了返回值

查MSDN是Windows程序员必须掌握的技能之一。  Run-Time Library Reference  scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l  Example  See Also  Send Feedback     Read formatted data from the standard input stream. These are versions of scanf, _scanf_l, wscanf, _wscanf_l with security enhancements as described in Security Enhancements in the CRT.    int scanf_s(    const char *format [,       argument]...  ); int _scanf_s_l(    const char *format,    locale_t locale [,       argument]...  ); int wscanf_s(    const wchar_t *format [,       argument]...  ); int _wscanf_s_l(    const wchar_t *format,    locale_t locale [,       argument]...  );    Parameters format Format control string.  argument Optional arguments.  locale The locale to use.  Return Value Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end-of-file character or the end-of-string character is encountered in the first attempt to read a character. If format is a NULL pointer, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, scanf_s and wscanf_s return EOF and set errno to EINVAL.  For information on these and other error codes, see _doserrno, errno, _sys_errlist, and _sys_nerr.  Remarks The scanf_s function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. If copying takes place between strings that overlap, the behavior is undefined.  wscanf_s is a wide-character version of scanf_s; the format argument to wscanf_s is a wide-character string. wscanf_s and scanf_s behave identically identically if the stream is opened in ANSI mode. scanf_s doesn't currently support input from 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.  Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or [. The buffer size is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if reading a string, the buffer size for that string is passed as follows:  char s[10];  scanf("%9s", s, 10);  The buffer size includes the terminating null. A width specification field may be used to ensure that the token read in will fit into the buffer. If no width specification field is used, and the token read is too big to fit in the buffer, nothing will be written to that buffer.  Note:  The size parameter is of type unsigned, not size_t.    In the case of characters, one may read a single character as follows:  char c;  scanf("%c", &c, 1);  When reading multiple characters for non-null terminated strings, integers are used as the width specification and the buffer size.  char c[4];  scanf("%4c", &c, 4); // not null terminated  For more information, see scanf Width Specification.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _UNICODE defined   _tscanf_s  scanf_s  scanf_s  wscanf_s   _tscanf_s_l  _scanf_s_l  _scanf_s_l  _wscanf_s_l    For more information, see Format Specification Fields — scanf functions and wscanf Functions.   Requirements Routine  Required header   scanf_s, _scanf_s_l  <stdio.h>   wscanf_s, _wscanf_s_l  <stdio.h> or <wchar.h>    For additional compatibility information, see Compatibility in the Introduction.  Example   Copy Code  // crt_scanf_s.c // This program uses the scanf_s and wscanf_s functions // to read formatted input.    #include <stdio.h>  int main( void ) {    int      i,             result;    float    fp;    char     c,             s[81];    wchar_t  wc,             ws[81];     result = scanf_s( "%d %f %c %C %s %S", &i, &fp, &c, 1,                      &wc, 1, s, 80, ws, 80 );    printf( "The number of fields input is %d\n", result );    printf( "The contents are: %d %f %c %C %s %S\n", i, fp, c,            wc, s, ws);    result = wscanf_s( L"%d %f %hc %lc %S %ls", &i, &fp, &c, 2,                       &wc, 1, s, 80, ws, 80 );    wprintf( L"The number of fields input is %d\n", result );    wprintf( L"The contents are: %d %f %C %c %hs %s\n", i, fp,             c, wc, s, ws); }     Copy Code  71 98.6 h z Byte characters 36 92.3 y n Wide characters     Copy Code  The number of fields input is 6 The contents are: 71 98.599998 h z Byte characters The number of fields input is 6 The contents are: 36 92.300003 y n Wide characters    .NET Framework Equivalent System::Console::Read  System::Console::ReadLine  See also Parse methods, such as System::Double::Parse.  See Also Concepts Floating-Point Support Stream I/O Locale fscanf, _fscanf_l, fwscanf, _fwscanf_l printf, _printf_l, wprintf, _wprintf_l sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l sscanf, _sscanf_l, swscanf, _swscanf_l Send feedback on this topic to Microsoft.

引用 4 楼 xxyj6450 的回复:引用 1 楼 ant2012 的回复:scanf_s如果是给静态数组输入值就不需要后面的长度，如果是给字符串指针（动态开辟的内存）输入数据就需要后面的长度另外，不管我输入啥，它读到的都是0，请问它是从哪读到这个值的？  数据是来自控制台呢

引用 1 楼 ant2012 的回复:scanf_s如果是给静态数组输入值就不需要后面的长度，如果是给字符串指针（动态开辟的内存）输入数据就需要后面的长度哥，我的s1是个静态数组呀，怎么也不行。

引用 7 楼 xxyj6450 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 查MSDN是Windows程序员必须掌握的技能之一。. 噢，多谢，感谢大神，原来scanf_s输入字符要求带缓冲大小的参数。 但scanf是完全正常的，我传入scanf_s的变量长度是固定的，%s也明确指示了是要输入字符串，这些信息足够判断指针的长度，因此不应再让我输入它的长度。 而且既然是scanf的高级替代，则应在保留scanf特性的基础上再进行高级的控制，而不应带入这种不一致的副作用。 我对这种设计表示不理解。[/quote] 所以很多人包括我在内都 #pragma warning(disable:4996)

引用 6 楼 zhao4zhong1 的回复:查MSDN是Windows程序员必须掌握的技能之一。. 噢，多谢，感谢大神，原来scanf_s输入字符要求带缓冲大小的参数。 但scanf是完全正常的，我传入scanf_s的变量长度是固定的，%s也明确指示了是要输入字符串，这些信息足够判断指针的长度，因此不应再让我输入它的长度。 而且既然是scanf的高级替代，则应在保留scanf特性的基础上再进行高级的控制，而不应带入这种不一致的副作用。 我对这种设计表示不理解。


Question: 能问一个很奇怪的问题吗

你不可能运行到函数体返回，函数入口时要把所需要东西进行压栈，函数返回时会出栈，这句话表示这个函数运行不到出栈并返回参数给调用者，比如函数中有exit(0);

一般在函数中间直接调用exit退出进程，或者在线程函数中直接退出线程，不过具体要看上下文。最好给个例子。

例如：  int main(int argc, char* argv[]) {     while(1)     {         /* It will never return */     }      return 0; }

线程函数 主循环 ……

永远不会返回的函数，比如  void hello () {     exit (0); }

一般 单片机 运行代码（主程序中）， 这一类的程序，都是无限循环的不出错的话，永不退出，自然也就永不返回了。 操作系统的某一部分，本质上，也是无限循环的，只是可以在用户控制下，退出而已。 实际上，服务器系统，几乎一直在运行，不出问题，不升级系统，100年也还在运行。


Question: 这是一段多项式的不完整代码，编译没有错误，运行时智能正确显示第一项。求大牛解答？我在vs2013下编译。

多谢指导，可是自己心急了。

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


Question: socket客户端里connect内存冲突

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

引用 11 楼 q980764821 的回复:[quote=引用 8 楼 adlay 的回复:] [quote=引用 7 楼 q980764821 的回复:] [quote=引用 4 楼 www_adintr_com的回复:]10061 是目标机器对应的端口没打开，连接不上 端口我在防火墙里设置打开了 但是netstat -查了并没有那个端口   有影响么？     现在还是连不上    10061[/quote] 不光是防火墙打开，得有进程打开了这个端口，在这个端口上等待连接才行的。[/quote]   我服务器端一直开着的啊  还有什么可能会出错吗[/quote]  那你先试下在命令行中   telnet  服务器IP   服务器端口 看是否能连接上，如果不能就是服务器的问题，可以才是客户端的问题。 （如果提示找不到 telnet 命令，在控制面板，添加删除程序，系统组件 里面把  telnet 客户端 选上）    另外，如果你要连本机的话，直接用 127.0.0.1 的 IP 就行了。 如果你是要连 iiiiii.imwork.net 这个域名，你的代码是错的，gethostname 会把名字填成本机的。

客户端与服务端要对照着看一下。 检查端口打开没有。

10061 是目标机器对应的端口没打开，连接不上

引用 8 楼 adlay 的回复:[quote=引用 7 楼 q980764821 的回复:] [quote=引用 4 楼 www_adintr_com的回复:]10061 是目标机器对应的端口没打开，连接不上 端口我在防火墙里设置打开了 但是netstat -查了并没有那个端口   有影响么？     现在还是连不上    10061[/quote] 不光是防火墙打开，得有进程打开了这个端口，在这个端口上等待连接才行的。[/quote]   我服务器端一直开着的啊  还有什么可能会出错吗

//****************************客户端***********************************  #pragma warning(disable: 4996) #include<stdio.h> #include<stdlib.h> #include<WinSock2.h> #pragma comment(lib,"ws2_32.lib") void main() { 	WSADATA wsadata; 	int iResult = WSAStartup(MAKEWORD(2, 2), &wsadata); 	if (iResult != NO_ERROR) 		printf("Error at WSAStartup()\n");  	char name[33] = "iiiiii.imwork.net"; //定义用于存放获得的主机名的变量   	char *ip; //定义IP地址变量   	PHOSTENT hostinfo; 	if (gethostname(name, sizeof(name)) == 0) {  		if ((hostinfo = gethostbyname(name)) != NULL) {  			ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);   		} 	} 	printf("%s", ip);    	SOCKET server; 	server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 	if (server == INVALID_SOCKET){ 		printf("Error at socket():%1d"); 		WSACleanup(); 		return; 	}  	SOCKADDR_IN clientService; 	clientService.sin_family = AF_INET; 	clientService.sin_addr.s_addr = inet_addr(ip); 	clientService.sin_port = htons(27015);  	if (connect(server, (SOCKADDR*)&clientService, sizeof(SOCKADDR)) == SOCKET_ERROR){ 		printf("Failed to connect: %d\n", GetLastError()); 		getchar();  		WSACleanup(); 		closesocket(server);  		return; 	}  这代码比之前的代码多了一个域名解析      因为这帖子在网上查的到所以把域名改了下  。   请问可能会是什么原因呢 ？

引用 1 楼 adlay 的回复:printf("Error at socket():%1d");   %ld 的输出没有给参数  printf("Failed to connect: %s\n",GetLastError());  GetLastError 返回的是整数，用 %d 来输出，不是 %s    谢谢 改成%d管了 但是能不能帮我帮到底下 。。现在connect代码10061  可能是什么原因

后面我回追加30分给大家  希望大家帮我下  。

10061为目标端口的话  引用 5 楼 user-3 的回复:客户端与服务端要对照着看一下。 检查端口打开没有。  我在同一台机子上运行两程序   。27015 端口我在防火墙里打开了 我netstat看了下端口没有27015    运行后还是10061   可能是什么情况呢  。

引用 7 楼 q980764821 的回复:[quote=引用 4 楼 www_adintr_com的回复:]10061 是目标机器对应的端口没打开，连接不上 端口我在防火墙里设置打开了 但是netstat -查了并没有那个端口   有影响么？     现在还是连不上    10061[/quote] 不光是防火墙打开，得有进程打开了这个端口，在这个端口上等待连接才行的。

引用 4 楼 www_adintr_com的回复:10061 是目标机器对应的端口没打开，连接不上 端口我在防火墙里设置打开了 但是netstat -查了并没有那个端口   有影响么？     现在还是连不上    10061


Question: socket发送命令到telnet客户端问题

[quote=引用 2 楼 zhao4zhong1 的回复:]   已经解决，谢谢赵4老师和liubo_1993的帮助，感觉多少分都无法表达您们对我的帮助，谢谢您们！ 下面是我所进行的一点修改，希望以后别人搜到这个帖子时能够感受到我们共同的努力。 [code=c]DWORD CSocketTx::SendTh(CSocketTx *pSocketTx) {     char pBuff[256]="username\r\npassword\r\n";//这个地方看不同的东西，进入的方式不同做出修改     int nRet,i;     char ch;      i=0;     while(1) {//这里要判断一下，要不然会无限循环，写成while（‘\t’）,也可以写别的。。。         if ( pSocketTx->m_nExit == 1 ) {             ExitThread(0);             return 0;         }         //等待用户输入信息 //      WaitForSingleObject(stdin1,INFINITE); //      ch=getch();         ch=pBuff[i++];                  //将用户的输入信息发送给Telnet服务器         nRet = send(pSocketTx->m_hSocket,&ch,sizeof(ch),0);         if ( nRet == SOCKET_ERROR ) {             TRACE("\nSend Fail........!\n");             pSocketTx->m_nExit = 0;             continue;         }       //这里要记得加一下i的判断，个人感觉没什么用多少不过我加了for（i=50）{i=0；continue；}要将i置零。     }     return 0; }

引用 8 楼 markxiaokeng 的回复:[quote=引用 6 楼 liubo_1993 的回复:] 在你接受数据的线程，recv收到的串和login:，Password:比较，如果是login:就立马send一个用户名的串，如果是Password就send一个密码的串，如果是其他不做任何操作 您好，那意思就是我要定义一个数组为login[]="login";,password[]="password";,然后把这个放到recv这里是吗， nRet = recv(pSocketTx->m_hSocket,pBuf,sizeof(pBuf),0);这里来判断当我输完ip是ok的，返回login等待输入，然后就在sand函数模块下发送一个str1="root";str2="****";这样可行吗？但是我感觉这样做的话，while（1），循环我就不知道怎么弄了。[/quote]  用pBuf和你的两个string比较，如果和login相同就send一个用户名的串，如果和password相同就send一个密码的串，这些内容是写在你接受的线程中，不是在这个线程

引用 2 楼 zhao4zhong1 的回复:DWORD CSocketTx::SendTh(CSocketTx *pSocketTx) {     char pBuff[256]="username\r\npassword\r\n";     int nRet,i;     char ch;      i=0;     while(1) {         if ( pSocketTx->m_nExit == 1 ) {             ExitThread(0);             return 0;         }         //等待用户输入信息 //      WaitForSingleObject(stdin1,INFINITE); //      ch=getch();         ch=pBuff[i++];                  //将用户的输入信息发送给Telnet服务器         nRet = send(pSocketTx->m_hSocket,&ch,sizeof(ch),0);         if ( nRet == SOCKET_ERROR ) {             TRACE("\nSend Fail........!\n");             pSocketTx->m_nExit = 0;             continue;         }     }     return 0; }  赵老师您好，您的code是可以运行的，只要把//if (!ch) break;这一行去掉，是可以进到路由的，但是他会出现这样的情况 那个乱码我想把这个数组先清零char pBuff[256]={‘\0’};然后再赋值，但那个错误提示是怎么回事，难道是信息缓存区出现了问题，还有这个while（）是怎么处理的，以为会做一些无用的循环。。。。

求大神现身。

引用 6 楼 liubo_1993 的回复:在你接受数据的线程，recv收到的串和login:，Password:比较，如果是login:就立马send一个用户名的串，如果是Password就send一个密码的串，如果是其他不做任何操作 您好，那意思就是我要定义一个数组为login[]="login";,password[]="password";,然后把这个放到recv这里是吗， nRet = recv(pSocketTx->m_hSocket,pBuf,sizeof(pBuf),0);这里来判断当我输完ip是ok的，返回login等待输入，然后就在sand函数模块下发送一个str1="root";str2="****";这样可行吗？但是我感觉这样做的话，while（1），循环我就不知道怎么弄了。

引用 5 楼 markxiaokeng 的回复:[quote=引用 3 楼 liubo_1993 的回复:] ch定义成char *的不就可以了，从键盘接的时候用gets(ch); send(pSocketTx->m_hSocket,ch,sizeof(ch),0); 您好，您那个方法我也用过，不可以我不知道为什么我们可以输入进行输入用户名：root，但是我按回车时它不会提示我们输入密码，也就是程序到登录提示就停止了，是不是加个判断，当我输入字符串了，按enter键就发送指令。。。[/quote]  不需要判断的，不过读入字符串一定要用gets()

引用 3 楼 liubo_1993 的回复:ch定义成char *的不就可以了，从键盘接的时候用gets(ch); send(pSocketTx->m_hSocket,ch,sizeof(ch),0); 您好，您那个方法我也用过，不可以我不知道为什么我们可以输入进行输入用户名：root，但是我按回车时它不会提示我们输入密码，也就是程序到登录提示就停止了，是不是加个判断，当我输入字符串了，按enter键就发送指令。。。

引用 2 楼 zhao4zhong1 的回复:DWORD CSocketTx::SendTh(CSocketTx *pSocketTx) {     char pBuff[256]="username\r\npassword\r\n";     int nRet,i;     char ch;      i=0;     while(1) {         if ( pSocketTx->m_nExit == 1 ) {             ExitThread(0);             return 0;         }         //等待用户输入信息 //      WaitForSingleObject(stdin1,INFINITE); //      ch=getch();         ch=pBuff[i++];         if (!ch) break;         //将用户的输入信息发送给Telnet服务器         nRet = send(pSocketTx->m_hSocket,&ch,sizeof(ch),0);         if ( nRet == SOCKET_ERROR ) {             TRACE("\nSend Fail........!\n");             pSocketTx->m_nExit = 0;             continue;         }     }     return 0; }  赵4老师您好！我用了你改的程序，无法进入到路由器，运行的时候是第一幅图，是不是我把username改成root，password改成我的密码造成的。第二幅图是我原本的程序运行出来的，需要手动输入用户名和密码，现在我想不用我输入那个root和密码，直接进入到提示界面。这个怎么办？


Question: 这个跟大小端有关系么？vs里面怎么设置可是实现输出倒过来？

大小端，这个有两种看法 某些人把Intel 8086~如今的X86 字节顺序，称为 大端 Big End  motorola 68XXXX 等 芯片，字节顺序，称为小端 Little End  另一些人恰恰相反 总之是两种不同的字节顺序  简单的测试就是  int main(){ union{ int x  char a[4]; }; x=0x12345678 if( a[0] == 0x78)         printf("II");//Intel 格式，TIFF  文件中 II表示 Intel 格式 else         printf("MM");//motorola 格式，TIFF  文件中 MM表示 Motorola格式 return 0; }

引用 11 楼 wangyaninglm 的回复:[quote=引用 4 楼 wang0635 的回复:] int	x = 0x12; if (*(char *)&x == 0x12) 	//小端 else 	//大端  想请问一下，这么写是啥意思？[/quote] 运行时判断大小端

引用 4 楼 wang0635 的回复:int	x = 0x12; if (*(char *)&x == 0x12) 	//小端 else 	//大端  想请问一下，这么写是啥意思？

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节，一个字节为 8bit。但是在C语言中除了8bit的char之外，还有16bit的short型，32bit的long型（要看具体的编译器），另外，对于位数大于 8位的处理器，例如16位或者32位的处理器，由于寄存器宽度大于一个字节，那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x，在内存中的地址为0x0010，x的值为0x1122，那么0x11为高字节，0x22为低字节。对于 大端模式，就将0x11放在低地址中，即0x0010中，0x22放在高地址中，即0x0011中。小端模式，刚好相反。我们常用的X86结构是小端模式，而KEIL C51则为大端模式。很多的ARM，DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

是的，和大小端有关。  #include<stdint.h> #include <stdio.h>  #if defined(_WIN32) || defined(_WIN64) #include <windows.h> #include <winsock2.h> #else #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #endif   union X {     int32_t a;     struct      {         int16_t b;         int16_t c;     }; };   int main() {     union X x;     x.a = htonl(0x20150810);     printf("%x,\n",&x.a);     printf("%x,\n",ntohl(x.a));     printf("%x,%x\n",&x.b,&x.c);     printf("%x,%x\n",ntohs(x.b), ntohs(x.c));       getchar();     return 0; }

只能转成char[] 然后奇偶swap

改代码把 引用x.a = htonl(0x20150810);

这个和处理器有关，大小端

对，这个跟大小端有关。 PowerPC处理器使用大端模式，而Pentuim处理器使用小端模式。

这个是取决于处理器的，没法从vs里设置。

我去。我不是这个版的版主，


Question: 希望 帮忙解释一下

仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //

二级指针就是用来存一级指针的地址的

把它理解为动态的二维数组就好。

引用 10 楼 pricks的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] 《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！   这样不会越界吗？[/quote] 引用 9 楼 zhao4zhong1 的回复:《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！   这样不会越界吗？[/quote] 从右往左算，不存在越界不月结

楼上

引用 6 楼 zhangxiangDavaid 的回复:明白了一级指针，类推二级指针 明白了二级指针，类推三级指针； //在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------  明白了三级指针，类推四级指针； //在堆中开辟一个2×3×4×5的4维int数组 #include <stdio.h> #include <malloc.h> int ****p; int h,i,j,k; void main() {     p=(int ****)malloc(2*sizeof(int ***));     if (NULL==p) return;     for (h=0;h<2;h++) {         p[h]=(int ***)malloc(3*sizeof(int **));         if (NULL==p[h]) return;         for (i=0;i<3;i++) {             p[h][i]=(int **)malloc(4*sizeof(int *));             if (NULL==p[h][i]) return;             for (j=0;j<4;j++) {                 p[h][i][j]=(int *)malloc(5*sizeof(int));                 if (NULL==p[h][i][j]) return;             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     p[h][i][j][k]=h*60+i*20+j*5+k;                 }             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     printf(" %3d",p[h][i][j][k]);                 }                 printf("\n");             }             printf("--------------------\n");         }         printf("=======================\n");     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 free(p[h][i][j]);             }             free(p[h][i]);         }         free(p[h]);     }     free(p); } //   0   1   2   3   4 //   5   6   7   8   9 //  10  11  12  13  14 //  15  16  17  18  19 //-------------------- //  20  21  22  23  24 //  25  26  27  28  29 //  30  31  32  33  34 //  35  36  37  38  39 //-------------------- //  40  41  42  43  44 //  45  46  47  48  49 //  50  51  52  53  54 //  55  56  57  58  59 //-------------------- //======================= //  60  61  62  63  64 //  65  66  67  68  69 //  70  71  72  73  74 //  75  76  77  78  79 //-------------------- //  80  81  82  83  84 //  85  86  87  88  89 //  90  91  92  93  94 //  95  96  97  98  99 //-------------------- // 100 101 102 103 104 // 105 106 107 108 109 // 110 111 112 113 114 // 115 116 117 118 119 //-------------------- //======================= //

明白了一级指针，类推二级指针

就是指针的指针，举个通俗的例子，你去找A那东西，A告诉你东西在B处。 一般用来存储二维数组的，如矩阵

这句话是分配了whl个指针空间，返回这块空间的地址。由于每一项类型是指针，所以返回双重指针。可以当成指针数组理解，指针数组的首地址类型是双重指针。


Question: C语言，请问一个被调用函数里面开辟了指针内存，并且返回指针，那么怎么释放它呢？

4、如何给帖子结帖，结帖如何给分？ 点击帖子左上方的"结帖"按钮，可以进行如下操作： 单独给分结帖：当您的问题得到解答，请给回答者相应的分数，来结束该帖。当您结帖后，系统将返回给您该帖的50%的可用分。 注：结帖人不允许给自己的回复发分。 无满意答案结帖： 当您的问题得不到合适的答案。您可以选择无满意结帖结束这个问题。 注：无满意结帖，系统将回收帖主的悬赏分，且没有任何可用分返还。无满意答复，必须提问满24小时才可以进行操作。 平均给分结帖：当回复过长参与人数过多时候，您可以使用平均给分的功能。 注：技术区不允许平均给分结帖。

怎么给你分数？

引用 4 楼 u014626834 的回复:谢谢！第一次玩C论坛，问题解决了之后怎么做呢？结贴吗？ 嗯，结贴，送我点分数

谢谢！第一次玩C论坛，问题解决了之后怎么做呢？结贴吗？

是的。free会根据指针，找到分配的空间，把它释放掉。

在被调用函数中返回了的话，你的意思是在主函数中对接收的指针free(p1)吗？

什么叫“指针内存”？是不是就是动态分配了一块空间？直接对返回的指针调用free(ptr)即可。


Question: 基础太差！请教一个c语言基础问题

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

楼上正解

char默认是signed，用整数常量128赋值，实际存入的是截断成一个字节的-128，十六进制是0x80。再赋值给a，扩展成整数-128，如果整数是32位的，就是0xffffff80，按无符号数解释，就是十进制的4294967168


Question: 请C预言功底扎实的朋友帮忙看一个小问题

引用 5 楼 riscben 的回复:[quote=引用 1 楼 ri_aje 的回复:] 因为 const pSubParaAttribTyp const 的类型是 SubParaAttribTyp* const，所以匹配不上 const SubParaAttribTyp*.  const pSubParaAttribTyp const 里面有两个const，前一个const就是形容这个指针是指向一个const的SubParaAttribTyp结构体的[/quote] 你想当然了，两个 const 都是修饰 pSubParaAttribTyp 类型的，没有一个能够渗透到里面的 SubParaAttribTyp。

引用 3 楼 u010087712 的回复:1、SubParaAttribTyp*和pSubParaAttribTyp确实是一样的，但是const SubParaAttribTyp*  与const pSubParaAttribTyp 并不 2、SubTBL_AAA 和SubTBL_BBB都是const SubParaAttribTyp*类型  我的问题就是第一条不理解 既然SubParaAttribTyp*和pSubParaAttribTyp是一样的 那么const SubParaAttribTyp* 和const pSubParaAttribTyp 为什么不一样？ 就是在各自的前面加个const而已 两个不都是应该指向const的SubParaAttribTyp结构体变量么？

引用 1 楼 ri_aje 的回复:因为 const pSubParaAttribTyp const 的类型是 SubParaAttribTyp* const，所以匹配不上 const SubParaAttribTyp*.  const pSubParaAttribTyp const 里面有两个const，前一个const就是形容这个指针是指向一个const的SubParaAttribTyp结构体的，所以我不太明白为什么和const SubParaAttribTyp*匹配不上

引用 7 楼 ri_aje 的回复:[quote=引用 5 楼 riscben 的回复:] [quote=引用 1 楼 ri_aje 的回复:] 因为 const pSubParaAttribTyp const 的类型是 SubParaAttribTyp* const，所以匹配不上 const SubParaAttribTyp*.  const pSubParaAttribTyp const 里面有两个const，前一个const就是形容这个指针是指向一个const的SubParaAttribTyp结构体的[/quote] 你想当然了，两个 const 都是修饰 pSubParaAttribTyp 类型的，没有一个能够渗透到里面的 SubParaAttribTyp。[/quote]  我再理一理 const pSubParaAttribTyp指的是指针本生是一个const型的，而不是它指向的对象是const型的？ 而const SubParaAttribTyp*指的是它指向的对象是const型的，指针本身不一定是const型的？ 所以两个不能匹配？

typedef typedef type-declaration synonym;  The typedef keyword defines a synonym for the specified type-declaration. The identifier in the type-declaration becomes another name for the type, instead of naming an instance of the type. You cannot use the typedef specifier inside a function definition.  A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the decl-specifiers portion of the declaration. In contrast to the class, struct, union, and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.  Example  // Example of the typedef keyword typedef unsigned long ulong;  ulong ul;     // Equivalent to "unsigned long ul;"  typedef struct mystructtag {    int   i;    float f;    char  c; } mystruct;  mystruct ms;   // Equivalent to "struct mystructtag ms;"  typedef int (*funcptr)();  // funcptr is synonym for "pointer                            //    to function returning int"  funcptr table[10];   // Equivalent to "int (*table[10])();"

const pSubParaAttribTyp const ReferSubTBL[2]  这个肯定会错啊，SubTBL_AAA、SubTBL_BBB是数组首地址，是个指针。


Question: 关于fread的一个问题，有图，求教

大概是端序问题，读完ImageData[i][j]加一句 ImageData[i][j] = _byteswap_ulong(ImageData[i][j]) 试试

是不是没考虑字节序的问题哦，整数 0x12345678 在内存和文件中保存出来是 78 56 34 21

太感谢了。。。问题已经解决。


Question: scanf无法将输入的数存入变量

引用 10 楼 Zidane_2014 的回复:我再VC里面跑了一下。 没有问题。 按照你的方法打断点也能正常运行的。 怀疑你是不是输入的时候出现了问题。  我又试了试，果然还是断点用的不熟悉，应该在运行到scanf并停下来等待输入时再输入，我输早了

上面已经能说清楚了，你看那边提示的"以‘,’分隔"的逗号跟你下面敲的逗号都不一样，能生效才怪了。

再供参考：#include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }

int main(int argc, const char * argv[]) //main可能第一个参数是文件名。 仅供参考

引用 4 楼 HIN735 的回复:我看到了，你的逗号是全角'，'应该用半角',' 我运行的时候是半角，运行成功  我正常运行的时候也没问题，但就是逐行运行的时候不能正常走下去 不清楚这是怎么回事

#include <stdio.h>   //求三个数的平均值 float avg(int x, int y, int z){     return (x+y+z)/(3.0f);//} } int main(int argc, const char * argv[]) {     int x=1,y=1,z=1;     printf("请输入三个整数，以‘,’分开:\n");     scanf("%d,%d,%d",&x,&y,&z);          float aa;     aa=avg(x,y,z); 	printf("%d,%d,%d这三个数的平均值：%f",x,y,z,aa); 	     return 0; }

运行没问题啊，你的avg函数返回值没有接收。

仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

从图片右下角看，你的程序实际已经退出了，输入数字的时候，命令行终端把23当成了命令。你是不是在linux系统运行？可能调用scanf时程序崩溃了。

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

我看到了，你的逗号是全角'，'应该用半角',' 我运行的时候是半角，运行成功

引用 1 楼 HIN735 的回复:运行没问题啊，你的avg函数返回值没有接收。  ...看来脑袋真是短路了，居然没打印出来  我这断点逐行运行到scanf那里就老是出错呢，执行不下去


Question: glib GString 释文问题

g_string_new和g_string_free是一对，配对使用就好了，再用g_free是画蛇添足的做法。

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。


Question: 关于return

如果函数返回是void，可以return；也可以不写 其它情况下都要写，return函数的类型和你函数的定义有关。 return ( auth_info.attest_crt_ptr != NULL ); 这里返回的是true或者false.()里是一个判断式

return  根据函数声明的返回值的类型，可以不返回任何东西 也可以返回 return 表达式的值 要和 返回值的类型兼容。。。 类型兼容 指的是可以隐式转换为 返回值类型。  return 语句 有两种形式； return; // 不带 return 表达式，不返回任何值， 类型 void ； void 类型函数，以及C++，构造函数，析构函数 中的return   return expr; //带 return 表达式 ，,返回表达式的值 。 类型为定义 函数时的（返回值）类型 。  另外： return (expr) ；只是一种习惯 ，其中的（) 完全是多余的；

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  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对应的汇编并单步执行观察相应内存和寄存器变化。）

return 只能返回函数声明的类型，先计算出结果，再返回结果。

这是一个表达式，而这个表达式是有值得。所以可以被 return 返回的。

返回判断的结果啊


Question: 做《c和指针》课后练习时关于char型溢出的一个疑惑

引用 15 楼 lin5161678 的回复:[quote=引用 14 楼 lm_whales 的回复:] 同一个地方还规定了  -32767是最小 int  是不是  -32768 不合法?[/quote] 他这个新的规定的思想是 正数 负数要对称，至于合不合理，个人认为，应该是各有道理  所谓最小实现，其实就是 char >= 8 Bits ,int >=16Bits，long >=32Bits这一类的  DSP上 char 是 16 Bits 那其实是  相应的 -32768 在这个时候，是个不合法的数 从前DOS下，TC int 是16 Bits 在这个标准下，-32768 就是不合法的 至于具体 -128 或者-32768 在某个系统下，合不合法，取决于 char,int 等整型的长度（Bits数） char 为8Bits 的时候，-128 是不合法的 int(short) 为16 Bits的时候， -32768 是不合法的 int(short) 型 并不是，每个系统都受制于最小范围， 无论如何实现 整型（有符号数） ， 而是总有一个数不合法，这个数就是 绝对值最大的负数  最小范围，刚好就把 最小长度中的这个 -32768，-128 等 放到 取值范围之外。

引用 15 楼 lin5161678 的回复:[quote=引用 14 楼 lm_whales 的回复:] 同一个地方还规定了  -32767是最小 int  是不是  -32768 不合法?[/quote] 这么做还有一个很合理的原因 那就是 对负数取绝对值，在数学上，结果一定是正的 而 -32768 ，-128 等数，在该长度正数的取值范围，没法定义绝对值 如果定义为 32768 ，128 这个数二进制 和  -32768 ，-128  值相同，表示的却是负数。 这样 【-32767 ，32767】 就比 【-32768，32767】要严谨一点 同理 【-127，127】 这个范围 比【-128，127】 要严谨一点 当然，这样做，也有他的缺点，就是有一个编码没有用上（-32768 ，-128）

引用 12 楼 lm_whales 的回复:问题是 一般实现，也都是 -127 ～127 而不是  -32767 ~ 32767那又如何? 反正 这也不能说明 -128 就是 非法啊

引用 14 楼 lm_whales 的回复: 同一个地方还规定了  -32767是最小 int  是不是  -32768 不合法?

引用 13 楼 lin5161678 的回复:[quote=引用 12 楼 lm_whales 的回复:] 问题是 一般实现，也都是 -127 ～127 而不是  -32767 ~ 32767那又如何? 反正 这也不能说明 -128 就是 非法啊 [/quote]不能如何，只是不被认可而已 连 标准库里面都改掉了， 你写 -128 在某些系统上可能会警告，或者直接报错，如此而已。

引用 10 楼 lin5161678 的回复:[quote=引用 9 楼 lm_whales 的回复:] [quote=引用 6 楼 adlay 的回复:] [quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80  如果真如你所的，0x80 表示 -127，那 0x81 怎么办？ 也表示 -127？ 两个不同的数变了成同一个数，那面对  char x = -127 的时候，内存里面该如何存储这个值才能符合写的人的预期？世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ～127  -128  =0x80 是非法数值 不在  char  表示范围  char 的范围是  负数 [0x81 0xFF] ， 0，正数 [1~ 0x7F]   正好是 【-127 ～ -1】，0，【1，127】  所以正好是 【-127，127】  0x80 正好不在这个范围，所以是个非法数  [/quote]说错了 不是非法数 标准要求-127~127 说的是最小范围  只要比这个范围大 喜欢实现为 -32768 ~ 32767 也是完全没问题的 都是合法的[/quote] 问题是 一般实现，也都是 -127 ～127 而不是  -32767 ~ 32767

C新标准（其实不新，早就是老标准了） char 范围确实是 【-127，127】 但是 char（8Bits 整数） 也确实可以表示 0x80 char c =0x80; /* 也可以改为 char c =128; */ printf ("%d",c);不能说明问题，因为 char 参数在这里 按照 int 传递。这里有类型提升。 即便新标准，hhd 格式。 printf("%hhd",c);也不能说明什么问题。

引用 9 楼 lm_whales 的回复:[quote=引用 6 楼 adlay 的回复:] [quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80  如果真如你所的，0x80 表示 -127，那 0x81 怎么办？ 也表示 -127？ 两个不同的数变了成同一个数，那面对  char x = -127 的时候，内存里面该如何存储这个值才能符合写的人的预期？世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ～127  -128  =0x80 是非法数值 不在  char  表示范围  char 的范围是  负数 [0x81 0xFF] ， 0，正数 [1~ 0x7F]   正好是 【-127 ～ -1】，0，【1，127】  所以正好是 【-127，127】  0x80 正好不在这个范围，所以是个非法数  [/quote]说错了 不是非法数 标准要求-127~127 说的是最小范围  只要比这个范围大 喜欢实现为 -32768 ~ 32767 也是完全没问题的 都是合法的

引用 6 楼 adlay 的回复:[quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80  如果真如你所的，0x80 表示 -127，那 0x81 怎么办？ 也表示 -127？ 两个不同的数变了成同一个数，那面对  char x = -127 的时候，内存里面该如何存储这个值才能符合写的人的预期？世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ～127  -128  =0x80 是非法数值 不在  char  表示范围  char 的范围是  负数 [0x81 0xFF] ， 0，正数 [1~ 0x7F]   正好是 【-127 ～ -1】，0，【1，127】  所以正好是 【-127，127】  0x80 正好不在这个范围，所以是个非法数

引用 4 楼 adlay 的回复:补码表示的数的绝对值是  取反 + 1,  10101100 按位取反后是 83，再加 1 就是 84 了。同理，0x80 表示的有符号数也是 -128. 这里确实忘记加1了，无语，这么弱智的错误居然也会犯。。

引用 3 楼 lm_whales 的回复:char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80   赞~\(≧▽≦)/~  解释的很清楚

引用 3 楼 lm_whales 的回复:char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80  如果真如你所的，0x80 表示 -127，那 0x81 怎么办？ 也表示 -127？ 两个不同的数变了成同一个数，那面对  char x = -127 的时候，内存里面该如何存储这个值才能符合写的人的预期？世界都乱套了。

引用 3 楼 lm_whales 的回复:char型范围是-127到127 是这样的 -128  这个数值，已经溢出了  最高位同时表示 符号，和值 0x80 二进制为 1000 0000  本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128   早期char型范围，确实是 -128 ～127  如今已经改为 -127 ～127了   -128 应该表示为 -127 - 1 其实还是 0x80  这个很好验证   	char x = 0x80; 	printf("%d\n", x);   它就是 -128

新人看看 哈哈

checksum(检验和）用一个signed char变量进行计算，它初始为-1 -128~127


Question: 指针问题

char *squeeze(char *s1,char *s2) {     int flag = 0;     int i=0;     int j=0;     int k = 0;     while(*s1!='\0')     {                 //根据该字段判断是否s1当前字符匹配s2中某一个字符         flag = 0;         while(*s2!='\0')         {             if(*s2 == *s1)             {                 flag = 1;   ----这里找到了是不是应该跳出循环             }             s2++;         }         if(!flag)   ------这里的操作是想做什么？我的理解应该是找到了进行删除操作吧，但是这个条件？这块仔细看看         {             *(s1+j) = *s1;               j++;         }         s1++;     }     s1[j]='\0';     return s1; }

你使用字符指针是不能改变他指向的内容，要改变内容需要使用字符数组。

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

#include<stdio.h> #include<string.h> char *squeeze(char *s1, char *s2){ 	int i, j; 	int len = strlen(s1); 	char *tmp = (char *)malloc(sizeof(char) * (len + 1)); 	memset(tmp, '\0', len + 1); 	for(i = 0,j = 0; i < strlen(s1); i++){ 		if(strchr(s2, *(s1 + i)) == NULL){ 			*(tmp + j) = *(s1 + i); 			j++; 		} 	} 	return tmp; } int main(){ 	char *s1 = "abcdefg"; 	char *s2 = "abc"; 	char *result = squeeze(s1, s2); 	printf("%s\n", result); 	free(result);	 	return 0; }  char  *s1指向字符串常量，不可修改

前面加个const不就好了，char数组得指定长度才好删

引用 1 楼 zhao4zhong1 的回复:char  s1[] = "abcdefg";  char  s2[] = "abc"; 首先我源程序中指针指向的是一个字符串常量，而这个字符串常量是存储在代码区中的！  引用 6 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 我指针指向的是一个字符串常量，指针在栈上分配空间，他的值是指向字符串常量的首地址的地址，而常量的值是不能够被修改的。而数组就不一样，首先会在栈上面开辟一段空间存放数组p的内容，而他的内容是字符串常量的的拷贝（一个很大的区别）。这样理解对吗？

另外你把主函数里的定义改成这样就不会报错   char s1[100] = "abcdefg"; char s2[100] = "abc";   因为你之前的s1 s2是指向常量字符串  参看：http://blog.csdn.net/zlqqhs/article/details/39290977

你要在你程序上改，可我看了半天也没看懂你那些操作是什么意思，你可以自己单步调试看下  另参看：http://www.cnblogs.com/hellophone/archive/2013/08/11/3252070.html


Question: 【新人求助！急！！】用STC12C5A60S2同时测温度（DS18B20）和电压（内部AD转换）会出现错误？）

顶顶，解决了能分享吗，

那最终问题是怎么解决的？望楼主与后辈分享。

赵老师，您好！ 我把延时函数的i改为1000，3000，5000，8000都不行啊 void delay_1ms(uint a) //延时约1ms {     uint i;     while (a--)         for(i=1000;i>0;i--);   //1T单片机i=600，若是12T单片机i=125 }

个人经验：delay或sleep的时间加大再试试。


Question: 求Linux C 下开发使用的轻量级网络库。

libevent


Question: C语言中位运算符&和|是怎么运算的

位运算，需先转换为二进制，然后再进行运算. &(按位与) ： 按位取与可以将两个数之间，只有一个为1的位数据清零  |(按位或) ：  当两个位都为0，结果位0，否则为1； 详见http://www.maomao365.com/?p=2720

学一下进制之间的转换。如：十进制转换为二进制.

位运算，百度一下，有很多资料的

位运算。 &是与。 |是或。 详情百度。

不要把时间浪费在看十进制和知道十进制结果上。务必记住，数字在电脑里存储是二进制，位运算 &、|、~ 也是二进制。看二进制时，就忘掉十进制吧。HEX        BIN                              DEC 0x00000001 00000000000000000000000000000001 1 0x00000002 00000000000000000000000000000010 2 0x00000004 00000000000000000000000000000100 4 0x00000008 00000000000000000000000000001000 8 0x00000010 00000000000000000000000000010000 16 0x00000020 00000000000000000000000000100000 32 0x00000040 00000000000000000000000001000000 64 0x00000080 00000000000000000000000010000000 128 0x00000100 00000000000000000000000100000000 256 0x00000200 00000000000000000000001000000000 512 0x00000400 00000000000000000000010000000000 1024 0x00000800 00000000000000000000100000000000 2048 0x00001000 00000000000000000001000000000000 4096 0x00002000 00000000000000000010000000000000 8192 0x00004000 00000000000000000100000000000000 16384 0x00008000 00000000000000001000000000000000 32768 0x00010000 00000000000000010000000000000000 65536 0x00020000 00000000000000100000000000000000 131072 0x00040000 00000000000001000000000000000000 262144 0x00080000 00000000000010000000000000000000 524288 0x00100000 00000000000100000000000000000000 1048576 0x00200000 00000000001000000000000000000000 2097152 0x00400000 00000000010000000000000000000000 4194304 0x00800000 00000000100000000000000000000000 8388608 0x01000000 00000001000000000000000000000000 16777216 0x02000000 00000010000000000000000000000000 33554432 0x04000000 00000100000000000000000000000000 67108864 0x08000000 00001000000000000000000000000000 134217728 0x10000000 00010000000000000000000000000000 268435456 0x20000000 00100000000000000000000000000000 536870912 0x40000000 01000000000000000000000000000000 1073741824 0x80000000 10000000000000000000000000000000 2147483648布尔运算 (用 1 代表 true，0 代表 false)：与：1 & 1 = 1, 1 & 0 = 0, 0 & 1 = 0, 0 & 0 = 0; 或：1 | 1 = 1, 1 | 0 = 1, 0 | 1 = 1, 0 | 0 = 0; 非：~0 = 1, ~1 = 0;二进制位运算就是把每一个位都按照上述规则计算。以二进制查看一个32位整数，它是由32个0或1的序列组成。如果你将每个位置看作一个开关：0-关，1-开，你就不难理解他的用途了。检测第二位是否存在 (不存在)： 5 & 2 = 0 -- (1 | 4) & 2 = 0 00000000000000000000000000000101 & 00000000000000000000000000000010 = 00000000000000000000000000000000 将第二位置为1 (先前为0)： 5 | 2 = 7 -- (1 | 4) | 2 = (1 | 2 | 4) 00000000000000000000000000000101 | 00000000000000000000000000000010 = 00000000000000000000000000000111 检测第二位是否存在 (存在)： 7 & 2 = 2 -- (1 | 2 | 4) & 2 = 2 00000000000000000000000000000101 & 00000000000000000000000000000010 = 00000000000000000000000000000010 将第二位置为1 (先前为1)： 7 | 2 = 7 -- (1 | 2 | 4) | 2 = (1 | 2 | 4) 00000000000000000000000000000111 | 00000000000000000000000000000010 = 00000000000000000000000000000111 将第二位置为0 (先前为1)： 7 & ~2 = 5 -- (1 | 2 | 4) & ~2 = (1 | 4) 00000000000000000000000000000111 & 11111111111111111111111111111101 = 00000000000000000000000000000101 将第二位置为0 (先前为0)： 5 & ~2 = 5 -- (1 | 4) & ~2 = (1 | 4) 00000000000000000000000000000101 & 11111111111111111111111111111101 = 00000000000000000000000000000101二进制运算的优点就是将某位清零的时候不需要知道之前是1还是0，设置1的时候不需要知道之前是1还是0，可以检测某个位是1还是0。通俗地讲就是用32位二进制数字记录最多32个不同开关的排列组合，并可以检测或设置任意一个开关是否为开或者关。  对于 5 & 2 这样的表达式，你的第一个反应应该是：它是检测 5 中是否包含 2 这个标志位的，而不是关心它的“十进制”结果，没有意义。换算成二进制，一目了然。不过通常，都是将这些二进制常量定义为宏名称这样更直观。如我们在 Windows 编程中非常常见的窗口样式，就是二进制位的一个经典范例：DWORD dwStyle = (DWORD)GetWindowLongPtr(hwnd, GWL_STYLE); if (dwStyle & WS_CHILD) {     dwStyle &= ~(WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);     dwStyle |= WS_CLIPSIBLINGS;     SetWindowLongPtr(hwnd, GWL_STYLE, (LONG_PTR)dwStyle); }事实上，二进制位在 Windows 编程中无处不在。

位运算，请参考百度

结果是 000

101 010 ----- 000


Question: 急求！重谢！C语言简单小问题！

到达文件末尾的时候，可以让文件位置指针后退2位，去读取最后一个字符，这样你不就知道最后一个字符是不是‘\n’ 如果是'\n'的话，段落数+1，不是的话，就不用加1了

引用 18 楼 zhao4zhong1 的回复:[quote=引用 17 楼 zhangxiangDavaid 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？[/quote] 你猜。[/quote] 我猜： z的含义表面上看是标记非空行，但在处理超长行时有特殊用途： 如果z为1，表明当前行非空，则只需读完改行剩下的内容即可。 否则，需要对当前读到的内容进行判断。

引用 17 楼 zhangxiangDavaid 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？[/quote] 你猜。

引用 7 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }  变量z的含义是什么？

这样理解是对的，你把错误的地方修改一下看看

引用 14 楼 user-4的回复:1)ch 必须改为 int 类型， 因为 (ch=fgetc(fp1)) 同样是 ch类型的 和 EOF 比较是有问题的 2)多定义一个 字符类型，不如直接计算最后一行的长度简单明了 3）   ch++; //这个++ 是不对的 ch 是从文件读到的数据 不用++，这个++ 造成 ch,ch2 通常不会 ‘\n'     ch2=ch; // 这是做什么用的？ 首先谢谢指正前面的错误。ch2=ch是想保存跳出while之前的最后一个字符，我觉得是ch==EOF之前的字符也就是文本中最后一个字符。如果ch2是\n，那段落数就少加一个。不谈前面的错误，这样的理解哪里有问题？为什么实现不了段落数的正确获取？

引用 11 楼 user-4 的回复:这个 读到文件结束，在上一个段落和文件结束前，有文字那就添加一个段落 如果，换行后（段落后）紧接着就是文件结束了，那就不用添加这个段落。 这是个+1 ，-1 的问题，处理一下就好。我试了一下，在程序上加了这么一小段，（printf单纯为了测试这个if语句能不能运行），可是当测试文本末尾有\n，if语句也没有运行，是不是EOF不能作为文件最后一个字符用？		else 		{ 			character++; 			word++; 		}          /*遇到其他字符时字符个数+1*/ 		ch++; 		ch2=ch; 	} 	if(ch2=='\n') 	{ 		printf("a"); 		character++; 	}

#include <stdio.h> #include <stdlib.h> int main() {     FILE *fp1, *fp2; /*定义两个指向FILE类型结构体的指针变量*/    int ch;// 定义整型，用来读取字符    long paraglen =0;//定义段长     char filename1[100],filename2[100] ; /*定义数组变量为字符型*/     long character,word,sentence,paragraph; /*定义变量为长整型*/     character=word=sentence=paragraph=0; /*长整型变量的初值均为0*/     printf("Enter file name \n");     scanf("%s", filename1); /*输入要进行统计的文件的路径及名称*/     if((fp1=fopen(filename1, "r"))==NULL) /*以只读方式打开指定文件*/     {         printf("cannot open file.\n");         exit(1);     }     printf ( "Enter file name for write data:\n");     scanf("%s",filename2); /*输入文件名即将统计结果放到那个文件中*/     if((fp2=fopen(filename2, "w"))==NULL) /*已可写方式要存放统计结果的文件*/     {         printf("cannot open file \n");         exit(1);     }     while((ch=fgetc(fp1))!=EOF) /*知道文件内容结束处停止while循环*/     {         paraglen++;//每读取一个字符，段长加一         if(ch>='A' && ch<'Z'||ch>='a' && ch<='z')         {             character++;         }          /*当遇到字母时字符个数+1*/         else if(ch==' ')         {             character++;             word++;         }          /*当遇到空格时字符数+1*/         else if(ch>='0' && ch<='9')         {         character++;         }          /*当遇到数字时数字个数+1*/         else if(ch=='.'||ch=='!'||ch=='?')         {             sentence++;             character++;         }          /*当遇到.!?时句子数+1，字符数+1*/         else  if ((ch=='\r')||(ch=='\n'))         {    paragraph++;              paraglen = 0;//段长，实际上是行长，每当换行就清零         }                /*当遇到换行符时段落数+1*/         else         {             character++;             word++;         }          /*遇到其他字符时字符个数+1*/         ch =0;     }         if(paraglen)                paragraph++;  /*遇到段长非零，表示读到 文件结束，最后一个段（行），没有计算所以，段(行)数加一*/                /* （或者读出错，这里不考虑读文件出错），需要的话，使用ferror 函数，读取文件错误码 */          fclose(fp1);      /*关闭fp1指向的文件*/         fprintf(fp2,"character:%ld word:%ld sentence:%ld paragraph:%ld\n", character, word, sentence,paragraph);/*将统计结果写入fp指向的磁盘文件中*/         fclose(fp2);         while(getchar()!='q'); }  这是修改后的代码 ch ++ 是不必要的，因为ch 是从文件里读出来的，需要的话，重置为 0

引用 9 楼 user-4 的回复:谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）  不是合不合理的问题，而是取舍的问题， 当时这么定义的读写文件的函数，自然有他的考量。[/quote]那请问一下我可不可以做较小程度的修改来实现段落数的正确统计，因为段落数是以回车为标志的，如果最后一段没有回车就少统计一个。能不能帮忙看一下我对修改段落数统计的想法，谢谢。

引用 8 楼 D_CHRIS 的回复:[quote=引用 6 楼 赵4老师的回复:]char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。 谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）[/quote]  不是合不合理的问题，而是取舍的问题， 当时这么定义的读写文件的函数，自然有他的考量。

引用 6 楼 赵4老师的回复:char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。 谢谢详解，我想再问个问题，我之前考虑的优化方案是再定义一个ch2，用来存放从文件读取的ch上一个值，大概想法是如果ch=EOF，ch2!=\n时，段落数++，请问把EOF作为从文件中读到的最后一个字符，这样的做法合理吗？可行吗？或者有什么能够定义文本文件最后一个字符的？（因为想在源程序的基础上进行较少的改动，对于之前楼层提出的建议会采纳再写一个程序）

char ch;//会导致无法区分到底是读到了0xFF字符还是到了文件末尾。

引用 3 楼 赵4老师的回复:char ch; 应改为 int ch; 定义为char的目的就是为了读取文件中的字符，如果改为int类型是否也能实现同样的功能呢？

将while语句中的条件判断挪到while循环的第一句或中间某句或最后一句视具体情况而定。

char ch; 应改为 int ch;

引用 1 楼 赵4老师的回复:不要使用 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;  //... } 类似的例子还可以举很多。  不要使用 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;  //... } 类似的例子还可以举很多。 [/quote] 那请问基于我的程序怎么改呢


Question: 统计单词个数，如何去掉单词后面的标点符号？

#pragma warning(disable:4018) #include <stdio.h> #include <string.h> #include <ctype.h> #include <malloc.h> #include <locale.h> int main() {     char *s,*s1,*M,*N;     int i,k,n,L,maxlen,minlen;     FILE *fp;      setlocale(LC_ALL,"chs");     fp=fopen("D:\\Exce1.txt","r");     if (fp==NULL) return 1;      s=(char *)malloc(1000*32);     if (s==NULL) return 2;      for (i=0;!feof(fp);i++) {         fscanf(fp,"%31s",s+i*32);         L=strlen(s+i*32);         if (!isalpha(s[i*32+L-1])) s[i*32+L-1]=0;         printf("第%d个单词为：%s\n",i+1,s+i*32);         if (i%1000==999) {             s1=(char *)realloc(s,(i+1+1000)*32);             if (s1==NULL) return 3;             s=s1;         }     }     printf("共%d个单词\n",i);      maxlen=strlen(s);     M=s;     for (k=32;k<i*32;k+=32) {         if (maxlen<strlen(s+k)) {             maxlen=strlen(s+k);             M=s+k;         }     }      minlen=strlen(s);     N=s;     for (n=32;n<i*32;n+=32) {         if (minlen>strlen(s+n)) {             minlen=strlen(s+n);             N=s+n;         }     }      printf("最长的单词是：%s\n, 最短的单词是：%s\n",M,N);      fclose(fp);     free(s);     return 0; }

if (i%1000==999) {//当前单词数累加到除1000的余数是999时，重新分配s的大小，增加1000个     s1=(char *)realloc(s,(i+1+1000)*32);     if (NULL==s1) return 3;     s=s1; }

非常感谢赵4老师的回复。在你的代码基础上，我把程序增加了一个功能，显示最长和最短单词，代码如下：  #include <stdio.h> #include <string.h> #include <ctype.h> #include <malloc.h> //#include <locale.h> int main()  {     char *s,*s1;     int i,k,n,L,M,N,maxlen,minlen;     FILE *fp;       //setlocale(LC_ALL,"chs");     fp=fopen("D:\\Exce1.txt","r"); 	if (fp==NULL) return 1;  	s=(char *)malloc(1000*32); 	if (s==NULL) return 2;      for (i=0;!feof(fp);i++)  		{ 		 fscanf(fp,"%31s",s+i*32); 		 L=strlen(s+i*32);          if (!isalpha(s[i*32+L-1])) s[i*32+L-1]=0;          printf("第%d个单词为：%s\n",i+1,s+i*32);  		 //if (i%1000==999) 		 //{s1=realloc(s,(i+1+1000)*32); 		  //if(s1==NULL) return 3; 		  //s=s1; 		 //}     }     printf("共%d个单词\n",i);  	maxlen=strlen(s); 	M=0; 	for(k=1;k<(i*32);k++) 	{ 		if(maxlen<strlen(s+k)) 		{maxlen=strlen(s+k);M=int(s)+k;} 	}  	minlen=strlen(s); 	N=0; 	for(n=1;n<(i*32);n++) 	{ 		if(minlen>strlen(s+n)) 		{minlen=strlen(s+n);N=int(s)+n;} 	} 	     printf("最长的单词是：%s\n, 最短的单词是：%s\n",M,N);      fclose(fp);     free(s);     return 0; }  请问 if (i%1000==999)语句块的作用是什么？而且语句{s1=realloc(s,(i+1+1000)*32);运行时报错：cannot convert from 'void *' to 'char *' 所以我暂时注释起来了。  增加判断最长和最短单词程序块后，运行乱码，感觉是判断单词长度时出了点问题，希望得到你的更正，多谢！

上帖代码第9行删掉。

动态s的版本，仅供参考： #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> #include <ctype.h> #include <locale.h> int main() {     char *s,*s1;     int N=1000;     int i;     FILE *fp;      setlocale(LC_ALL,"chs");     fp==fopen("D:\\test.txt","r");     if (NULL==fp) return 1;      s=(char *)malloc(1000*32);     if (NULL==s) return 2;     for (i=0;!feof(fp);i++) {         fscanf(fp,"%31s",s+i*32);         L=strlen(s+i*32);         if (!isalpha(s[i*32+L-1])) s[i*32+L-1]=0;         printf("第%d个单词为：%s\n",i+1,s+i*32);         if (i%1000==999) {             s1=realloc(s,(i+1+1000)*32);             if (NULL==s1) return 3;             s=s1;         }     }     printf("共%d个单词\n",i);     fclose(fp);     free(s);     return 0; }

替换一下，把逗号都替换成空格。

#include <stdio.h> #include <string.h> #include <ctype.h> #include <locale.h> int main() {     static char s[1000][30];     int i;     FILE *fp;      setlocale(LC_ALL,"chs");     fp==fopen("D:\\test.txt","r");     if (NULL==fp) return 1;      for (i=0;i<1000 && !feof(fp);i++) {         fscanf(fp,"%29s",s[i]);         L=strlen(s[i]);         if (!isalpha(s[i][L-1])) s[i][L-1]=0;         printf("第%d个单词为：%s\n",i+1,s[i]);     }     printf("共%d个单词\n",i);     fclose(fp);     return 0; }


Question: 初学者关于MFC常规动态链接库的问题

出错在哪里我也不大清楚，明天我再仔细看看吧

的确是不配对 但是报错却是无法修改指向数据的指针，我想问一下，导出函数类型可以是 char *吗 因为我想返回一个buffer

extern "C" char _declspec(dllexport)_stdcall *Converte( char *OpenFilePath,char *SaveFilePath );  ?? char *Converte( char *OpenFilePath,char *SaveFilePath ) ?? 这两个不配对吧

出错在那里?

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。


Question: 求助，相当简单的一个输出函数，怎么运行是空的？

试了一下没问题啊，你怎么调用的 show?

void show(double array[],int geshu); 这句话不是函数调用。去掉void

main函数中的这一行不是函数调用，是声明。声明与调用的格式不一样。


Question: 十六进制转化为十进制问题，程序哪里出错了

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

楼主，你的这个语句if(s[j]>=0&&s[j]<=9)应该改为if(s[j]>='0'&&s[j]<='9')  ，即0和9改为字符型

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

修改如下：  #include<stdio.h> #define YES 1 #define NO 0 #define MAX 10 int htoi(char *s); int main() { 	int c, t; 	char s[MAX + 1]; 	int i = 0; 	while (i < MAX && (c = getchar()) != '\n') 		s[i++] = c; 	s[i] = '\0'; 	t = htoi(s); 	printf("%s=%d\n", s, t); 	return 0; } /*htoi:convert hexadecimal strings to integer*/ int htoi(char *s) { 	int hexdigit, j, inhex, n; 	j = 0; 	if (s[j] == '0') { 		++j; 		if (s[j] == 'x' || s[j] == 'X') { 			++j; 		} 	} 	n = 0; 	inhex = YES; 	for (; inhex == YES; ++j) { 		if (s[j] >= '0' && s[j] <= '9') 			hexdigit = s[j] - '0'; 		else if (s[j] >= 'a' && s[j] <= 'f') 			hexdigit = s[j] - 'a' + 10; 		else if (s[j] >= 'A' && s[j] <= 'F') 			hexdigit = s[j] - 'A' + 10; 		else 			inhex = NO; 		if (inhex == YES) 			n = 16 * n + hexdigit; 	} 	return n; } //0x123 //0x123=291

# include <stdio.h>  int htoi (char a []) {     int r = 0, tr, fr = 1, cnt = 0;      while (a [cnt] != '\0') cnt ++;      while (cnt --)     {         if (a [cnt] >= '0' && a [cnt] <= '9') tr = a [cnt] - '0';         else switch (a [cnt])         {             case 'a': case 'A': tr = 10; break;             case 'b': case 'B': tr = 11; break;             case 'c': case 'C': tr = 12; break;             case 'd': case 'D': tr = 13; break;             case 'e': case 'E': tr = 14; break;             case 'f': case 'F': tr = 15; break;             default: return -1;         }         r += tr * fr, fr *= 16;     }      return r; }  int main (void) {     printf ("%d\n", htoi ("face")); }

都是字符比较，按照以下的改过来就好了：  if(s[j] >= '0' && s[j] <= '9')


Question: 命令行编译运行C程序，链接报错：fatal error LNK 1104

引用 4 楼 adlay 的回复:你是打开 cmd.exe 然后切换到 VC 的安装目录下去编译的吗？ 你应该在开始菜单中选 Vistual Studio Tools 中的 Vistual Studio XXX Command Prompt 来进行编译。 经过你的提示，测试了确实是WIN10系统系统盘权限的问题。如下图：

引用 4 楼 adlay 的回复:你是打开 cmd.exe 然后切换到 VC 的安装目录下去编译的吗？ 你应该在开始菜单中选 Vistual Studio Tools 中的 Vistual Studio XXX Command Prompt 来进行编译。 是的。。直接cmd然后切到VC目录下编译的，不过没有成功。最后没有在系统盘编译就成功了。

最终还是解决了。最终的原因是c文件不要放在C盘根目录下。2l说的也对，就要指明基础库的位置，但是感觉-l链接挺麻烦。其实将首页的文档中的批处理文件复制到.c文件其他盘同一个目录下执行就可以了。 之前我坑了用了C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT这个文件。。。

引用 1 楼 u012033027 的回复:stdio.h只是头文件。如果要运行，得链接基础库，在linux下面叫libc。 在开发环境下面当然不用考虑，但是你要用命令行，就要指明基础库的位置，并且用“-l”选项与之相连。 好的，谢了，我先试一下。


Question: 请问一下这个期望是咋算的？

这个不是概率论的知识吗？和编程有毛关系

算了，前面的算法不要了，我总是把简单的问题弄得很复杂。没人喜欢这种解题方法。 为了得分，我千方百计寻找一种容易的图径。。。          2z=2+x+y         2x=2+y         2y=2+z   望着三个方程，我在发呆，这能用得上吗？   我正在发呆着。。。  版主，能给分了吗？   我只要5分就可以了，这是我花很多时间才找到的。

第1个四格 终止的 步数 4，3，2 概率 1/16,3/8,1/4,跨过 4,3 概率 1/16,1/4  第n个四格 终止的 步数 +3，+2 概率 *1/8,*1/2,跨过 +3,+2 概率 *1/8,*1/4 大概算到 第 4个 四格子 就可以确定大概的步数了

您这是版主吗？ 不要开玩笑了，说得这么祥细了，舍不得分说一下 一个很简单的问题，快给分。

引用 13 楼 c090869 的回复:版主，可以结贴吗？可以给分了吗？  如果我说的正确的话。 因为这题是寻择题，还可以应付的来，要不然可没办法， 应用基础知识，让机器算一下，这样简单多了。 如果进行了 1024*4 组跳，用二叉树分布下去到底13层，一共跳了14192+37*12次跳， 还剩37分枝没跳完，根据所给4种答案，最高期望值为4， 所以总的最高期望值为 （14192+37*16）/(1024*4)=3.609375,                  最低 “”“”“”“”“”（14192+37*13）/(1024*4)=3.5822.  没看懂。。。

算了1024*4种算法，平均最低步数为3.57324，还有37钟跳法没结束，按照1/3的缩小率。。。。。 明天再算

引用 9 楼 lm_whales 的回复:22      3步，概率为 1/8  ----> 22      2步，概率为 1/4 2）出格， 下一个四格接着计算 3）第二 以及以后各个 4格，3格 终止，4格跨越 n.1) 不出格,止步     111       Si +3 步,  pi * 1/8.     12         Si +2 步,  pi * 1/8. -->1/4     21         Si +2 步，pi * 1/8  ---1/4 n.2)  出格,继续   112     Si+3+...步，pi *1/8*...     22       Si+2+...步，pi *1/4*...       第一个四格内部，跨出的概率为１/16 止步的概率为 15/16    第二个四格内　跨出的概率为３/８*１/16, 止步的概率为 5/8 *1/16 到二个四格 止步的步数，分别是  ４*1/16,3*1/8*3,2*1/4 ,　  （4+3） *1/16 *1/8 ,（4+２）*　 1/16 *1/４*２ （３+3)*１/８*1/8,(3+3)*1 /8*1/4*2

题目只有前跳，一格，两格 所以概率各为1/2，不然就不是1/2 了  第一个四格，4格终止，5格跨越 1）不出格，在此止步 1111   4步，概率为 1/16 112    3步，概率为 1/8 121    3步，概率为 1/8 211    3步，概率为 1/8 22      3步，概率为 1/8  2）出格， 下一个四格接着计算 1112  4步+nextS+..., 1/16* nextP*... 122    3步+nextS+..，1/8 *nextp*... 212    3步+nextS+..，1/8 *nextp*...  3）第二 以及以后各个 4格，3格 终止，4格跨越 n.1) 不出格,止步     111       Si +3 步,  pi * 1/8.     12         Si +2 步,  pi * 1/8.     21         Si +2 步，pi * 1/8 n.2)  出格,继续   112     Si+3+...步，pi *1/8*...   22       Si+2+...步，pi *1/4*...     以此类推

请参考，虽然我看不懂 http://blog.csdn.net/u010476094/article/details/48110405

按照 每四格 作为一个 步骤，求出跨越四格的概率，和不跨越的概率  统计所有不跨越的概率

步数越多，概率越小

所谓期望，指的是数学期望，类似平均值  最少 步数 为 2 步  每步两格子 最多步数不确定 按照概率算出某种（加权）平均值 就是 期望的步数

引用 7 楼 paschen 的回复:1号格子与2号都只能前进吗？因为没有两格来退  另外退后是否也算是走了一步？  楼主发在了C/C++版块，我就觉得自己算会很复杂，写一个函数来执行，通过随机数判断前进与后退，并统计步数，达到要求退出，然后调用这个函数多次，看平均步数与选项哪一个最接近。。...

选 2 吧  跳 2 次，一步和二步的概率都是 50%，那期待的结果就是 1 次跳 1 步，1 次 跳 2 步，总共跳了 3 步，编号 1 开始，经过 3 步编号就是 4 了

步数*概率，求和。 例如： 1步结束的概率为0，2步结束的概率为1/2*1/2+1/2*1/2，对应的情况是1格、两格；两格、一格。 所以，期望步数是： 1*0 + 2 *(1/2*1/2 + 1/2*1/2) + 3 *... 抱歉没有算完，有点复杂。


Question: 笔试题目

输入的时候按ctrl+z;

先输入2 8 回车 输入一个字符串后回车 就会出现结果 然后再输入一个字符串 再回车

小bug：  printf("%.*s\n", 8, p); 改为： printf("%.*s\n", N, p);

参考如下：  /* 按要求分解字符串，输入两个数M，N；M代表输入的M串字符串，N代表输出的每串字符串的位数，不够补0。 例如：输入2, 8， “abc” ，“123456789”，则输出为“abc00000”, “12345678“, ”90000000” */ #include <stdio.h> #include <string.h> #define MAXSIZE 100 char ln[MAXSIZE]; int i, j, L; static int M, N; char *p; int main(void) { 	i = 0; 	scanf("%d%d", &M, &N); 	while (i < M) 	{ 		scanf("%s", ln); 		L = strlen(ln); 		p = ln; 		while (L > 0) 		{ 			if (L >= N) 			{ 				printf("%.*s\n", 8, p); 				p += N; 			} 			else 			{ 				printf("%s%0*d\n", p, N - L, 0); 				break; 			} 			L -= N; 		} 		i++; 	} 	return 0; }

题目的意思是需要你自己去实现 函数功能，至于输入  楼上的已经跟你解析清楚了 void solve(char* str,int n,int len) { 	while(n<len) 	{ 		printf("%.*s\r\n",n,str); 		str = str+n; 		len = len - n; 	} 	for (int i=0;i<n;++i) 	{ 		if (i<len) 		{ 			printf("%c",*(str+i)); 		} 		else 		{ 			printf("0"); 		} 	} }

scanf的返回值由后面的参数决定 scanf("%d%d", &a, &b); 如果a和b都被成功读入，那么scanf的返回值就是2 如果只有a被成功读入，返回值为1 如果a和b都未被成功读入，返回值为0 如果遇到错误或遇到end of file，返回值为EOF。 且返回值为int型.scanf返回的是成功扫描进的数的个数

按照你的代码，你编译运行后，控制台会出现输入光标，你输入的头两个数字就代表M,N（以空格间隔，输入完M,N按回车），然后依次输入M个字符串，每输入一个字符串，按下回车，就会得到分解后的字符串结果（如果你的solve函数完成了分解代码编写）。 输入完M个字符串后，又到了另一轮的输入M,N——依次输入字符串——得到分解字符串  如果想结束while(scanf("%d %d",&m,&n) != EOF)循环，在每轮输入的开始，按下Ctrl+Z，scanf函数就会返回EOF


Question: main(t,_,a)char *a;{}这个声明怎么理解?

感谢感谢感谢

这种是以前很老的 C 语言语法了  main 返回 int, 默认的 t, _ 的类型也是默认成 int a 的类型为 char×  所以就是  int main(int t, int_, char* a) { }


Question: 新手急求帮忙！简单C语言程序！急求重谢！

引用 2 楼 D_CHRIS 的回复:[quote=引用 1 楼 user-1的回复:] if(strcmp(W[i].name,s)==0)   //如果重复        {                          W[i].time++;                 flag=1;                 sum++;                }        重复的 sum 就别 ++ 了吧 请问一下如果想要不分大小写单词统计词频，如何实现最小程度的改动？[/quote]  strcmp 换成 stricmp

引用 1 楼 user-1的回复: if(strcmp(W[i].name,s)==0)   //如果重复        {                          W[i].time++;                 flag=1;                 sum++;                }        重复的 sum 就别 ++ 了吧 请问一下如果想要不分大小写单词统计词频，如何实现最小程度的改动？


Question: 写了一段程序，不知道是什么错误，求指点

存指针试试呢?

引用 2 楼 user-3 的回复:[quote=引用 1 楼 hnwyllmm 的回复:] it=V.find(A);这里返回的是不能修改的，相当于const * 引用 1 楼 hnwyllmm 的回复:it=V.find(A);这里返回的是不能修改的，相当于const *  那么从set中查找出来的对象，有什么办法去修改呢？[/quote] 按说是不能修改的，不过你可以强制转换成非const *再修改，虽然可行但是违反了set的设计原则 看楼主设计的这个类，应该是cost是key，其它的做value，用map结构正合适

引用 1 楼 hnwyllmm 的回复:it=V.find(A);这里返回的是不能修改的，相当于const * 引用 1 楼 hnwyllmm 的回复:it=V.find(A);这里返回的是不能修改的，相当于const *  那么从set中查找出来的对象，有什么办法去修改呢？

it=V.find(A);这里返回的是不能修改的，相当于const *


Question: 前辈们dev c++如何静态链接

用depends.exe查看exe依赖的dll及其版本号。

已经测试了，没问题，dev不错

引用 1 楼 宋寒松的回复:取决于具体的LIB和应用。 就是控制台程序，不是vs有个选择mt那个选项吗，这个不知道咋弄呢，就是生成的exe在别的电脑可以直接运行

取决于具体的LIB和应用。


Question: 代码26行的LINK_NODE** pNext是什么意思，是指针吗？

LINK_NODE** pNext  二级指针，用来存储指针的地址，即指向指针的指针

指针的指针，当然也是指针

因为要修改 指针本身，所以传递二级指针 因为 需要传递二级指针，所以不能直接用 (*pNode)->next 只能用它的地址 因为 & 的优先级不如 -> 高， 所以 & (*pNode)->next 是 (*pNode)->next的地址， 即& （(*pNode)->next） 而不是 （&(*pNode)）->next -------这个表达式不是一个合法表达式-----

LINK_NODE** pNext  表示二级指针。 在函数中如果需要修改指针指向的地址时，需要使用二级指针。因为如果传入如void xxxx(*p)在函数中写p=&other是不能修改原指针指向的。同值传递的概念相同。


Question: 前辈们vs2015如何创建c语言win32项目，不是控制台

这和win10没关系啊，你建立项目时候选择控制台，或者是空项目就可以了

好的各位前辈，麻烦了，我记下了，等以后再装回win10再试试，先在xp下学习了

不好意思，刚才看错了。以为是要创建控制台程序。 要创建win32，只要把MFC的框架关掉就能正常编译。

改一下你的Link选项。

创建的时候选 Win32 项目，在向导的时候有个勾选 Empty Project 勾上就行了。

引用 1 楼 user-4的回复:微软的编译器是靠后缀区别c和c++的, 后缀名改成c就行了。  不过做软件开发, c++比较好, 反正基本兼容c. 是的前辈，我的意思是，控制台程序可以建立空白项目，然后往里面再加入.c源文件就行了，可是，建立win32窗口程序就没办法只建立空白项目，而是创建后里面有很多的头文件和源文件，选择空白项目也不行，我是想按照 Windows程序设计 这本书写入代码，但是要怎么弄呢，建立空白控制台程序写这书上的代码出错，而win32窗体程序又无法建立空白程序，咋办呢

引用 3 楼 user-4的回复:[quote=引用 2 楼 hahajing3998 的回复:] [quote=引用 1 楼 user-4的回复:]微软的编译器是靠后缀区别c和c++的, 后缀名改成c就行了。  不过做软件开发, c++比较好, 反正基本兼容c. 是的前辈，我的意思是，控制台程序可以建立空白项目，然后往里面再加入.c源文件就行了，可是，建立win32窗口程序就没办法只建立空白项目，而是创建后里面有很多的头文件和源文件，选择空白项目也不行，我是想按照 Windows程序设计 这本书写入代码，但是要怎么弄呢，建立空白控制台程序写这书上的代码出错，而win32窗体程序又无法建立空白程序，咋办呢[/quote]  直接空白项目就行，我建立桌面程序从来都是空白程序，建立win32项目只是IDE事先配置好了一些项目属性。 比如: 默认给了一个烂框架, 设置了连接器里面的“子系统”等等。 默认的空白项目很不错，main, wmain, WinMain wWinMain这几个入口函数直接用就行, 自动识别 [/quote] 我换回了xp，学好以后再说吧，用的devc

引用 2 楼 hahajing3998 的回复:[quote=引用 1 楼 user-4的回复:]微软的编译器是靠后缀区别c和c++的, 后缀名改成c就行了。  不过做软件开发, c++比较好, 反正基本兼容c. 是的前辈，我的意思是，控制台程序可以建立空白项目，然后往里面再加入.c源文件就行了，可是，建立win32窗口程序就没办法只建立空白项目，而是创建后里面有很多的头文件和源文件，选择空白项目也不行，我是想按照 Windows程序设计 这本书写入代码，但是要怎么弄呢，建立空白控制台程序写这书上的代码出错，而win32窗体程序又无法建立空白程序，咋办呢[/quote]  直接空白项目就行，我建立桌面程序从来都是空白程序，建立win32项目只是IDE事先配置好了一些项目属性。 比如: 默认给了一个烂框架, 设置了连接器里面的“子系统”等等。 默认的空白项目很不错，main, wmain, WinMain wWinMain这几个入口函数直接用就行, 自动识别


Question: write函数返回值总是为-1

楼主是用读模式打开文件吗？那样肯定不能写了。系统调用返回失败，看看errno是什么才容易定位问题

少了个字，望各位不吝赐教，谢谢


Question: 关于指针的一些问题

引用 3 楼 zwy1114860564 的回复:指针是地址，指向int和指向double的指针有什么不同，指针本身除了地址信息之外，还有其他信息，例如怎么解析这个地址的内容，指向int的指针就说明了这个地址后面的两个字节的内容是可以解析为int的，同理指向double的指针就说这个指针后面的四个字节的内容可以解析为double。可以看到两个指针首先是指向内存大小不一样，然后是最后解析成的内容不一样。 有道理

指针本身是相同类型的， 但用*来取值时，就依赖它所指的变量类型。

指针变量都是用来存放其它类型数据的地址，地址都是一样的  定义为不同类型的指针，主要是便于取值，以及告诉程序员指针指向的是什么类型的数据，便于访问。如将double类型指针强制转换成int型时，在使用*取值符号时，程序就会以Int型格式来取double的数据，而浮点型和整形在存储格式上的差异，导致取出的数据不光是精度的丢失，显示结果完全不一样


Question: C语言新手求助，想编一个小程序但是有一部分卡住了

楼主，可以考虑以字符ASCII码为数组下标值，ASCII总共128个字符 ，就定义128个元素的数组。 先都将time初始化为0，word = 数组下标值（存储字符，便于后续排序，且没必要声明为一个数组，一个char就行）。 当读入一个字符时，直接w[ch]++;   如果统计的是字符串，可以用map，hash_map


Question: 运算符优先级判断

这份代码（http://www.oschina.net/code/snippet_200884_7833）非常值得参考。


Question: 这个素数表输出为什么出问题了？求大神

楼主，你插断点看看，是不是数组越界了

问题明白了记得结贴哦

# include<stdio.h> # define stu 11 int sum(int x, int a[], int st2);  int main(void) {     int a[stu] = { 2 };     int x = 3;     int i = 2;      sum(x, a, stu);      for (i = 2; i < stu; i++)     {         printf("素数表：%d\t", a[i]);     }      return 0; } int sum(int x, int a[], int st2) {     int i = 2;     int b = 3;     int j;      for (j = 2; j < st2; x++, j++)     {         for (i = 2, b = 3; i < x; i++, b++)         {             if (x % i == 0)             {                 x++;                 continue;             }              if (x == b)             { 				/********当b=10时，会出现数组越界，所以会导致程序崩溃*******/                 //a[b] = x; printf("a[b] -> %d\n", a[b]); continue;   				/**************************************** 				* 				* 修改：qianghaohao 				* 出错主要原因是数组越界问题！！！ 				* 				*****************************************/ 				a[b - 1] = x;  				printf("a[b] -> %d\n", a[b -1]); continue;             }  			/*****这样终止循环也会导致数组越界*****/ 			//if (st2 == j) 			//{ 			//	break; 			//} 			         }  		/**************************************** 		* 		* 修改：qianghaohao 		* 出错主要原因是数组越界问题！！！ 		* 将退出循环条件写到外面并改一下条件。 		* 		*****************************************/ 		if (st2 == x) 		{ 			break; 		}     }      {         int i;         for (i = 2; i < st2; i++)         {             printf("实验素数表：%d\t", a[i]);         }     }      return a[b - 1]; 	 }   出错原因已经注释了，主要原因是数组越界问题，程序逻辑设计不太好，所以容易不知不觉就越界了。


Question: 有木有人在吗？关于指针函数的函数指针这个绕绕的词

#include <stdio.h> #include <stdlib.h>  typedef int* (*pfun_t)(void);  int* create(void) {     int* ai = (int*)malloc(sizeof(int));     return ai; }  void destory(int* ai) {     if(ai != NULL){         free(ai);     } }  int main(int argc, char* argv[]) {     /** fun就是指针函数的函数指针 */     pfun_t fun = create;     printf("%p\n", fun);      return 0; }  引用 楼主 yff12321 的回复: 如上，能有味大神给解释一下吗？实在是想不通and想不懂啊？函数指针指向了一个函数的首地址，那指针函数的函数指针又是个什么玩意？

引用 2 楼 yff12321 的回复:[quote=引用 1 楼 cjqpker 的回复:] 首先， 指针函数 —— 是一个函数，这个函数返回值是指针类型 函数指针 —— 是一个指针，这个指针指向一个函数 其次， 函数指针，是个相对比较正式的概念，实际中也会偶尔使用到函数指针，多用于注册回调函数。 指针函数，我觉得不应该作为一个概念被提出来，多半是为了混淆人或达到一种字面上的效果而被提出来的，因为返回值各种各样，没必要把返回指针的函数单独拎出来给个概念。不然，也可以说整形函数、浮点函数、向量函数、引用函数、空函数等等等等，没什么实际用处，楼主不需要重视这个东西。那我想问的是，函数指针a也可以是一个函数吗？我真的有点被绕晕[/quote]  函数指针指向一个函数的地址，而调用函数的过程也就是跳转至函数的首地址处开始执行，因此函数指针可以正常调用的。

引用 1 楼 cjqpker 的回复:首先， 指针函数 —— 是一个函数，这个函数返回值是指针类型 函数指针 —— 是一个指针，这个指针指向一个函数 其次， 函数指针，是个相对比较正式的概念，实际中也会偶尔使用到函数指针，多用于注册回调函数。 指针函数，我觉得不应该作为一个概念被提出来，多半是为了混淆人或达到一种字面上的效果而被提出来的，因为返回值各种各样，没必要把返回指针的函数单独拎出来给个概念。不然，也可以说整形函数、浮点函数、向量函数、引用函数、空函数等等等等，没什么实际用处，楼主不需要重视这个东西。那我想问的是，函数指针a也可以是一个函数吗？我真的有点被绕晕


Question: openssl库使用求解

确定代码是这么写的(../..crypto/evp/evp.h)？..crypto 根本就是错的啊。

这个头文件确实有问题   我也发现了  但是改过来还是会报这个错误


Question: openssl使用问题求解

#由Windows版移至C语言#


Question: 求助,关于c的小问题

#ifdef xxx typedef int elem_type; #define ELEM_FORMAT  "%d" #else typedef char elem_type; #define ELEM_FORMAT  "%c" #endif  ....  printf("Some Worlds"  ELEM_FORMAT  "Other Worlds",  var_of_elem);

可以考虑使用sizeof进行判断。

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

引用 6 楼 CrabKun 的回复:     switch(sizeof(elem_type))     {         case sizeof(int):printf("int");break;         case sizeof(char):printf("char");break;         case sizeof(double):printf("double");break;     }  如果是非内置类型，怎么办？

使用cout

你这段代码不是已经给出了答案了吗elem_type是 int     那么 printf("%d",....) elem_type是 char     那么 printf("%c",....)

C语言中没有直接的办法，可以尝试：  if(sizeof(elem_type) == 1){     printf("%c",....); } else{     printf("%d",....); }

用if + typeid判断进行输出


Question: 新手C求指教

总要把现象说出来吧

你的num3并没有做任何处理，起码得输出一下吧


Question: 文件指针

FILE 是C语言，文件流 数据结构。 FILE指针，不是文件指针，只是FILE流指针，是FILE这种数据结构的指针。  文件指针，指的是文件打开后，准备读写的文件位置， 这个位置文件打开后，文件系统中，存有它的记录。 一些文件操作，会用到它，读写它。  文件指针 ，也不是C语言的指针概念，虽然在某种程度上，有相似的含义。

你只是保存指针地址是没用，要复制整个FILE结构体。  引用 3 楼 u011084550 的回复:[quote=引用 1 楼 user-3 的回复:] 在filecpy的时候，文件指针已经移动到了文件尾部，所以在filecpy的时，可能读不到东西，所以就跳出了。 引用 2 楼 walkiz 的回复:filecopy的时候，fp1和fp2的文件指针已经移到末尾，所以filecmp会出错。你可以在filecmp之前用fseek函数把fp1和fp2的文件指针移到前面：  fseek(fp1, 0L, SEEK_SET); fseek(fp2, 0L, SEEK_SET);  我之前定义了fp5,fp6保存fp1, fp2初始的值,然后在调用filecmp之前又赋值给fp1,fp2,为什么也是一样? [/quote]

引用 1 楼 user-3 的回复:在filecpy的时候，文件指针已经移动到了文件尾部，所以在filecpy的时，可能读不到东西，所以就跳出了。 引用 2 楼 walkiz 的回复:filecopy的时候，fp1和fp2的文件指针已经移到末尾，所以filecmp会出错。你可以在filecmp之前用fseek函数把fp1和fp2的文件指针移到前面：  fseek(fp1, 0L, SEEK_SET); fseek(fp2, 0L, SEEK_SET);  我之前定义了fp5,fp6保存fp1, fp2初始的值,然后在调用filecmp之前又赋值给fp1,fp2,为什么也是一样?


Question: EOF前面必须有个换行符吗?

不需要，linux下按下Ctrl＋D组合键表示EOF，而windows下是按Ctrl＋Z组合键。

不是必须。换行符和普通字符一样对待。


Question: centos中守护进程的fputs（）输出的内容会存到什么地方？

守护进程出错处理 守护进程调用了setsid函数就不再拥有控制终端，所以就无法正常向标准输出stdout或标准出错stderr（比如出错信息）输出信息。幸运的是系统日志守护进程syslogd可以提供这一服务。   Syslog 函数 #include<syslog.h> voidopenlog(char *ident, int option, int facility);         //打开日志 voidsyslog(int priority, char *format, …);                 //写入消息 voidcloselog(void);                                                 //关闭日志


Question: 仿真时VS监视的数据和我赋的值不一致

http://bbs.csdn.net/topics/390676437 char s[20]; sprintf(s,"%lg",num0);

引用 2 楼 wang0635 的回复:二进制里的12.45是无限小数，只能存有限位，所以不准了。小数要都准确，不能用float、double，要自己想办法 谢谢回复：如果想将12.45转化成字符串，那结果完全都不对了，请问有什么解决办法吗

正常


Question: 求助，getchar（）能读取float数吗？

可以用cin直接输入到float变量 如果输入到字符数组中，需要转换成double可以使用_ttof，该函数如果输入的是字母等非法值，返回的是0.0 如果要检查字符数组是否是合法浮点数，可以参看：http://download.csdn.net/download/paschen/4243026

引用 4 楼 qq_30446977 的回复:[quote=引用 3 楼 heroesjun 的回复:] [quote=引用 2 楼 qq_30446977 的回复:] [quote=引用 1 楼 heroesjun 的回复:] 不行的， getchar只能读取一个char，也就是一个字节，但输入一个浮点数，有多个字符。用gets函数和strtof函数： char buf[32] = {0}; gets(buf); float f = strtof(buf, NULL);  怎么判断输入流上哪个是float数呢？？ 怎么判断输入流上哪个是float数呢？？[/quote]  输入流失什么格式，举个例子。[/quote]  原题是，编写一个程序，读入、存储以及输出下列5中类型的字符串，每个字符串占一行，字符串间不能有空格。 1.类型1：一串小写字母，后跟一个数字（如number1 2.类型2：两个单词，每个单词的第一个字母大写，单词间用—分隔（如Olive-Up 3.类型3：小数如3.21 4.类型4：一串大小写字符加空格（如Seven Up 5.类型5：一串除了空格及数字外的任何字符（如floating-point 第1和2编写玩了，第3个就抓瞎了。不过研究半天了，对输入流和返回流了解加深了。已经能做到从流上用gets读取字符到字符串，然后用atof提取浮点数。但是实验半天后发现，发现43.21读到字符串中时，是3个字符分别是“43“、”.”、“21”是3个字符。[/quote]getchar()循环存数组里,然后atof(s)判断返回值时候否是浮点数

你先要理解字符和字符串的区别。

你的需求其实跟自己写词法分析器是一样的，参考http://blog.csdn.net/felicitia/article/details/8109137。

引用 3 楼 heroesjun 的回复:[quote=引用 2 楼 qq_30446977 的回复:] [quote=引用 1 楼 heroesjun 的回复:] 不行的， getchar只能读取一个char，也就是一个字节，但输入一个浮点数，有多个字符。用gets函数和strtof函数： char buf[32] = {0}; gets(buf); float f = strtof(buf, NULL);  怎么判断输入流上哪个是float数呢？？ 怎么判断输入流上哪个是float数呢？？[/quote]  输入流失什么格式，举个例子。[/quote]  原题是，编写一个程序，读入、存储以及输出下列5中类型的字符串，每个字符串占一行，字符串间不能有空格。 1.类型1：一串小写字母，后跟一个数字（如number1 2.类型2：两个单词，每个单词的第一个字母大写，单词间用—分隔（如Olive-Up 3.类型3：小数如3.21 4.类型4：一串大小写字符加空格（如Seven Up 5.类型5：一串除了空格及数字外的任何字符（如floating-point 第1和2编写玩了，第3个就抓瞎了。不过研究半天了，对输入流和返回流了解加深了。已经能做到从流上用gets读取字符到字符串，然后用atof提取浮点数。但是实验半天后发现，发现43.21读到字符串中时，是3个字符分别是“43“、”.”、“21”是3个字符。

引用 2 楼 qq_30446977 的回复:[quote=引用 1 楼 heroesjun 的回复:] 不行的， getchar只能读取一个char，也就是一个字节，但输入一个浮点数，有多个字符。用gets函数和strtof函数： char buf[32] = {0}; gets(buf); float f = strtof(buf, NULL);  怎么判断输入流上哪个是float数呢？？ 怎么判断输入流上哪个是float数呢？？[/quote]  输入流失什么格式，举个例子。

引用 1 楼 heroesjun 的回复:不行的， getchar只能读取一个char，也就是一个字节，但输入一个浮点数，有多个字符。用gets函数和strtof函数： char buf[32] = {0}; gets(buf); float f = strtof(buf, NULL);  怎么判断输入流上哪个是float数呢？？ 怎么判断输入流上哪个是float数呢？？