Question: 循环嵌套问题求解

晕，还是看错打印部分了，打印在外循环。 你就理解while的分析就好了，打印部分忽略

上面打印部分说错了，打印部分在内循环外，看错了，看成打印部分在内循环了。 首先要理解，b--是先取b的值做运算，运算结束后b的值递减1 所以 i=1第一次大循环 b=i%2=1 然后第一次内循环 b=1，while(b-->=0)的执行顺序是，先取b的值1来做比较运算，运算结果为true，然后b递减1变为0，然后while(运算结果true)满足循环条件，进入内循环执行k++，k变为1（这里看错了，没有打印信息） 然后第二次内循环 b=0，while(b-->=0)的执行顺序是，先取b的值0来做比较运算，运算结果为true，然后b递减1变为-1，然后while(运算结果true)满足循环条件，进入内循环执行k++，k变为2 然后第三次内循环 b=-1，while(b-->=0)的执行顺序是，先取b的值-1来做比较运算，运算结果为false，然后b递减1变为-2，然后while(运算结果false)不满足循环条件，内循环结束 然后执行打印，b=-2，k=2（这里才有打印） 然后继续i=2第二次大循环 b=i%2=0 然后内循环，while(b-->=0)的执行顺序同上 依次类推，直到大循环结束

分析图已经很明确了 首先要理解，b--是先取b的值做运算，运算结束后b的值递减1 所以 i=1第一次大循环 b=i%2=1 然后第一次内循环 b=1，while(b-->=0)的执行顺序是，先取b的值1来做比较运算，运算结果为true，然后b递减1变为0，然后while(运算结果true)满足循环条件，进入内循环执行k++，k变为1，打印b=0，k=1 然后第二次内循环 b=0，while(b-->=0)的执行顺序是，先取b的值0来做比较运算，运算结果为true，然后b递减1变为-1，然后while(运算结果true)满足循环条件，进入内循环执行k++，k变为2，打印b=-1，k=2 然后第三次内循环 b=-1，while(b-->=0)的执行顺序是，先取b的值-1来做比较运算，运算结果为false，，然后b递减1变为-2，然后while(运算结果false)不满足循环条件，内循环结束 内循环结束后继续i=2第二次大循环 b=i%2=0 然后内循环，while(b-->=0)的执行顺序同上 依次类推，直到大循环结束

b-- >=  0注意是先把b--整个表达式的值与0比较，再计算自减～


Question: 这个整么进行.txt文件读取啊  请教大神！！！

蟹蟹 蟹蟹 弄好了

单行读取，查看strtok函数用法，进行字符串分割，放到字符串数组中。 这是一位大神关于c语言字符串的分割函数。供参考：https://www.cnblogs.com/wkfvawl/p/9042695.html 如果在linux上，还可以考虑用 cut  ，awk 命令。

首先，让你的程序和你要读取的txt在同一个文件夹里（不然你要自己手动敲地址），运用freopen，即freopen（"a.txt","r",stdin）;这一条语句，a.txt是你的文件名，r是以只读模式打开，stdin则是以标准形式读入， 如下： #include<stdio.h> int main() { 	freopen("a.txt","r",stdin); }

fscanf读取，因为是有固定格式的。

根据每个单元的偏移按行读取

不是以空格来分隔了？


Question: 如何在vs code 中实现不同C语言程序之间的函数互相调用的问题？

C和C++完整教程:https://blog.csdn.net/it_xiangqiang/category_10581430.html C和C++算法完整教程:https://blog.csdn.net/it_xiangqiang/category_10768339.html

你这是visual studio吧

不好意思，我这里更正一下文件main.c的内容  # include "stdio.h" # include "function.h"   /*包含的头文件*/ int main() { int a=2; int b=4;         printf( "%d\n",fun(a,b));         printf( "%d\n",times(a,b));         return 0; }

这还不算难的，难的是不同架构间，不同系统、编译器不一样之间的相互调用。


Question: printf("now i=%d,flag=%d",i,flag);这条语句会执行吗？

不会执行，因为这条语句和break在同一个代码块里，并且实在break之后，根据顺序执行，执行到break之后后面的就不会执行了，直接跳出循环了～

不会，跳出循环


Question: 请问一下我的代码怎么不能自动登录到指定网页?求助大神解析一下.

问题是为什么会登录对应的网站，网站的打开需要浏览器，楼主用命令并没有调用浏览器吧  建议了解一下网页打开的原理～


Question: c 语言指针变量相减

指针 - 指针 = 两者差／指针所指向变量类型的长度  例如，int *a = 12; int*b = 6; a - b = (12-6)/4;  这里说的int类型字节长度为4

引用 8 楼 真相重于对错的回复:[quote=引用 3 楼 sunjianan2020418 的回复:][quote=引用 1 楼 自信男孩的回复:]没什么问题，是对指针赋值呢。5,8地址。楼主并没有对5,8对应的内存做读写操作呢？只是指针的加减法，类似普通变量的加减法～ 为什么最后等于零了[/quote] char** 指向的地址里面存放的是char*,char* 的长度是4字节（32位），8 和 5之间不能存放一个char* ,指针相减结果是二者之间能够放多少个这个类型的数据 所以p1-p2 放不下一个，因此为0 如果改成char* p1 ,*p2; p1-p2 就是3[/quote] 这个回答是正解

引用 7 楼 千梦一生的回复:[quote=引用 6 楼 千梦一生 的回复:]就是说，指针在电脑看来跟int没任何区别。唯一不同在于：你指定它是指针，那么，电脑就听你的把int的值当作地址来看。 再描述就是：你可以认为指针就是一个int【跟int一模一样】，但它被你叫做指针，所以，电脑允许你通过（*指针）的方式去把该int的值作为地址访问指向的数据。[/quote] 懂了谢谢

引用 9 楼 暮霞。的回复:我觉得是因为，你的p，q都没有开辟指针的空间，在后面	p = (char**)5;q = (char**)8;这两句就好像是强行给两个指针空间地址 指针相减的结果=(地址1-地址2)/sizeof(类型) 如上就是 （8 - 5）/ 4 = 0.75 但是由于会默认输出int类型，因为0 好的谢谢你

对的就是这样

用gcc编译不行，打印不出来；不理解。

引用 3 楼 sunjianan2020418 的回复:[quote=引用 1 楼 自信男孩的回复:]没什么问题，是对指针赋值呢。5,8地址。楼主并没有对5,8对应的内存做读写操作呢？只是指针的加减法，类似普通变量的加减法～ 为什么最后等于零了[/quote] char** 指向的地址里面存放的是char*,char* 的长度是4字节（32位），8 和 5之间不能存放一个char* ,指针相减结果是二者之间能够放多少个这个类型的数据 所以p1-p2 放不下一个，因此为0 如果改成char* p1 ,*p2; p1-p2 就是3

引用 6 楼 千梦一生 的回复:就是说，指针在电脑看来跟int没任何区别。唯一不同在于：你指定它是指针，那么，电脑就听你的把int的值当作地址来看。 再描述就是：你可以认为指针就是一个int【跟int一模一样】，但它被你叫做指针，所以，电脑允许你通过（*指针）的方式去把该int的值作为地址访问指向的数据。

两个指针相减的意义在于，假定它们指向同一个数组内的不同元素，则相减后，得到两个元素下标的差值。

引用 2 楼 千梦一生的回复:你写的是代码。 机器理解的是0、1 中间有个叫编译器的为你把你的代码翻译给机器听。 指针、int的区别是编译器看的。机器看指针和int没区别 说的浅点呗还是不懂啊

引用 1 楼 自信男孩的回复:没什么问题，是对指针赋值呢。5,8地址。楼主并没有对5,8对应的内存做读写操作呢？只是指针的加减法，类似普通变量的加减法～ 为什么最后等于零了


Question: float尾数只有23位能够精确24位最大数是16777215.根本精确不到3.4e38这个取值范围。如果我赋值一个数大于

浮点数是表示范围大, 但是精度不高,  23位二进制精度用10进制就是6-7位精度, 超过的精度会丢失  f=16777219.0  e=log(f)/log(2) e=0+(e|0)  m=(1<<23) n=(f/pow(2,e) - 1.0) n=n*m n=((n+0.5)|0)                         //这里四舍五入, 精度丢失  h = 0 | ((e+0x7f)<<23) | n    // 这里是16进制储存数据  v=h&(m-1) v=(v+0.0)/m f=(1.0+v)*pow(2,e)              // 这里最终结果成了  16777220    以下是计算步骤:  f = 16777219.00000000 16777219.00000000 e = log ( f ) / log ( 2 ) e = 16.63553251225261 / log ( 2 ) e = 16.63553251225261 / 0.6931471805599453 e = 24.00000025797396 24.00000025797396 e = 0 + ( e | 0 ) e = 0 + 0x0000000000000018 e = 24 24 m = ( 1 << 23 ) m = 0x0000000000800000 0x0000000000800000 n = ( f / pow ( 2 , e ) - 1.000000000000000 ) n = ( f / 16777216.00000000 - 1.000000000000000 ) n = ( 1.000000178813934 - 1.000000000000000 ) n = 1.788139343261719E-007 1.788139343261719E-007 n = n * m n = 1.500000000000000 1.500000000000000 n = ( ( n + 0.5000000000000000 ) | 0 ) n = ( 2.000000000000000 | 0 ) n = 0x0000000000000002 0x0000000000000002 h = 0 | ( ( e + 0x000000000000007F ) << 23 ) | n h = 0 | ( 151 << 23 ) | n h = 0 | 0x000000004B800000 | n h = 0x000000004B800000 | n h = 0x000000004B800002 0x000000004B800002 v = h & ( m - 1 ) v = h & 0x00000000007FFFFF v = 0x0000000000000002 0x0000000000000002 v = ( v + 0.0000000000000000 ) / m v = 2.000000000000000 / m v = 2.384185791015625E-007 2.384185791015625E-007 f = ( 1.000000000000000 + v ) * pow ( 2 , e ) f = 1.000000238418579 * pow ( 2 , e ) f = 1.000000238418579 * 16777216.00000000 f = 16777220.00000000 16777220.00000000

自定义想要的数据类型，重载需要的计算方式。

看我的问题在回答，我不是要你告诉我单精度是怎么存储的。我的问题是如果尾数超出23位后怎么转换成十进制比如 我定义一个float016777219二进制是1.00000000000000000000011*24尾数已经24位了超出尾数表示范围了。单结果是16777220是为什么 我的问题是如果指数超过23位后比如指数是25怎样还原十进制

https://www.cnblogs.com/fengliu-/p/7455246.html 建议了解一下这个～


Question: C语言中的@符号是什么意思？

没见过这个运算符

建议提供更多的信息，比如代码～  在C语言里没遇到过@运算符～


Question: 链表中的删除问题

#include <stdio.h> #include <stdlib.h> #include <time.h>  typedef struct node {     int data;     struct node *next; }Node;  //void Creat(Node *h) void Creat(Node **h) {     int i,n;     Node *p , *node;     //h->next = NULL;     //p = h;     srand(time(0));     printf("请输入结点数量：");     scanf("%d",&n);     for (i = 0; i < n; i++)     {         node = (Node*)malloc(sizeof(Node));         node->data = rand() % n;         if (*h == NULL) {             (*h) = node;             p = (*h);         } else {             p->next = node;             p = node;         }     }     p->next = NULL; }  //void Delete(Node *h)   //n为被删除数据所在的位置 void Delete(Node **h)   //n为被删除数据所在的位置 {     int i,n;     Node *p=*h;     Node *q;     printf("请输入要删除第几个数据：");     scanf("%d",&n);      if (n == 1) {         *h = (*h)->next;         free(p);         return;     }     for (i = 1; i < n-1; i++)     {         if (!p)             break;         p = p->next;     }     if (!p) {         printf("Can't find it!\n");         return;     }      //q = p;     q = p->next;     if (!q) {         printf("Can't find it!\n");         return;     }     //p->next = (q->next)->next;     p->next = q->next;     //free(q->next);     free(q); }   void Print(Node *h) {     Node *p;     p = h;     printf("数据如下：");     //while (p->next != NULL)     while (p != NULL)     {         printf("%d ",p->data);         p = p->next;     }     printf("\n"); }  int main(void) {     Node *head = NULL;      Creat(&head);     Print(head);     Delete(&head);     Print(head);     return 0; } 供参考～  楼主的创建链表，删除链表以及输出都有问题～

最好画个图这样更清晰一些 修改如下  for (i = 1; i < n; i++) {      p = p->next; } q = p->next; p->next = q->next; free(q)


Question: 常指针和指针常量

int* 声明一个指向内容为int类型指针从 可以类比 const *  是在声明一个指向内容为常量类型的指针 【并且实际情况也正是如此】

引用 7 楼 Wyk2016 的回复:[quote=引用 1 楼 千梦一生的回复:]简单的一匹  * 和const的位置可以读出正确的名字  int* int 的 指针【即指针指向的内容是int】  const *  常量 的 指针 【即指针指向的内容是常量】  const int* int型常量 的 指针【即指针指向的内容是int型常量】   区分两者把语文学好就可以了 没有自己的见解，太死板，没有精髓，[/quote]  这就是我过去学习后自己的理解。难道你认为我是从哪里抄来的吗？ 最后发现区分指针常量、常量指针只需要看 * 和const的相对位置就行了。 而辨识二者的区别，则只需要把语文常识学好就行了。找到定语即可

引用 1 楼 千梦一生的回复:简单的一匹  * 和const的位置可以读出正确的名字  int* int 的 指针【即指针指向的内容是int】  const *  常量 的 指针 【即指针指向的内容是常量】  const int* int型常量 的 指针【即指针指向的内容是int型常量】   区分两者把语文学好就可以了 没有自己的见解，太死板，没有精髓，

引用 5 楼 Wyk2016的回复:各位大神，细品，什么是精练， 4楼的弟兄提议很好，

各位大神，细品，什么是精练，

const* 常指针强调你不可以通过本指针来操作其指向的内容 这句话需要改一下，不可以通过本指针来修改（写）其指向的内容，不包括读哦，是可以读的

说起来挺可笑的，绝大多数C语言图书都没把这个问题讲清楚。

指向常量的指针表示该指针中存放的是常量的地址，常量指针指的是指针本身是常量，不能修改该指针中保存的地址，而该地址保存的可以是常量也可以是变量。 具体区别请参考《C++中指向常量的指针和常量指针》 希望能够帮到您！


Question: 关于c语言返回值的地址问题

把lptr赋值给头文件里的rtn。 这句话如果使用memcpy或者sprintf的话，应该是没有问题的。  可以在free掉lptr 只有加一句打印。 打印一下此时的rtn。看看问题出在哪里。

不知道。 不过如果是水平不到位的程序容易犯的一个错误是返回局部变量地址。这种是不安全不正确的

你把代码贴全了 要知道fun是怎么返回结果的才能帮你分析

引用 11 楼 自信男孩的回复:[quote=引用 6 楼 subosen 的回复:][quote=引用 4 楼 自信男孩的回复:]你的代码呢？从你的描述来看，看不出为什么的。fun函数返回的是什么地址，局部变量地址，还是全局变量地址以及静态变量等等这些不清楚呢 头文件定义返回的数据 char rtn[1024]; 下面是外部函数逻辑 char* fun(char* p){ char* lptr ; 下面逻辑省略写了哈 malloc开辟lptr的空间 一系列操作 把lptr赋值给头文件里的rtn free掉lptr return rtn; } 逻辑大致这样[/quote] 没看到参数p做了什么？那么这个参数有啥意义呢？[/quote] 在一系列操作里

引用 6 楼 subosen 的回复:[quote=引用 4 楼 自信男孩的回复:]你的代码呢？从你的描述来看，看不出为什么的。fun函数返回的是什么地址，局部变量地址，还是全局变量地址以及静态变量等等这些不清楚呢 头文件定义返回的数据 char rtn[1024]; 下面是外部函数逻辑 char* fun(char* p){ char* lptr ; 下面逻辑省略写了哈 malloc开辟lptr的空间 一系列操作 把lptr赋值给头文件里的rtn free掉lptr return rtn; } 逻辑大致这样[/quote] 没看到参数p做了什么？那么这个参数有啥意义呢？

引用 6 楼 subosen 的回复:[quote=引用 4 楼 自信男孩的回复:]你的代码呢？从你的描述来看，看不出为什么的。fun函数返回的是什么地址，局部变量地址，还是全局变量地址以及静态变量等等这些不清楚呢 头文件定义返回的数据 char rtn[1024]; 下面是外部函数逻辑 char* fun(char* p){ char* lptr ; 下面逻辑省略写了哈 malloc开辟lptr的空间 一系列操作 把lptr赋值给头文件里的rtn free掉lptr return rtn; } 逻辑大致这样[/quote] 楼主的是返回全局变量，如果不一致，那么看一下最后修改的是那个？

printf(,f(1),f(2));  f(1),f(2) 先于printf();  f(1),f(2)两个 形式一样的函数连续调用，第一个malloc【比如结构体A大小的数据1】后free掉它。紧跟着第二个函数一模一样的函数调用，再次malloc【由于上下文、以及环境几无变化，因此我认为】操作系统极有可能就又把你释放的那一块拿来给你用【比如你在这里创建了一个结构体A大小的数据2】，后再free掉它。 ------------------------此时f(1),f(2)返回的都是野指针，但都指向了第二个执行的【f(1)或者f(2)之一】f()函数处理后的数据：数据2 紧跟着printf(，数据2的指针【野指针，危险】，数据2的指针【野指针，危险】)

引用 6 楼 subosen 的回复:把lptr赋值给头文件里的rtn free掉lptr return rtn; 返回了个野指针

我是楼主，因为项目信息安全原因不能贴代码，只能大致说一说不好意思哈(T ^ T)

引用 4 楼 自信男孩的回复:你的代码呢？从你的描述来看，看不出为什么的。fun函数返回的是什么地址，局部变量地址，还是全局变量地址以及静态变量等等这些不清楚呢 头文件定义返回的数据 char rtn[1024]; 下面是外部函数逻辑 char* fun(char* p){ char* lptr ; 下面逻辑省略写了哈 malloc开辟lptr的空间 一系列操作 把lptr赋值给头文件里的rtn free掉lptr return rtn; } 逻辑大致这样

引用 1 楼 user-5的回复:你把代码贴全了 要知道fun是怎么返回结果的才能帮你分析 头文件定义返回的数据 char rtn[1024]; 下面是外部函数逻辑 char* fun(char* p){ char* lptr ; 下面逻辑省略写了哈 malloc开辟lptr的空间 一系列操作 把lptr赋值给头文件里的rtn free掉lptr return rtn; } 逻辑大致这样


Question: 为什么我输入第九个值后，才会倒序打印前8个值？

您好，首先整理您的代码如下： #include <stdio.h>  int main(void)  { 	int number[8],a; 	 	for (a = 0;a < 8;++a) 		scanf_s("%d ", &number[a]); 		 	for (a = 7;a >= 0;a--) 		printf("%d ", number[a]); 		 	printf("\ndone"); 	 	return 0; }  其次我参考了如下网址： https://blog.csdn.net/silleyj/article/details/8545408  接着我使用了在线编译，模拟了您的代码，有如下几种情况 1、当输入 7 个参数时，由于是在线模拟，他自己给我补了一个随机数上去，然后倒序打印出 8 个数； 2、当输入 8 个参数时，可以正常倒序打印； 3、由上述两种情况分析，代码应该是没问题的。  思考方向： 1、参考上述网址，使用 scanf_s 时，是否要加第三个指定数据长度的参数？ 2、在输入第 8 个数值之后，是否有按下回车的操作？个人感觉，如果没有此操作，编译器可能不知道你是否输入完毕，只有当你输入第 9 个元素时，超出数据范围，才会跳出。  建议： 1、后续代码建议直接放到代码框中，便于阅读~

#include <stdio.h>  int main(void) {     int number[8],a;     for (a = 0;a < 8;++a)         //scanf_s("%d ", &number[a]); 	scanf_s("%d", &number[a]);     for (a = 7;a >= 0;a--)         printf("%d ", number[a]);     printf("\ndone");     return 0; } 供参考～  去掉%d后面的空格


Question: 删除字符串中指定的字符

上面有点错误，稍微修改 while(str[i]!=‘\0’) {     while (str[i]==c) { //这里用while，因为后面移向前的字符也可能是c         for(j=i; str[j]!=‘\0’; j++) {             str[j]=str[j+1];         }     }     i++; } 这个算法太频繁移动元素了，效率不高 改成以下更好一些 for(i=0,j=0; str[i]!=‘\0’; i++) {     if(str[i]!=c) str[j++] = str[i]; //只保存不为c的字符 } str[j]=‘\0’; //最后加上字符串符

把while(str[i]==c)改成while(str[i]!=‘\0’) 否则一旦str[i]!=c循环就结束了了，后面还有str[i]==c也不会被处理了 所以 while(str[i]!=‘\0’) {     if (str[i]==c) {         for(j=i; str[j]!=‘\0’; j++) {             str[j]=str[j+1];         }     }     i++; }

char *de_character(char* src, int ch) {     char *ret = src;     char *dst = src;     while (*src) {         if (*src != ch)             *dst++ = *src;         src++;     }     *dst = '\0';      return ret; }  供参考～


Question: srand()和rand()

C:\Program Files (x86)\Windows Kits\10\Source\10.0.10150.0\ucrt\stdlib\rand.cpp // // rand.cpp // //      Copyright (c) Microsoft Corporation. All rights reserved. // // Defines rand(), which generates psuedorandom numbers. // #include <corecrt_internal.h> #include <stdlib.h>    // Seeds the random number generator with the provided integer. extern "C" void __cdecl srand(unsigned int const seed) {     __acrt_getptd()->_rand_state = seed; }    // Returns a pseudorandom number in the range [0,32767]. extern "C" int __cdecl rand() {     __acrt_ptd* const ptd = __acrt_getptd();      ptd->_rand_state = ptd->_rand_state * 214013 + 2531011;     return (ptd->_rand_state >> 16) & RAND_MAX; }

srand是设置随机数的种子， 正常情况下，这个函数不应当过于频繁的调用，一般程序运行时初始化一次即可。

The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand().  These sequences are repeatable by calling srand() with the same seed        value  srand是生成随机数的种子，如果放在循环里，那么就是种子跟着变化，那么生成的就是相同序列的数值。

在C++中产生随机数的步骤分为两步：第一步是设置起始数；第二步是产生伪随机数。 srand()函数的作用是设置起始数，当起始数相同时，产生的随机数也是相同的，在for循环内部，您每次调用time()函数获取的时间都相同（for循环消耗的时间太短），即起始数是相同的，所以您获取到的随机数也是相同的。可以考虑在for循环中加一个延迟函数，例如 	for (i = 0; i < 10; i++) 	{ 		srand((time(NULL))); 		a[i] = rand() % 10; 		Sleep(1000);//-------延迟1秒--------- 	} 这样，每次调用time得到的就是不同的时间了，因此也会得到不同的随机数。需要注意的是，使用Sleep()函数，需要 #include <Windows.h> 另外，对于srand()函数和rand()函数产生随机数的详细方法，请参考《C++中产生随机整数的方法（srand()函数与rand()函数）》 希望能够帮到您！

谢谢各位了，明白了


Question: 创建快捷方式为什么需要管理员运行？

引用 5 楼 六道佩恩 的回复:话说这是在用指针访问C++的方法吗？ 微软为 COM 接口定义了自己的 ABI，并要求所有使用 COM 接口的编程语言都按照这个 ABI 进行操作。因此，无论是用 C 还是 C++ 语法访问 COM 接口，最终生成的 ABI 都是与 COM 兼容的，造成了 C 能访问 C++ 方法的“假象”。但在非 COM 代码中强烈不建议这么做，因为会损害稳定性和可移植性。

引用 4 楼 user-1 的回复:[quote=引用 3 楼 六道佩恩 的回复:] 你这个不是C接口啊，我要C接口的 可参考 https://gitee.com/apkipa-byte/codes/qcwvad58tonkrgemz0jxl46/raw?blob_name=main.c，基于我给出的链接中的 C++ 例子。[/quote] 话说这是在用指针访问C++的方法吗？

引用 3 楼 六道佩恩 的回复:你这个不是C接口啊，我要C接口的 可参考 https://gitee.com/apkipa-byte/codes/qcwvad58tonkrgemz0jxl46/raw?blob_name=main.c，基于我给出的链接中的 C++ 例子。

引用 1 楼 user-1 的回复:CreateSymbolicLinkA 创建的是符号链接，不是所谓的快捷方式。创建快捷方式请使用 IShellLink 和 IPersistFile 接口。具体操作请参考 https://docs.microsoft.com/zh-cn/windows/win32/shell/links。 你这个不是C接口啊，我要C接口的

引用 1 楼 user-1 的回复:CreateSymbolicLinkA 创建的是符号链接，不是所谓的快捷方式。创建快捷方式请使用 IShellLink 和 IPersistFile 接口。具体操作请参考 https://docs.microsoft.com/zh-cn/windows/win32/shell/links。 这两种有什么区别？区别大吗？


Question: C语言在处理UTF-8字符时，数据类型为什么用char *，而不是unsigned char *？

在C语言里，char类型可能等同于signed char，也可能等同于unsigned char，可以在编译时指定char类型到底等同于哪一个。要不，你问问Linux在编译时是怎么指定的？

字符集编码现在也没有搞清楚

因为涉及字节运算，我经常会遭遇符号位扩展方面的困扰，搞得简直都有些抑郁了！ 不得不条件反射地、歇斯底里地、不停地： x & 0xFF;  似乎只要一不留神，就会被符号位给坑害啦！呵呵。

只有右移对有符号数、无符号数有不同操作，其他都没影响

引用 2 楼 千梦一生 的回复:字符你认为拿来进行数字计算的可能性会多大？ 即便遇到了需要对字符编码进行数字运算。能这么做的估摸也对字符有一定的认识，会漏下这个？ unsigned 的意义完全就属于数学运算上的意义。 如果对字符确实有数学运算这方面的需求，可以根据具体运算情况进行选择是否unsigned。  若考虑到字符加密，需进行字节逻辑运算：^&|~的话，估计就不会轻下这个结论了。

樓上說得對，它的意義僅僅在於“開闢一塊内存區”

搞编码的，搞内存处理哪方面的人而言，{int、 unsigned int}，{char*，void*，...*},{int8,char, unsigned char}这些 真区别不大

要看具體的處理代碼，char的符號位有用也僅是在當作短整數使用的情況

我感觉啊。可能是因为少打一个unsigned的原因。

位運算不需要考慮符號位，一樣處理


Question: c语言如何实现窗口滚动？

VS，win32 console工程就是控制台窗口，一个黑色窗口


Question: 为什么while循环执行不了，菜鸟很懵逼

问题不少,优化一下,我也是菜鸟,马上三年级  #include <stdio.h> int main()   { 	int number, min, max, count, /*status,*/ sum;  	//sum = 0;  	count = 0;  	printf("Enter lower and upper integer limits:");  	//scanf_s("%d %d", &min, &max);  	//status = (scanf_s("%d %d", &min, &max) == 2);  	while (scanf_s("%d %d", &min, &max)!=EOF) 	{ 		sum = 0;//防止多次操作累加  		for (number = min; number <= max; number++) 		{ 			count = number * number; 			sum += count; 		} 		printf("The sums of the squares from %d to %d is %d", min , max , sum); 		//printf("Enter next set of limits :"); 		//scanf_s("%d %d", &min, &max); 	} 	printf("Done"); 	return 0; }

应该是if (status)  否则死循环了

可以在while循环前打印一下status的值，看是否满足循环条件

谢邀。 scanf_s("%d %d", &min, &max); status= (scanf_s("%d %d", &min, &max)==2); while (status)  {  以上，scanf_s调用了两次，这是没有必要的。可以保留第二个。 while语句要求括号内的控制表达式不为0，但是在while语句的循环体内又没有改变status的值，所以并不是没有循环，是它无法停下来。

调试结果的图片发错了，不好意思

int number, min, max, count, sum, status; 	sum = 0; 	count = 0; 	printf("Enter lower and upper integer limits:"); 	//scanf_s("%d %d", &min, &max);//------注释掉这一行，下面还有一行代码是输入------- 	status = (scanf_s("%d %d", &min, &max) == 2); 	while (status) { 		for (number = min; min <= number&& number <= max; number++) {//min <= number <= max改为min <= number&& number <= max 			count = number * number; 			sum += count; 		} 		printf("The sums of the squares from %d to %d is %d\n", min*min, max*max, sum);//-----添加换行符号-------- 		printf("Enter next set of limits :"); 		scanf_s("%d %d", &min, &max); 	} 	printf("Done"); VS2015 C++环境跳调试 关于修改min <= number <= max的原因是，在C++中，min <= number <= max并不是像数学中的number大于等于min并且number小于等于max的意思，而是先计算min<=number，这个表达式的结果是true或者false，即1和0，假设是true，则是1，之后再比较1<=max，如果你输入的max是大于等于1的，则min <= number <= max的结果始终是true，就像楼上朋友说的，for是死循环了。所以要把min <= number <= max改成 min <= number&& number <= max

执行不了还好，要是执行了就死循环了 while (status) //循环里没有改变status的处理，一旦进入循环就死循环了  执行不了说明你输入不对 status= (scanf_s("%d %d", &min, &max)==2); 所以status为false 根据的你的代码，你要输入两次数据才行 scanf_s("%d %d", &min, &max); //这里需要输入一次 status= (scanf_s("%d %d", &min, &max)==2); //这里还需要输入一次（为啥不和上面合并？），所以估计这里你忘了输入直接回车，就造成输入不对


Question: 求大佬帮我看看这段链表代码

按照2L的思路写的段代码，没测试过，如果代码有问题LZ自己修改吧   struct ListNode* rotateRight(struct ListNode* head, int k){     if (head->next==NULL || head==NULL) return head;     int size = 0, pos = 0;     struct ListNode *temp = head;     struct ListNode *tail = head;     while (tail != NULL) { //算链表长度         size++;         tail = tail->next;     }          k = k%size; //算出移动个数     if (k==0) return head; //如果刚好转一圈，则链表不变          tail = head;     while (tail->next != NULL) {         pos++;         if (pos == size-k) { //如果             head = tail->next; //记录新head             tail->next = NULL; //新head之前的node变成了新的末节点，所以要修改其next为null             tail = head; //tail指向新head继续循环，找到旧链表的末节点             if (head->next == NULL) break; //如果新head刚好是旧链表的末节点则中断循环         }         tail = tail->next;     }     tail->next = temp; //旧链表的末节点指向旧head     return head; }

末尾移动的元素的个数为k%链表长度（因为k==链表长度就刚好转一圈绕回原地） 比如 示例1，k=2，链表长度是5，所以移动k(2)%链表长度(2)=2 示例2，k=4，链表长度是3，所以移动k(4)%链表长度(3)=1


Question: 大佬们可以帮帮我吗（我是初学者）

引用 1 楼 user-4的回复:其实if(k>=i)改成if(k==i)就可以 因为for(k=2; k<i; k++)里，如果if(i%k==0)一直不满足，k最终=i才会结束循环，所以用if(k==i)就可以了；同时，因为if(i%k==0)一直不满足k才能走到i，所以k走到i就说明没有一个数可以被i整除（如果有，就会break，k就不可能走到i），那就说明i是素数。 好的，差不多懂啦，谢谢老哥

引用 3 楼 青山七海58的回复:论坛上你问语言的问题，懂的人会很乐意回答你，因为一看就知道。这种算法思路的问题要是有人肯花时间帮你看你就偷着乐吧。 哈哈哈哈好哒

引用 4 楼 棉猴的回复:int fun(int m) { 	int i, k; 	for (i = m + 1;; i++)  	{ 		for (k = 2; k < i; k++) 		{ 			/**************found**************/ 			if (i % k == 0)//-----如果等于0，说明i不是素数 			{ 				break;//如果i不是素数，则跳出for (k = 2; k < i; k++)，此时k的值小于i 			} 			/**************found**************/ 		} 		if (k >= i)//该行代码用于判断for (k = 2; k < i; k++)循环是怎么结束的（1）当k==i时for循环自然结束（2）当i%k==0时break结束 			//如果是（1）则说明i是素数，如果是（2）则说明i不是素数 		{ 			return(i); 		} 	} } 另外，对于for循环，还是加上大括号的好，即使只有一行执行代码！ 谢谢老哥的解答

int fun(int m) {     int i, k;     for (i = m + 1;; i++) {         for (k = 2; k < i; k++)             /**************found**************/             if (i % k == 0)                 break;         /**************found**************/         if (k == i)             return(i);     } }  void main() {     int n;     n = fun(2);     printf("n=%d\n", n); }   for (k = 2 ; k < i ; k++)  此循环中，k==i时退出，表示i不能被从2到i-1的整数整除。


Question: unix下动态库和头文件的问题

1 主程序没引入头文件，程序里是用dlopen，dlsym的方式来调用动态库so的吗？如果是这样，编译时没必要指定so，主程序运行到dlopen时才会加载链接库 2 引入头文件并指定链接库一起编译，这样的方式，主程序在一起动时就加载链接库  你所谓的执行区别就是指这个吧，前者会在用到链接库时才加载so，后者是在主程序一起动就加载链接库so


Question: 求大佬帮忙分析这份代码的思路

第N行的第J个数就是第N-1行的第J个和第J-1个的和,自己推才有意思哈

为什么刚好得到不同阶的数？

这个for循环，每循环一次，得到不同阶数的值，例如第一次循环得到[1，1],第二次循环得到[1,2,1]，第三次循环得到[1,3,3,1]

引用 3 楼 qybao 的回复：这个for要结合上面的array[i] = 1和下面的array[0] = 1一起来看 首先要知道i层循环的意义，i层循环的结果就是得到第i行的数据，如1L所说 那么来看具体分析 array[i] = 1 这里首先就是设定第i行的最后一个元素 然后for j 循环依次倒推第i行的i-1位置之前的元素 //先理解这个，下面再详细展开 最后再array[0] = 1设定第i行的0位置的元素，这样第i行的数据就生成了  好，再来展开for j 循环 i=0时，array[i]=array[0]=1，for j循环没有满足跳过执行，最后array[0]=1，所以第i=0行的结果就只有1个元素 array[0]=1，即array[]={1}  i=1时，array[i]=array[1]=1，看到了没，相当于在第0行的基础上，在最后的位置最后追加一个元素（也就是多了个元素），即array[0]=1(原来i=0循环时生成)，array[1]=1(本次i循环时生成的)，然后for j没满足跳过执行，最后array[0]=1，所以第i=1行的结果就是有2个元素，即array[]={1,1}  i=2时，array[i]=array[2]=1，看到了没，又在第1行的基础上在末尾多追加了一个元素array[2]=1，即此时 array[]={1,1,1}，然后进入for j循环，倒推array[2]位置之前的元素，首先看j=i-1，即array[i-1]=array[1]的情况，我们用图的方式展示 i=1时，array[]={1,1} //这是上一次i循环的结果，也就是第1行 i=2时，array[]={1,1,1} //这是本次i循环，也就是第2行，array[j]=array[i-1]是不是相当于第1行的最后一个元素（蓝上）？那么array[j-1]是不是相当于第1行的倒数第二个元素（绿上）？所以array[j](蓝上)+array[j-1](绿上)=array[j](蓝下)=1+1=2 所以就可以倒推出第2行的j位置的元素，依次继续往前类推，直到for j循环结束，最后再array[0]=1，就是把第2行的首元素设为0，所以最终结果，第i=2行有3个元素，即array={1,2,1}  i=3时，先array[i]=array[3]=1在第2行的基础上在最后追加一个元素，即如下图 i=2时，array[]={1,2,1} i=3时，array[]={1,2,1,1} 然后for j 循环 ，第1次j循环 i=2时，array[]={1,2,1} i=3时，array[]={1,2,1,1} 得到 i=2时，array[]={1,2,1} i=3时，array[]={1,2,3,1} 第2次for j循环 i=2时，array[]={1,2,1} i=3时，array[]={1,2,3,1} 得到 i=2时，array[]={1,2,1} i=3时，array[]={1,3,3,1} 然后j循环退出，再array[0]=1，最终第i=3行有4个元素，即array[]={1,3,3,1}  所以for j不是公式，相当于把上一行（i-1行）的结果依次倒推，两两元素相加的结果最为本行（i行）的第 j 个元素qybao大佬，永远滴神！


Question: 请各位大佬帮忙解决一个指针问题，需要输出long long数据每两个字节的值

感谢，看来还是没有摸透 引用 1 楼 自信男孩 的回复:改一下循环条件不就可以了吗？  for (i = n-1; i >= 0; i--) {     printf("%#x\t", *(p+i)); }


Question: scanf输入char*提示段错误linux

struct students { char *name; char *member; char *state; };  如果对指针内存分配不熟悉，还是建议用 char name[10] 这种方式

都是野指针惹的祸，s是野指针，s->name也是野指针。所以结果是未定义的，出现段错误也是可能的。  #include<stdio.h> #include<stdlib.h> #define datesize 64  struct students {     char *name;     char *member;     char *state; };  void appendmessage() {     struct students *s;      s = (struct students *)malloc(sizeof(struct students));     if (!s)         return;      printf("学生姓名：");     //标记1     char *name = (char *)malloc(sizeof(char) * 32);     if (!name)         return;     scanf("%s",name);     //标记1 end     //标记2     s->name = (char *)malloc(sizeof(char) * 32);     if (!s->name)         return;     scanf("%s",(*s).name);     //标记2 end     printf("学生编号：");     s->member = (char *)malloc(sizeof(char) * 32);     if (!s->member)         return;     scanf("%s",(*s).member);     printf("学生状态：");     s->state = (char *)malloc(sizeof(char) * 32);     if (!s->state)         return;     scanf("%s",(*s).state);     printf("----写入文件----");     FILE *fp = fopen("studate.txt","ab");     //...... } 供参考～  上面的改法只是一种，也可以用数组或普通变量～


Question: c语言关于float问题

请参考《C++浮点型变量的存储方式》 希望能够帮到您！

float是-3.4E+38到3.4E+38，没有超。100.0f的f表示这个是double，乘了之后会升级成double，就像你char乘int会升级成int。

float 指数-128——127


Question: c语言小白求助

value是float的，右边的值是double的

waitKey (0)?

是不是那个“请按任意键继续”的黑色窗口啊？要是的话你需要添加头文件“stdlib.h”，然后在return 0； 的前面添加  system("pause");  这样一句就能了，这条语句的意思是 暂停程序，等待输入

没看到enter界面，跟enter界面好像没关系吧。

编译没问题吧，另外，enter界面是什么呢？

不明白enter界面是啥，代码看上云是没错的


Question: sourceinsight 两个文件中定义了同名的结构体变量

可以考虑改一下头文件，把两个同名结构体如果元素完全一样，可以用一个声明，如果结构体成员不一样，建议改一下其中一个结构体名字

有一个概念叫命名空间namespace，就是为了解决这样的问题。 所以你可以把两个结构体放在两个不同的命名空间，引用时加上命名空间来区分即可 比如 namespace A { typedef struct x {     int a; } X; }  namespace B { typedef struct x {     int a;     int b; } X; }  引用时 A::X a; //引用A的结构体X B::X b; //引用B的结构体X


Question: 假定int a=2，b=3；，表达式(b/a*2.0>2.0*a/b)+(++a-b--)的值是？  为什么答案是0而不是1呢？

这种题目不需要深究，写代码千万别这样写，看的人要累死 a++ 、a-- 这种，表达式尽量只包含a一次

引用 3 楼 朕守山河 的回复:要明白一般的编译器实际上是从右向左进行计算的 也就是先计算（++a-b--），计算这部分的时候，++a为3，-b--这个时候也为3，所以为0，算完这一步后，a的值为3，b的值变成2 那么(b/a*2.0>2.0*a/b)变成（2/3*2>2*3/2)为假，所以为0  最后0+0为0 建议测试一下～

这个我考虑的是从左向右计算；因此结果应该是1+0=1  #include <stdio.h>  int main(void) {     int a=2,b=3;      printf("%d\n", (b/a*2.0>2.0*a/b)+(++a-b--));      return 0; } 在linux下测试结果是1.

引用 7 楼 朕守山河 的回复:[quote=引用 5 楼 自信男孩 的回复:][quote=引用 4 楼 朕守山河 的回复:][quote=引用 1 楼 自信男孩 的回复:]分两部分吧，第一个部分是+前。 (b/a*2.0>2.0*a/b)；要看结果是否为真还是假。  通过计算可知：2.0 > 4.0/3很明显为假。即0  +后： (++a-b--)即++a为3. b--先算(b--)即为3. 所以3-3 = 0； 最后是0+0=0 2.0 > 4.0/3很明显为假。即0？？？你这个是怎么算出来的？ 这个问题是因为编译器原因[/quote] 就是true和false的值。 [/quote] 兄弟。。。麻烦你看明白我的意思了再回复哈 2>4/3结果为假？[/quote] 理解错了。那也不是2 > 4/3哦，应该是2.00000 > 4.00000/3；2和4是double类型哦。

引用 5 楼 自信男孩 的回复:[quote=引用 4 楼 朕守山河 的回复:][quote=引用 1 楼 自信男孩 的回复:]分两部分吧，第一个部分是+前。 (b/a*2.0>2.0*a/b)；要看结果是否为真还是假。  通过计算可知：2.0 > 4.0/3很明显为假。即0  +后： (++a-b--)即++a为3. b--先算(b--)即为3. 所以3-3 = 0； 最后是0+0=0 2.0 > 4.0/3很明显为假。即0？？？你这个是怎么算出来的？ 这个问题是因为编译器原因[/quote] 就是true和false的值。 [/quote] 兄弟。。。麻烦你看明白我的意思了再回复哈 2>4/3结果为假？

兄弟 你这个....麻烦看清楚意思了，2>4/3结果是假？

引用 4 楼 朕守山河 的回复:[quote=引用 1 楼 自信男孩 的回复:]分两部分吧，第一个部分是+前。 (b/a*2.0>2.0*a/b)；要看结果是否为真还是假。  通过计算可知：2.0 > 4.0/3很明显为假。即0  +后： (++a-b--)即++a为3. b--先算(b--)即为3. 所以3-3 = 0； 最后是0+0=0 2.0 > 4.0/3很明显为假。即0？？？你这个是怎么算出来的？ 这个问题是因为编译器原因[/quote] 就是true和false的值。

引用 1 楼 自信男孩 的回复:分两部分吧，第一个部分是+前。 (b/a*2.0>2.0*a/b)；要看结果是否为真还是假。  通过计算可知：2.0 > 4.0/3很明显为假。即0  +后： (++a-b--)即++a为3. b--先算(b--)即为3. 所以3-3 = 0； 最后是0+0=0 2.0 > 4.0/3很明显为假。即0？？？你这个是怎么算出来的？ 这个问题是因为编译器原因

这个表达式是典型的“使用变量的同时、又改变这个变量”。这种问题，建议你不要纠结，因为不同的編译器给出的结果是不一样的。 先抛开你的问题，看下面的例子： int a = 1; int b = a + a++; b的结果可能是2，也可能是3。 原因在于，所有的操作符(operator)，C的标准规定了优先级和结合律，但大多数没有规定计算的顺序(the order of evaluation)。 优先级和结合侓只是告诉你哪些操作符与哪些操作数绑定在一起，并且习惯上我们会用括号括起来，所以a + a++相当于 a + (a++)而不是(a+a)++； 但是即使是a + (a++)，编译器可以先考虑计算左边的a，也可以先考虑计算右边的a++，这个顺序是标准没有规定的。  所以，你的表达式(A) + (B)，先处理A的话是一个结果，先处理B的话是另外一个结果。 都对。


Question: 在自定义数组中如何将main函数中的数组和其他值比较？

确实多了单引号。。

所以可以使用对数组名进行位移的方式遍历数组中的所有元素。 请参考《C++中函数的数组形参》 《C++数组地址偏移》 希望能够帮到您！

你自己不是搞定了吗？只不过while('n' != arr[i]) 可能期待的是 while(n != arr[I]) //没有引号，有引号是字符，没有引号才是你传进来的参数。 用arr[i]就可以访问数组的其它元素，所以估计是你写错了'n'，多了引号


Question: 关于C语言的语法 *p++ *= *q++;

a = *p++ * *q++等价于  a = *p  乘以 *q p = p+1; q = q+1;  如果是代码：  int[] A = int[10]; int[] B = int[20]; int *p = A//数组 int *q = B;//数组 int a; a = *p++ * *q++;  相当于  a = A[0]*B[0]; q = &A[1]; p = &B[1];

*p++ *= *q++; 展开应该是*p++ =(*q++) * (*p++);

a = *p++ * *q+++我不信他是对的

引用 5 楼 千梦一生 的回复:a = *p++ * *q+++我不信他是对的 手抖多打了个+

如此阴间的代码，我看着挺难受。

引用 3 楼 自信男孩 的回复:*p++ *= *q++; 这样写，不如写成  p[i] *= q[i];看着舒服。 既然用了i建议用p[i], q[i]; 起初是写成这样的，但我这不是听说 *p++ 比下标访问更快吗， 就改成这样了。。。  发现挺麻烦，因为要保留一个指向头的指针，就得为一个数组准备2个指针，一个用来移动，一个始终指向头部  而且有的写法不易读，比如:  a = *p++ * *q+++ 这是啥，但它是正确的

是可以的，是我的错。没有创建临时指针，把唯一指针移到末尾了


Question: 线性表的顺序存储结构

说到底还是传值和传地址的问题

楼主的代码可以贴全一些。  从数据结构和参数类型可知，Creat函数的第一个参数应该传&lin才可以，当然函数定义里第一个参数应该是Line *L。 否则不能从Creat函数里得到你想要的数据。

报什么错了？Creat和Print函数怎么实现的？

就目前的代码看，应该没啥错误，结构体名也是可以做参数传入的，只是用的比较少而已


Question: 怎么用C语言代码表示10负n次方

整个n是需要有限制的吧，不成超过double或long double的小数范围，最好是能在有效的取值范围

啥意思？ 比如 double a=1e-9 表示10的-9次方


Question: 求大佬帮我看看这道题目的详细思路和代码问题！

很多都可以百度

lower_bound 就是二分法找q的元素的位置（适用于排好序的数组） 比如 a[]={1，2，3} 数组找q=3，l是左位置0，r是右位置2，中心位置是mid=(l+r)/2 = 1，a[1]=2<q=3，所以左位置+1即l=1；继续查找，中心位置mid=(l+r)/2=2，a[2]=2<q=3，所以左位置+1即l=2；此时不满足while循环，退出，所以l=2就是结果，即a[2]=3就是就是找到的结果 这个函数感觉有点缺陷，最后应该还要判断a[l]是否这的和q相等  INT_MAX是整形的最大值，因为要找最小长度，所以初始化最小值为整形最大值。就好像从数组a[]={3,2,1}找最小值，这样初始化min=100（相当于INT_MAX），这样一个for循环就能找到最小，即 int min=100; //100和INT_MAX一个意思，INT_MAX表示初始值就是整形最大的，这里的100是因为我们知道数组里没有大于100的元素 for(int k=0; k<3; k++)      if (a[k] < min) min=a[k]; //如果min不是最大，假设所以元素到大于min，那么就找不到min了，比如所以元素大于100，那最后min就找不到  sums数组是构建一个原数组前缀元素的和的数组，也就是原来数组的前i个元素的和就是sums数组的第i位置的元素。 nums = {1, 2, 3, 4} sums = {0, 1, 3, 6, 10} //看到了吗，sums数组会多出一个元素，所以要 numsSize + 1。nums[0]=1之前是0=sums[0]，nums[1]=2之前是1=sums[1]，nums[2]=3之前是1+2=3=sums[2]，nums[3]=4之前是1+2+3=6=sums[3]，4之后（相当于所有元素的和）是1+2+3+4=10=sums[4] sums最终是排好序的，所以二分法适用   //这个for循环想干嘛？ 这个for循环就是要求出sums的每个元素，上面说了，sums是nums的前缀和的数组，所以要for nums循环来一个一个加nums的前缀元素算出sums  //这个for循环的内容能解释一下吗？ 这个每次用sums的前一个元素加上s的值最为查找对象，然后用二分法来查找 比如 第一次用sums[0]+s作为目标值来进行二分法查找，第二次用sums[1]+s作为目标值来进行二分法查找，依次类推。然后每次二分法找到的结果判断是不是最小，如果是最小，则交换ans的值  思路： 其实就是要搞明白target=s+sums[i-1]的意义，上面说了，sums是nums的前缀的和，那么s+sums[i-1]是不是相当于s+nums[i-1]的前缀的和，nums[i-1]的前缀，是不是就是nums[0]到nums[i-1]的子串，所以相当于s+（nums[0]到nums[i-1]的子串的和）；搞明白这个意义就可以了，二分法只是快速查找而已，没什么特别意义。所以如果用二分法找到target的位置bound，那就说明从nums[i]到nums[bound]的和就是s（因为target-（nums[0]到nums[i-1]子串的和）=s），这样，从每次查找到的bound中选出最小的即可。


Question: C里手动分配内存必须手动回收吗？

要看你是在哪里申请的空间，如果是在栈上申请的，比如alloca就是在栈上分配的动态，那么不需要手动回收。 如果实在堆上申请的空间，那是需要手动释放的，不过整个程序退出时，即使没有手动释放，系统也会帮忙回收的。

1楼标准答案.

必须。否则只有在程序退出的时候，系统才回收全部资源。 C语言没有java及C#之类的智能

不会被自动回收

在堆上分配的内存（也就是用malloc、new这样的语句分配的）不释放会一直存在，栈上分配的函数退出会自动回收。


Question: 数据结构中的链队列的入队操作

s->next= NULL;可以理解为初始化，s是链接到队列的末尾，队列的末尾的next不就是执行NULL吗？ 楼主看一下队列遍历里可以通过判断是否为NULL来确定是否到了末尾。  新的节点进来，就会把上一个s->next的NULL给覆盖了，就是用新的s覆盖上一个s->next

新的结点连接到上一个结点的next域上，这个新结点的next又指向NULL。


Question: 学生成绩管理系统（c语言）

有什么问题呢？还是单纯的代码展示？

楼主的代码写的不全呢，比如： struct Class *banjixinxi(struct Class *head) {      int j;     for(j=1;j<=5;j++)     {         stuHead = chengjishuyu(j);      }     return head; } 这里的head什么也没做，直接返回，所以程序里除了一些编译错误，就是代码还没写完，即使没有这些错误也不能运行。建议楼主写完了再问吧


Question: VS2019开发C语言的问题

请参考《VS2015中使用scanf()不报错的设置方法》 希望能够帮到您！

感谢大佬们！我懂了

其实错误提示已经很明确的给出解决方法了

VS中设置#define _CRT_SECURE_NO_WARNINGS(解决C4996错误) 1.我们在编译老的用C语言的开源项目如lua源包的时候，可能因为一些老的.c文件使用了strcpy,scanf等不安全的函数，而报警告和错误，而导致无法编译通过。 2.此时我们有两种解决方案： a.在指定的源文件的开头定义：#define _CRT_SECURE_NO_WARNINGS  （只会在该文件里起作用） b.在项目属性里设置，这会在整个项目里生效，依次选择：属性->配置属性->C/C++ ->预处理器->预处理器定义->编辑 最下面加上一行：_CRT_SECURE_NO_WARNINGS   （注意不需要#define） 这个其实网上就能搜到答案

看错误信息是楼主的编译器不支持scanf需要用scanf_s（vs里支持的）。  把scanf改成 scanf_s("%d", &x); 试试～

引用 4 楼 千梦一生 的回复:#define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:4996) 如果用#define这一句一定要放在程序的第一行

为啥不看报错信息，用啥instead

去定义 _CRT_SECURE_NO xxx 就可以无视这个警告了。 因为这个函数不安全，已经早就抛弃了


Question: 关于VC里好多头文件不能用的问题，本人新手，请大神们务必回答一下！！！谢谢

图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。  　　C++ Builder是真正的可视化的开发工具。C++ Builder可以用鼠标拖拉控件加上设置属性轻松的“设计”出一个程序的图形用户界面，利用可视的组件/控件像“搭积木”一样，以“所见即所得”的方式搭建应用程序的界面，这也是C++ Builder这个名字中Builder的概念。这样，只需要用C++语言编写业务逻辑代码，类似于DOS下文本界面编程，只要专注于实现业务逻辑功能就可以了，代码非常简洁。数据的输入和表现，都在图形用户界面，非常直观、易用。这就是RAD开发（Rapid Application Development，快速应用程序开发）。  书籍推荐： 《C++Builder 6程序设计教程（第二版）》 （陆卫忠，刘文亮　等编著 /2011-04-01 /科学出版社）（当当网） 《C++Builder 6编程实例精解》（赵明现），PDF，是数字版的，非扫描版的，里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》（台湾 吴逸贤），里面有10几个简单小游戏的实现，可以自己看懂以后再重写，才是自己掌握的。 《C++ Builder 5高级编程实例精解》（刘滨 编著）都是较大的实用的程序。  C++ Builder 6.0几个示例程序项目源代码下载：       C++ Builder第一个程序（模拟聊天室）v1.11 C++ Builder模拟数字双时钟示例（未完成）v0.2.1 C++ Builder纸牌游戏Demo v0.03 C++ Builder不规则图像透明贴图（位图的透明显示）三种方法及简单动画v1.3 C++ Builder写的《ZEC 四则运算练习程序》 海底海星情景v0.9.2 C++ Builder简单电话簿Demo例子v1.11

<dos.h>、<bios.h>、<graphics.h>是用于DOS软件开发的，VC++6已经不支持DOS/win16开发了，如果需要的话，可以使用microsoft c/c++ 7.0或者VC++ 1.x

VC++6.0挺好的，对于缺少的头文件，可以从网上下载以后，再拷贝到VC++6.0的库文件夹下就可以了

引用 10 楼 ooolinux的回复:那些是DOS平台游戏了，非要看看代码运行效果的话，可以用DOSBox运行Turbo C 2.0或Borland C++ 3.1（支持鼠标）来编译，Windows 2000以后无法直接运行。 非常感谢您可以告诉我这些

十分感谢各位积极的回复！

非常感谢！这对我很有用！

要看创建的什么类型的项目

引用 3 楼 smwhotjay的回复: 因为非vc6标准库了。 要自己手动指定安装 我现在贼头疼，解决不掉完成不了后面的任务

引用 3 楼 smwhotjay的回复: 因为非vc6标准库了。 要自己手动指定安装 咳咳，那您可以告诉我怎么安装解决吗？毕竟这么多头文件，我也不知道该安装什么？安装在哪里？

引用 2 楼 qybao的回复:查看一下这些头文件在include路径下吗？如果不在，你要用-I参数指定include路径来编译。 emmmm,我补充一下，主要是我学到系统相关的函数时发现的这些头文件，写一些基本的例题还是没什么问题的，就是目前就发现主要和系统相关的不行

因为非vc6标准库了。 要自己手动指定安装

应该是没有加在相应的库吧，


Question: 求大佬帮忙看看我这段代码错在哪？

if (j=-1 || haystack[i]==needle[j])； 你这行写错了吧？j = -1

int *getNext(char *p, int *next) {     int k=-1, j=0;     next[0] = -1;     while (j<strlen(p))     {         //if (k=-1 || p[k]==p[j])         if (k==-1 || p[k]==p[j])         {             next[++j] = ++k;         }         else         {             k = next[k];         }     }     return next; }  int strStr(char * haystack, char * needle){     if (needle==NULL) return 0;      int x = strlen(needle);     int i=0, j=0;     int *next = (int *)malloc(x*sizeof(int));      getNext(needle, next);      while (i<strlen(haystack) && j<strlen(needle))     {         //if (j=-1 || haystack[i]==needle[j])         if (j==-1 || haystack[i]==needle[j])         {             i++;             j++;         }         else         {             j = next[j];         }     }     if (j==strlen(needle))      return i-j;     else      return -1; } 供参考～  有这两处的问题～

我全部搞懂了，谢谢各位大佬们

int *getNext(char *needle, int *next) {     int k=-1, j=0, n=strlen(needle);     next[0] = -1;     while (j<n)     {         if (k==-1 || needle[k]==needle[j])         {             next[++j] = ++k;         }         else         {             k = next[k];         }     }     return next; }  int strStr(char * haystack, char * needle){     int len1=strlen(haystack); 	int len2=strlen(needle);     if (len2==0) return 0;     int i=0, j=0;     int next[strlen(needle)+1];          //这里为什么要加1？我看其他KMP算法这里并没有加1     getNext(needle, next);     while (i<len1 && j<len2)     {         if (j==-1 || haystack[i]==needle[j])         {             i++;             j++;         }         else         {             j = next[j];         }     }     if (j>=len2)      return i-j;     else      return -1; }  大佬们，我已经写出正确的代码了，但是我不知道上面的next数组后面为什么要加1？

if (needle==NULL) return 0 改成 if (needle==NULL) return -1 并追加 if (strlen(needle)==0) return 0  空字符串不是NULL，是””

错误一： if (needle==NULL) return 0 改成 if (needle==NULL) return -1 并追加 if (strlen(needle)==0) return 0  错误二：  //if (k=-1 || p[k]==p[j])     if (k==-1 || p[k]==p[j])  错误三：  //if (j=-1 || haystack[i]==needle[j])     if (j==-1 || haystack[i]==needle[j])  改完之后还是不行哭了，究竟还错在哪里


Question: .c源文件怎么编译成.sys文件？

我以前用vs2003 ddk  编译过sys驱动。


Question: 关于KMP算法的问题

谢谢user-1大佬，你已经有效地回答了我很多问题了，非常感谢，看来我以后问问题还是要贴出具体代码才能让人更好地回答

为什么next[0]=-1?这只是为了方便判断j回退到哪个位置，因为如果一直不匹配，j最多会回退到next[0]重新开始匹配，为了能判断j回退到next[0]，就要给next[0]赋一个特定值，一般这个特定值采用-1，因为后面的next不可能会出现负数，所以用个负数能方便判断j回退到了next[0]  写成next[1]=0，这个就看程序逻辑怎么控制了，因为用next[0]=-1，i=1，j=-1也能算出next[1]=0  j为什么等于-1？这是为了错开匹配字符串。next数组是用匹配字符串自己和自己错开1位来求的，比如 -abcd //原字符串（没有-字符，-只是为了对齐方便说明比较），i在第一个a位置，即0位置 xabcd //错开位置字符串（没有x字符，x字符只是为了方便说明开头错开一位），j在x位置 错开位置字符串的x位置相对于原字符串来说就是-1（因为a是0位置，a的左边x就是-1）  if j==-1 是为了判断匹配字符串是不是最开始匹配。p[i]==p[j]表示原字符串和错位位置字符串的该位置的字符相同。if的意思就是满足上述条件则算出next，并继续比较下一个字符 比如 aabb //原字符串，i在第一个a位置，即0位置 xaabb //错开位置字符串，j在x，即-1位置 第一轮循环，j==-1（最开始比较），所以i++，j++，算得next[1]=0；然后下一轮循环，原字符串p[i]即p[1]=a，错开位置字符串p[j]即p[0]=a，所以满足p[i]==p[j]，则继续比较下一个字符i++，j++，同时算的next[2]=1（即找到1个字符匹配，也就是匹配长度为1）；然后继续下一轮循环，原字符串p[i]即p[2]=b，错开位置字符串p[j]即p[1]=a，p[i]!=p[j]，进入else，重新回退错开字符串的位置j=next[j]=next[1]=0，所以变成 aabb //原字符串，此时i在第一个b位置 -xaabb //错开位置字符串j在a，即0位置 然后继续下一轮比较，原字符串p[i]即p[2]=b，错开位置字符串p[j]即p[0]=a，p[i]!=p[j]，进入else，j继续回退，即j=next[j]=next[0]=-1（第一个问题next[0]=1的意义就在这里，j回退到了最开始位置），所以变成 aabb //原字符串，此时i在第一个b位置 --xaabb //错开位置字符串j在x，即-1位置 然后继续下一轮循环，因为j==-1，所以直接比较下一个字符，所以i++，j++，算得next[3]=0 依次类推，最终算出全部的next  为什么next[j]刚好等于j？因为满足if，说明有j个字符匹配，所以匹配长度就是j（j==-1说明刚开始，有0个字符匹配）  为什么回溯到next[j]？因为next的意义就是保存了上次匹配的长度，所以如果发现不匹配，错开位置字符串就在跳过上一次匹配长度的基础上重新开始匹配，具体参见上面的分析。  if和else又看不懂了？其实kmp和getnext的if和else意思差不多，kmp是在t里找p字串，所以就是比较t和p的匹配度；而getnext是p和错开位置的p的匹配度比较，目的为了算出next；所以kmp和getnext的if和else逻辑一样的，都是找匹配度，只是前者是长串跟子串比，后者是自己跟错开位置的自己比  这个if麻烦也解释一下？这个if说明如果j能走到子串p的最后，则t就包含p，所以p在t的索引就是i-j；如果这个if不满足，说明p不能匹配完，所以t不包含p，则返回-1


Question: 关于C语言数组和指针有个问题

引用 10 楼 火花20180731的回复:char* str = "abcdefg";  "abcdefg"是字面值常量，存储在常量区某一块，这里是把"abcdefg"在常量区的地址存到str指针中 char a[10]; 声明一个容量为10的数组，a是个局部变量，会在栈区中为a分配一块10字节的内存 copy通过str中存储的地址进入常量区内存把“abcdefg”拷贝到数组的内存中 char* a; 声明一个指针，指针所指内存用char格式读取。指针a和str都有自己的内存，都用来备份地址，不能用来存储字符串。 a没有初始化，所以a本身的内存存的是个垃圾值，也就是没有明确指向的指针是野指针，读写野指针的“目标内存”会引发段错误！造成程序崩溃。 谢谢啦！辛苦了，明白了

引用 7 楼 千梦一生的回复:字典不是有目录吗，查字典找某个字的具体读音、释义的时候，先得找到目录那一条【那一行】，根据后边的书页，翻过去再能看对吧。 那一行就如同指针。你建立了一个那样的条目，但后面的书页【对应指针指向的地址】是未知的，可能是任何地方。意图通过该随机的地址去访问数据。这样的行为自然不被许可。 谢谢哥，明白了

引用 11 楼 skzeng@ros的回复:觉得有帮助，又不结贴，你几个意思 这个我不知道手机版的在哪里结贴

觉得有帮助，又不结贴，你几个意思

你的*a是一个野指针，它没有指向一块具体的内存，你对它进行copy操作就是对他指向的内存操作，但是它的指向未知，有可能是一块不允许访问的内存，就会报段错误，可以使用malloc：char *a = malloc(16);然后就可以了。 你定义一个数组a[]的话系统会自动在栈里面给它分配一块内存，是可以进行访问的。

char *a;是野指针，即指向的位置是随机的，a指向的内存区域不一定是可以写的，因此如果指向不可写，那么copy函数就是写，就会出现异常，不如段错误。  用数组，那么定义的空间是在栈上，栈上的空间是可以读写的。

很开心能帮到你，望尽快结贴～

懂了。谢谢哥。我的那个原来是没有给指针分配空间

可以用malloc给char *a分配一块内存，这样就可以使用了

正确答案：如图是用数组可以输出的，而用指针也是可以输出的。不过题主的代码有问题。 问题所在：数组char a[10],默认定义为具有10个元素的一维数组。而指针的使用则必须指向一块内存地址，因此需要有定义，你可以自己分配一块新的地址，也可以指向已有量。因为变量就是内存空间里的值，而内存空间的名字就是地址。指针则指向地址。望采纳~

不能是我那样 char *a吗

用指针你要先初始化指针，让它指向一块有效的内存 比如 char *a = (char*)malloc(sizeof(char)*32);//a指向申请的内存 copy(a, str); free(a); //如果是自己申请内存，用完之后要自己释放内存


Question: 空洞文件的overflow问题。

4*1024*1024*1024 这是4G的空间，建议减少到4*1024试试，应该就不会有溢出的提示了。

Vbox是实模式吧，不能访问那么多内存。


Question: 《C和指针》，点运算符描述的矛盾之处

点操作符的左操作数可以是左值也可以是右值 struct Foo {     int foo; }; Foo bar() {     //...     return Foo(); } bar().foo; //rvalue


Question: 请问大家在Leetcode上为什么会显示 heap-buffer-overflow，实在找不出问题了

第一个break如果在第一次nums[0]不满足，就跳出循环了，还能继续后面的？

int *res=malloc(sizeof(int)*2 ); //2个大小够么？ if(!ina(i,res,m)&&!ina(j,res,m)) //这之前res 缓冲区都没有赋值/初始化 是否调用的参数有误？

同问，在做3sums时出现同样的问题

这个错误一般是对内存越界 比如你malloc了4字节的空间 却给赋值超过4字节的东西  就会报这个错  你现在malloc了8个字节  你下面res[m]=j； m是否超过了2，是的话  就报这个错

1. 两数之和

不看意图的话,肯定是无限递归了. base没有考虑清楚导致的.

题目编号可以说下. 只看代码不懂意图.


Question: 求解一个小问题

引用 2 楼 自信男孩的回复:printf("最后的输出结果是%d,但a的值是%d",(a=2*8,a/4)); 这句代码里有两个%d，那么后面有几个参数对应呢？一个吧。那么另一个是不是一个随机值呢？ 谢谢大佬，我明白了

引用 1 楼 user-2的回复:4198859应该是个随机值,因为printf("最后的输出结果是%d,但a的值是%d",(a=2*8,a/4));这是一个逗号表达式,只能算一个值,第二个%d没有值传给它!  逗号表达式:运算顺序从左到右,整个表达式的值为最后一个表达式的结果. 比如这里:(a=2*8,a/4)的计算过程: a=2*8  计算完后a =16; 然后计算a/4 计算结果为4; 所以整个表达式的结果是4; 所以printf中的第一个%d打印4. 第二个%d压根就没有传值! 谢谢大佬，我明白了


Question: k为什么是15？

引用 4 楼 楚歌的楚啊 的回复:k = 10*10>15?10:15 乘号优先级比较高吧 错了 后面是15：10

k = 10*10>15?10:15 乘号优先级比较高吧

引用 1 楼 真相重于对错 的回复:宏是直接的文本替换 展开后就是 k=10*(i)<(j)?(i):(j); 已经给你展开了，所以应该很清楚知道结果了，这个k就是j赋值的。 因为10 * (i)  < (j)这里*的优先级大于 <因此先执行10 * (i)然后执行 < (j);很明显判断为假，j赋值给k。

#define MIN(i,j) ((i)<(j)?(i):(j))

宏是直接的文本替换 展开后就是 k=10*(i)<(j)?(i):(j);

谢谢，

引用 2 楼 mengjfu的回复:#define MIN(i,j) ((i)<(j)?(i):(j)) 非常感谢，涨知识了 谢谢

引用 1 楼 真相重于对错的回复:宏是直接的文本替换 展开后就是 k=10*(i)<(j)?(i):(j); 谢谢，


Question: 求大神帮忙

挺好的

vs没有问题，默认的转换估计不对。

代码看上去是没问题的，什么错误截个图看看

代码没错 ，应该把错误信息发出来 ， 估计是编译器方面的错误

代码没问题，也不用强制类型转换，因为5*(F-32)/9;本身就是整型数据的四则运算。  楼主要说一下显示成什么格式了？认为是错误的。  printf("fahr=150,celsius=%d\n",C); 可以加一个换行符。


Question: 如何用C语言实现自定义弹窗与选项

windows 平台： 使用MFC / Qt等，很容易实现。 C#的话应该也比较容易，直接创建对话框项目就行，类似MFC。 或者直接调用Windows API MessageBox相关接口，也可以。 更复杂 更自定义的，可以往显存写数据的方式做窗口。  网页： 这不是C语言了。当然也可以弹窗，alert、confirm  其他比如嵌入式，比如海思： 用Qt跨平台。 或者用C语言 从在FrameBuffer上画点线面等基础函数开始做起一步步搭窗口。

用c可以实现，但要调用windows api比较麻烦

使用C语言绘制UI窗口比较麻烦，建议可以使用C++ 的 MFC, 创建弹框 so easy.

c 当然可以，只是麻烦。 不同的平台有不同的方式。 windows 平台建议了解一下win32，gui编程。

单独的C语言恐怕不行，建议使用C++ MFC库～


Question: LeetCode 802.找到最终的安全状态。内存越界？我看了半天没问题啊...

引用 1 楼 遇见女神 的回复:a[*(returnSize)++]=i ; 这行代码可能发生数组越界 为什么呢，我重新写了个变量从0开始就过了，但我前面已经*returnSize=0;了呀，为什么也会越界。

a[*(returnSize)++]=i ; 这行代码可能发生数组越界


Question: 新手求助，问了几个身边的人都得不到满意的解释

int *p = 0;等价p指向0地址位置。p += 6;等价p 偏移了6 * sizeof(int*)。再看一下sizeof(int*)是多少就知道输出p是多少了。

自己想明白了……


Question: 关于sscanf使用的一些疑惑

引用 4 楼 不闻窗外事 的回复:那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);   需要，否则得到的数据就不对，也就是输入 5=abc 或者  5 = abc 可以参考以下关于空白符的描述部分 http://c.biancheng.net/view/415.html https://blog.csdn.net/21aspnet/article/details/174326  关于char buf[] = "123 = abc"; 包含空格时输入不对的问题，原因很简单，对于输入数据来说，扫描器是以空白符来分割信息的，也就是遇到空白符时读入一个数据进来，所以"123 = abc"被当作3个数据读入（”123“， ”=“， ”abc“），而sscanf每次只会读入一个数据，即只读入“123”，然后用“123”去匹配格式，结果只有第一个数据符合（“123”后面的数据算空字符串，即"%[^= \t]=%s"前半部符合，后半部为空） 你可以查看sscanf读入成功的数据就知道了 char buf[] = "123 = abc"; char key[256]; char value[256]; int n = sscanf(buf, "%[^= \t]=%s", key, value); //读入了几个数据？ printf("key=[%s] value[%s]\n", key, value); printf("%d\n", n); //确认读入几个数据  至于格式不匹配为啥还会读入数据?输入格式没有规定完全匹配才会读入数据，而是匹配一个读入一个，如果匹配出错则后面就不会继续读入 比如 int a=0,b=0; char c='?'; scanf("%d%d%c", &a,&b,&c); //程序运行后输入：1 2a会车，看看什么结果，再运行一次输入：1 ab回车，看看什么结果 printf("%d,%d,%c\n", a, b, c);

引用 3 楼 自信男孩 的回复:对于多个格式的文件输入scanf,是用空格来区分开来的。比如  scanf("%d%s", &num, str); 输入两个类型数据%d和%s。只要中间加上至少一个空格，就可以分开两个输入。 那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);

引用 1 楼 自信男孩 的回复:scanf/printf sscanf/fprintf snprintf这些都是格式化的输入输出，因此需要严格按照格式来～ 大哥，我问得就是为什么sscanf在匹配是会忽略空格，严格按照格式，那岂不是就不能忽略了？？？

引用 14 楼 不闻窗外事 的回复:[quote=引用 13 楼 qybao 的回复:] 你的意思就是说scanf这种它的匹配模式中，如果有空格，可以匹配输入的多个空格，也可以直接略过空格，匹配下一部分？？？ 理论上是这样的，除非还有其他特殊的输入格式 相当于"%d %d"格式可以匹配 "数字空格*数字" 这样的输入（空格*表示中间有任意个空格）

引用 13 楼 qybao 的回复:[quote=引用 11 楼 不闻窗外事 的回复: 大哥，你说的这些我都知道，我想知道的不是略去一个还是多个空格，也不是你举得两个例子，你能看看你举得两个例子跟我举得例子的区别吗？？？你的第二个例子如果“1=abc”没有空格，也可以，你不信试试。你说过滤一个或者多个空格，但是“1=abc”这种一个空格都没有啊，为什么也可以得到正确的结果，你说的是多个空格的情况，我问得是“1=abc”没有空格的情况。关键按你说的没有空格是不行的，但是实际上是可以的，这才是问题所在  你没理解我说的。“1=abc”这种一个空格都没有也可以，是因为格式化字符串带空格就会略过输入数据的空格继续读入下一个非空格开始的数据，所以你的输入数据没空格也可以的呀，就是没有略过任何空格，直接读取到下一个非空格数据而已。[/quote] 你的意思就是说scanf这种它的匹配模式中，如果有空格，可以匹配输入的多个空格，也可以直接略过空格，匹配下一部分？？？

[quote=引用 11 楼 不闻窗外事 的回复: 大哥，你说的这些我都知道，我想知道的不是略去一个还是多个空格，也不是你举得两个例子，你能看看你举得两个例子跟我举得例子的区别吗？？？你的第二个例子如果“1=abc”没有空格，也可以，你不信试试。你说过滤一个或者多个空格，但是“1=abc”这种一个空格都没有啊，为什么也可以得到正确的结果，你说的是多个空格的情况，我问得是“1=abc”没有空格的情况。关键按你说的没有空格是不行的，但是实际上是可以的，这才是问题所在[/quote]  你没理解我说的。“1=abc”这种一个空格都没有也可以，是因为格式化字符串带空格就会略过输入数据的空格继续读入下一个非空格开始的数据，所以你的输入数据没空格也可以的呀，就是没有略过任何空格，直接读取到下一个非空格数据而已。

引用 10 楼 qybao 的回复:[quote=引用 7 楼 不闻窗外事 的回复:] scanf("%d = %s", &num, str);就拿这个来说吧，为什么我输入“123 = hello”可以，输入“123=hello”也是一样的，为什么明明是"%d = %s"，却可以忽略空格，不输入空格。最后的结果都是num=123，str=hello，返回值都是2  我给你发的那两个链接你点进去看了吗？里面提到的是格式符字符串中带空格的情况。至于buf带空格的问题，只是告诉你原因所在，不是让你把重点转到buf带空格。所以你可以好看看链接对格式化字符串中带空格的处理的描述。  以下摘自链接中的说明 （B）         空白字符 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符，空白符可以是space,tab,newline等等，直到第一个非空白符出现为止。  所以，如果格式化字符串如果没有空格，那么输入的数据也不能带空格；如果格式化字符串带空格，那么输入数据可以在两个匹配格式之间加任意空格（因为空格回被略去，直接匹配下一个非空格字符开始的数据）  比如 scanf("%d=%s", &num, str); 输入"1 = abc"会出错，因为格式化字符串没有空格，所以输入数据带空格就和格式化字符串不匹配 scanf("%d = %s", &num, str); 输入“1     =          abc”也能正确读入数据，因为格式化字符串带空格，所以输入数据的空格被略过，读入正确  [/quote] 我把例子写到这里， int main(int argc, char *argv[]) { 	int num; 	char str[128]; 	int i = scanf("%d = %s", &num, str); 	printf("i = %d num=%d str=[%s]\n", i, num, str);     return 0; }  结果： 123=abc i = 2 num=123 str=[abc]

引用 10 楼 qybao 的回复:[quote=引用 7 楼 不闻窗外事 的回复:] scanf("%d = %s", &num, str);就拿这个来说吧，为什么我输入“123 = hello”可以，输入“123=hello”也是一样的，为什么明明是"%d = %s"，却可以忽略空格，不输入空格。最后的结果都是num=123，str=hello，返回值都是2  我给你发的那两个链接你点进去看了吗？里面提到的是格式符字符串中带空格的情况。至于buf带空格的问题，只是告诉你原因所在，不是让你把重点转到buf带空格。所以你可以好看看链接对格式化字符串中带空格的处理的描述。  以下摘自链接中的说明 （B）         空白字符 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符，空白符可以是space,tab,newline等等，直到第一个非空白符出现为止。  所以，如果格式化字符串如果没有空格，那么输入的数据也不能带空格；如果格式化字符串带空格，那么输入数据可以在两个匹配格式之间加任意空格（因为空格回被略去，直接匹配下一个非空格字符开始的数据）  比如 scanf("%d=%s", &num, str); 输入"1 = abc"会出错，因为格式化字符串没有空格，所以输入数据带空格就和格式化字符串不匹配 scanf("%d = %s", &num, str); 输入“1     =          abc”也能正确读入数据，因为格式化字符串带空格，所以输入数据的空格被略过，读入正确  [/quote] 大哥，你说的这些我都知道，我想知道的不是略去一个还是多个空格，也不是你举得两个例子，你能看看你举得两个例子跟我举得例子的区别吗？？？你的第二个例子如果“1=abc”没有空格，也可以，你不信试试。你说过滤一个或者多个空格，但是“1=abc”这种一个空格都没有啊，为什么也可以得到正确的结果，你说的是多个空格的情况，我问得是“1=abc”没有空格的情况。关键按你说的没有空格是不行的，但是实际上是可以的，这才是问题所在

引用 7 楼 不闻窗外事 的回复:scanf("%d = %s", &num, str);就拿这个来说吧，为什么我输入“123 = hello”可以，输入“123=hello”也是一样的，为什么明明是"%d = %s"，却可以忽略空格，不输入空格。最后的结果都是num=123，str=hello，返回值都是2  我给你发的那两个链接你点进去看了吗？里面提到的是格式符字符串中带空格的情况。至于buf带空格的问题，只是告诉你原因所在，不是让你把重点转到buf带空格。所以你可以好看看链接对格式化字符串中带空格的处理的描述。  以下摘自链接中的说明 （B）         空白字符 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符，空白符可以是space,tab,newline等等，直到第一个非空白符出现为止。  所以，如果格式化字符串如果没有空格，那么输入的数据也不能带空格；如果格式化字符串带空格，那么输入数据可以在两个匹配格式之间加任意空格（因为空格回被略去，直接匹配下一个非空格字符开始的数据）  比如 scanf("%d=%s", &num, str); 输入"1 = abc"会出错，因为格式化字符串没有空格，所以输入数据带空格就和格式化字符串不匹配 scanf("%d = %s", &num, str); 输入“1     =          abc”也能正确读入数据，因为格式化字符串带空格，所以输入数据的空格被略过，读入正确

引用 8 楼 自信男孩 的回复:[quote=引用 4 楼 不闻窗外事 的回复:][quote=引用 3 楼 自信男孩 的回复:]对于多个格式的文件输入scanf,是用空格来区分开来的。比如  scanf("%d%s", &num, str); 输入两个类型数据%d和%s。只要中间加上至少一个空格，就可以分开两个输入。 那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);[/quote] 需要的。  空格是区分两个输入的或者多个输入[/quote] scanf("%d = %s", &num, str);就拿这个来说吧，为什么我输入“123 = hello”可以，输入“123=hello”也是一样的，为什么明明是"%d = %s"，却可以忽略空格，不输入空格。最后的结果都是num=123，str=hello，返回值都是2  “123=hello”并没有空格啊，一样匹配“%d = %s”

引用 4 楼 不闻窗外事 的回复:[quote=引用 3 楼 自信男孩 的回复:]对于多个格式的文件输入scanf,是用空格来区分开来的。比如  scanf("%d%s", &num, str); 输入两个类型数据%d和%s。只要中间加上至少一个空格，就可以分开两个输入。 那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);[/quote] 需要的。  空格是区分两个输入的或者多个输入

引用 5 楼 qybao 的回复:[quote=引用 4 楼 不闻窗外事 的回复:] 那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);   需要，否则得到的数据就不对，也就是输入 5=abc 或者  5 = abc 可以参考以下关于空白符的描述部分 http://c.biancheng.net/view/415.html https://blog.csdn.net/21aspnet/article/details/174326  关于char buf[] = "123 = abc"; 包含空格时输入不对的问题，原因很简单，对于输入数据来说，扫描器是以空白符来分割信息的，也就是遇到空白符时读入一个数据进来，所以"123 = abc"被当作3个数据读入（”123“， ”=“， ”abc“），而sscanf每次只会读入一个数据，即只读入“123”，然后用“123”去匹配格式，结果只有第一个数据符合（“123”后面的数据算空字符串，即"%[^= \t]=%s"前半部符合，后半部为空） 你可以查看sscanf读入成功的数据就知道了 char buf[] = "123 = abc"; char key[256]; char value[256]; int n = sscanf(buf, "%[^= \t]=%s", key, value); //读入了几个数据？ printf("key=[%s] value[%s]\n", key, value); printf("%d\n", n); //确认读入几个数据  至于格式不匹配为啥还会读入数据?输入格式没有规定完全匹配才会读入数据，而是匹配一个读入一个，如果匹配出错则后面就不会继续读入 比如 int a=0,b=0; char c='?'; scanf("%d%d%c", &a,&b,&c); //程序运行后输入：1 2a会车，看看什么结果，再运行一次输入：1 ab回车，看看什么结果 printf("%d,%d,%c\n", a, b, c);    [/quote] scanf("%d = %s", &num, str);就拿这个来说吧，为什么我输入“123 = hello”可以，输入“123=hello”也是一样的，为什么明明是"%d = %s"，却可以忽略空格，不输入空格。最后的结果都是num=123，str=hello，返回值都是2

引用 5 楼 qybao 的回复:[quote=引用 4 楼 不闻窗外事 的回复:] 那如果是这种呢？？空格需要匹配吗？？？ scanf("%d = %s", &num, str);   需要，否则得到的数据就不对，也就是输入 5=abc 或者  5 = abc 可以参考以下关于空白符的描述部分 http://c.biancheng.net/view/415.html https://blog.csdn.net/21aspnet/article/details/174326  关于char buf[] = "123 = abc"; 包含空格时输入不对的问题，原因很简单，对于输入数据来说，扫描器是以空白符来分割信息的，也就是遇到空白符时读入一个数据进来，所以"123 = abc"被当作3个数据读入（”123“， ”=“， ”abc“），而sscanf每次只会读入一个数据，即只读入“123”，然后用“123”去匹配格式，结果只有第一个数据符合（“123”后面的数据算空字符串，即"%[^= \t]=%s"前半部符合，后半部为空） 你可以查看sscanf读入成功的数据就知道了 char buf[] = "123 = abc"; char key[256]; char value[256]; int n = sscanf(buf, "%[^= \t]=%s", key, value); //读入了几个数据？ printf("key=[%s] value[%s]\n", key, value); printf("%d\n", n); //确认读入几个数据  至于格式不匹配为啥还会读入数据?输入格式没有规定完全匹配才会读入数据，而是匹配一个读入一个，如果匹配出错则后面就不会继续读入 比如 int a=0,b=0; char c='?'; scanf("%d%d%c", &a,&b,&c); //程序运行后输入：1 2a会车，看看什么结果，再运行一次输入：1 ab回车，看看什么结果 printf("%d,%d,%c\n", a, b, c);  [/quote]  谢谢回复，但是我在意的空格不是输入时的空格，而是sscanf中的空格，我的意思是sscanf(buf, "%[^= \t] = %s", key, value); 中引号内部的空格，而不是buf中的空格，为什么引号内部的空格在buf中没有被匹配，仍然会继续匹配，例如char buf[] = "123=abc";没有空格，但是"%[^= \t]"匹配完123之后，在sscanf的引号内部应该匹配空格了，但是buf中下一个字符是等号，在这种情况下，sscanf引号中等号前的那个空格被忽略了，继续用引号中的等号匹配buf中的等号。


Question: C语言

引用 5 楼 月凉西厢的回复:一般认为是从常量区拷贝过去的。具体的话需要看到反汇编代码 也就是说可能是从常量区copy过去的，可能是直接嵌入到指令中的，具体那种不好说

一般认为是从常量区拷贝过去的。具体的话需要看到反汇编代码

这个不一定，它和编译是否优化，数据量的大小有关。

首先代码在编译时，编译器看到这个"abcd"字符串后，就给你把他放到一个固定的地方【你程序中所有出现的这种直接"字符串abc..."都是如此】。这个地方叫静态常量区。 此时，程序中，那个exe【或者dll...】中。存在一个"abcd" ---------------------------------- 接着程序执行时，cpu依据这条指令的意思，在栈上开辟一段char[]数组空间。开辟的长度依据面常量区的"abcd\0"为准。然后从常量区将字符串复制过来 此时，程序中，这个进程上。存在一个"abcd"【静态常量区】，这个线程栈上，有一段空间对应该数组b。其内容为"abcd\0"【复制而来的】

编译个exe.用od载入。查看字符串。我觉得在text段里。

个人认为是copy到b数组中。  "abcd"不是一个字符，如果是一个字符，可以考虑是直接存储到b数组中。


Question: 各位大佬们能给我讲一讲KMP算法吗？

该算法重点就在于理解PMT和next 不要想那么复杂，简单地理解next为该位置的前一个位置的匹配长度即可

上边说的不清楚，应该是最后一个c的。。。

next 数组是这样的，模式串，每一位的Next的值是 最大的从左往右与从右向左相等的长度 比如  abcxxxxxabc那么c的next值就是3

我主要是next数组不懂，代码完全看不懂

这个算法的思路主要在于在已匹配的字符串当中确认最长可匹配后缀子串和最长可匹配前缀子串， 然后下一轮循环的时候直接跳到最长可匹配后缀子串的位子  从而实现减少循环  我觉得这个算法就是在BF算法基础上面做了这个操作 去掉了一些不必要的循环对比 具体的解释真的没法说清  你可以看看下面的链接 https://baijiahao.baidu.com/s?id=1659735837100760934&wfr=spider&for=pc https://baijiahao.baidu.com/s?id=1659735837100760934&wfr=spider&for=pc

这个真不是一两句能讲明白,你先把你的具体不明白的地方说出来...


Question: 谁能帮我看看哪里错了

引用 1 楼 user-3的回复:你的期待结果是什么？ 单纯从语法上来说 case 0: //后面是冒号 另外，如果希望每个case做不同的处理，应该在case 语句结束后加break，即 case 0: break; case 1: s += 1; break; //如果没有break，那么case 1执行后会继续执行case 2，当然如果你的本意就是case 1和case 2都执行，那么另当别论 case 2: s += 2; break; case 3: s += 3; break; case 4: s += 4; break; 谢谢你们，我太粗心了

引用 2 楼 chxchxkkk的回复:如果把case 后面的 分号写对成 冒号，程序可以正常运行。 谢谢你们，我太粗心了

没有break，那么从case 0会执行到case 4.

如果把case 后面的 分号写对成 冒号，程序可以正常运行。


Question: 求大佬指导，用下列公式求cos(x)的近似值，精确到最后一项的绝对值小于e

你好好检查sum阶乘对不对，每次计算阶乘重新初始化了吗？ 要么你就把for里的 j=1 去掉，放到外面初始化j；要么就每次for j循环前初始化sum 另外，while(k>=e)也有问题，假设 k=s/sum小于e，后面的totle=totle+k*flag还是执行了，也就是会多计算一项。

double funcos( double e, double x ) {     double k=1.0 ;     double s ;     double total = 1 ;     int j ;     double i = 2 ;     int falg = -1 ;     int sum = 1 ;             while( k >= e )     {         s = pow ( x , i) ;                  for ( j = 1 ; j <= i ; j++  )         {               sum *= j ;                      }         k = s / sum ;         total = total + k*falg  ;          falg = -falg;          i += 2 ;     }     return total ; }  改了还是不对

引用 楼主 深山旧梦还惊觉 的回复:题目如下：   代码如下  #include <stdio.h> #include <math.h>  double funcos( double e, double x );  int main() {         double e, x;      scanf("%lf %lf", &e, &x);     printf("cos(%.2f) = %.6f\n", x, funcos(e, x));      return 0; } double funcos( double e, double x ) {     double t = 1.0 ;     double l = 1.0 ;     int i  ;     int j = 2 ;     double total ;     double sum ;     while (  (t / l ) > e  )                       //当精度不满足时候循环     {                    t = pow (x , j) ;                                          for( i = 1 ; i <= j ; i++ )                           {                     l *= i ;                         //求分子             }                           total += -(t / l) ;                         //单项                           sum += total ;                         j += 2 ;                                  //递增指数 +2     }     return sum + 1 ; }   我这觉得思路没问题，但是代码不对，自己看不出来哪里出错了。  你这单项注释的一行啥意义？ 你看你的问题，正负项都没控制好，答案怎么可能对？ 正负项用 *= -1（也就是乘-1）来控制，所以改成 total = -1.0(初始值)，sum = 0 然后 for 循环里的 total += -(t / l) ; sum += total ; 改成 sum += total * (t / l) ; total *= -1; //total当作正负符号的flag，每运算一次改变一次符号

你的自定义函数里，total和sum没有初始化吧。  另外，double的输出应该用%lf，楼主的应该是 %.2lf


Question: PTA上的最大子列和问题，涉及动态数组的赋值，写了几次提交都显示运行时错误，但是在vs上能过，请问是哪里出了问题呢

还有那个scanf_s 改成scanf  ,麻烦你先把语法写对了。 再看分配空间，new int数组时，k是0，没有分配空间，怎么给a[]赋值呢？应该把 scanf_s("%d", &K);写到new之前

MaxSubseqSum的参数也不能用传数组啊

引用 1 楼 逸卍辰的回复:这是哪个题啊 数据结构的第一题啊，7-1

啊忘了说！我开始是用c＋＋写的，然后PTA一直过不去就想改成c语言看看，new和delete什么的是忘改了 总之就还是数组的问题

也没有delete ,别和c++用混了

c语言没有new关键字吧

这是哪个题啊

我会了！蟹蟹你哦！

scanf也不让用啊，怎么就“麻烦我先把语法写对了”

#include <stdio.h> #include <stdlib.h>  int MaxSubseqSum(int *A, int N) {     int ThisSum = 0, MaxSum = 0;     for (int i = 0; i < N; i++) {         ThisSum += A[i];         if (ThisSum > MaxSum)             MaxSum = ThisSum;         else if (ThisSum < 0)             ThisSum = 0;     }     return MaxSum; }  int main() {     int K = 0, t; int temp = 0;     scanf("%d", &K);     int* a = malloc(sizeof(int)*K);          for (int i = 0; i < K; i++) {         scanf("%d", &temp);         a[i] = temp;     }     t = MaxSubseqSum(a, K);     printf("%d", t);     free(a);     return 0; }


Question: c语言 error: expected '; '. '.' or ')'before 'char'    怎么解决？？？

int show_report(Product p[], int num_of_product char *pr_ordinal ); 第二个参数和第三个直接是不是少一个逗号呢？  switch的参数只能是int，整形数，你用字符串是不支持的。 建议楼主重新了解一下switch case的用法～

加","了case 也改成case 1了还是有这个报错

1.检查是否用了中文标点符号 2.	case "已完成": case 不支持这种写法吧

int num_of_product 和 char *pr_ordinal 之间加个逗号，也就是参数之间用逗号分开。

你这.....switch case用的真牛啊。。。不知道该怎么说你了

product 大小写也关注一下


Question: C#源代码如何用VS软件生成exe文件

那就是点F5生成exe文件的方法没错咯？我还以为这种方法不对，那生成的exe文件在哪能找到，你知道吗

这个是已经生成exe了吧，看着像是程序运行报的错。


Question: 发生了什么？

#include <stdio.h> #include <stdlib.h> #include <string.h>  struct film {     char title[45];     int rating;     struct file* next; };  char* s_gets(char* st, int n);  int main(void) {     struct film* head = NULL;     struct film* prev, * current;     char input[45];      puts("enter first name");     while (s_gets(input, 45) && input[0] != '\0') {         current = (struct  film*)malloc(sizeof(struct film));         //prev= (struct  film*)malloc(sizeof(struct film));         if (head == NULL)             head = current;         else             prev->next = current;         current->next = NULL;         strcpy(current->title,input);         puts("enter first rating");         scanf("%d", ¤t->rating);         while (getchar() != '\n')             continue;         puts("enter next");         prev = current;     }     if (head == NULL)         puts("there is no moive");     else         puts("there is a movie list");     current = head;     while (current != NULL) {         printf("%s   ,%d\n", current->title, current->rating);         current = current->next;     }     current = head;     while (current != NULL) {         free(current);         current = current->next;     }     return 0; }   char* s_gets(char* st, int n) {     char* ret_val;     char* find;      int i = 0;      ret_val = fgets( st, n, stdin);//下文所出现的都是已经输入完成的内容     if (ret_val) {//fgets没有读取到文件结尾或者读取错误         find = strchr(st, '\n');         if (find)         {             *find = '\0';         }         else             while (getchar() != '\n')                 continue;     }     return ret_val; }

而且pre指针也不用分配空间,应该注释掉 //prev= (struct  film*)malloc(sizeof(struct film));

内存泄露: while (current != NULL) {         free(current);         current = current->next;     }


Question: 不同的地方放入 str[1000] = '\0'; 这条代码，返回的值就发生变化了

引用 8 楼 九月qkq92 的回复:引用 5 楼 qq_1457346882 的回复:奥，你加这个是想把数组清空还是？我看你这是一次ｗｈｉｌｅ调用一次，如果清空的话用memset就好了    是的我是想清空。不过我觉得直接赋值空比较方便。 str[0] = '\0'也可以吧。 那不是，现在通用的就是用memset，这个函数很方便啊，都是一句语句，怎么直接赋值就比较方便，而且这是代码规范，虽说你这里把第一个赋值为\０可以，那是因为你这里是数组一样的判断，而且代码简短，工程文件里很多都是直接取一部分，那这一部分你这么赋值取出来不就是错的了。 我的理解是此时str的值应该为efcde，但是实际的值是ef　　　这个说的也是有问题的　不止是这一个函数，大多数获取函数都会在结束加\0 你这里ｓｔｒ的值不是ｅｆｃｄｅ而是ｅｆ'\0'de，你的输出判断都是判断是不是\0，是这个就截止，这也是同样的道理为什么直接赋值给第一个地址不好

引用 9 楼 qq_1457346882 的回复:引用 8 楼 九月qkq92 的回复:[quote=引用 5 楼 qq_1457346882 的回复:]奥，你加这个是想把数组清空还是？我看你这是一次ｗｈｉｌｅ调用一次，如果清空的话用memset就好了    是的我是想清空。不过我觉得直接赋值空比较方便。 str[0] = '\0'也可以吧。 那不是，现在通用的就是用memset，这个函数很方便啊，都是一句语句，怎么直接赋值就比较方便，而且这是代码规范，虽说你这里把第一个赋值为\０可以，那是因为你这里是数组一样的判断，而且代码简短，工程文件里很多都是直接取一部分，那这一部分你这么赋值取出来不就是错的了。 我的理解是此时str的值应该为efcde，但是实际的值是ef　　　这个说的也是有问题的　不止是这一个函数，大多数获取函数都会在结束加\0 你这里ｓｔｒ的值不是ｅｆｃｄｅ而是ｅｆ'\0'de，你的输出判断都是判断是不是\0，是这个就截止，这也是同样的道理为什么直接赋值给第一个地址不好[/quote]  因为赋值完后会在数组后面自动加‘\0’，我输出时到‘\0’结束，所以才只会打印ef。而实际上数组在我后一次赋值后变成了ef'\0'de,  它覆盖了前一个字符串的前3位。  是这样理解吗？

数组越界就不说了，你这个判断，运行都是正确的嘛？这个数组越界不会影响你的ｆｌａｇ值，影响的地方在你每次循环都把他初始化为０，然后下面判断改为一之后没有跳出全部的循环吧，你这样跳出最里层循环那还是会执行外循环的下一次，就又把ｆｌａｇ重置了，那两个不等于的时候就到ｆｌａｇ等于０退出了，所以你这个除了某些特定情况，比如你外循环是最后一次，不然都会ｆｌａｇ等于０吧 其次你这个为什么要在最后给赋值\0呢？完全用不到这两个啊，就算要初始化也是最开始定义的时候初始化为{}啊

//str[1000] = '\0'; 这条语句越界了，越界访问的结果是未定义的。     str[1000] = '\0';     //请问在这里加这条代码 和在上面有什么不一样？         str1[1000] = '\0'; 这两条语句一样是越界了。下表的范围是[0, 999]

越界的问题，楼上已经说了。楼主应该知道，数组(array)、map、list等等，都是从0开始的，最后一个值是ARRAYSIZE(arr) - 1

第二条我说错了， 应该是我每次重新给str和str1赋值的时候就会将之前的值覆盖掉吧？ 比如我第一次给str = “abcde” 第二次str = “ef”，我的理解是此时str的值应该为efcde，但是实际的值是ef。 是应为gets函数的缘故吗？

1、你的意思我明白了  我越界赋值为‘\0’了。  2、我的本意是想每一次循环前将str置为空。其实不用这样吧，每次循环完之后会str和str 就已经是空了吧？ 3、如果我要将一个字符串赋值为空除了一楼说的memset函数清空，str[0] = '\0'也可以吧？

str[1000] = '\0'; 这个是越界操作，你的临时变量都存在栈中，flag变成0说明str之后就是flag的保存地址，str[1000]='\0',相当于flag=0; 你只可以str[999]='\0';


Question: 求大佬帮忙

思路从数组和链表出发，存一个数字，然后单个计算，考虑进位，最后存储链表或者数组中，文件io操作到文档里面，或者直接操作文件，然后结束。


Question: 求助，按英文反向输出浮点数

你需要把 inum 定义为float 或者double 啊 scanf("%lf",&inum);

引用 1 楼 真相重于对错 的回复:第一浮点数不能用%运算 第二浮点数不能精确表示一个数  取巧的方法  char arr[80];     sprintf(arr, "%2lf", 4.6); 然后对 arr 取反 对了，我想还是我没表达清楚。 比如一个终端输入一个浮点数123.456，如何输出成six five foru.three two one；

引用 1 楼 真相重于对错 的回复:第一浮点数不能用%运算 第二浮点数不能精确表示一个数  取巧的方法  char arr[80];     sprintf(arr, "%2lf", 4.6); 然后对 arr 取反 额，超纲了。。。我才开始看到数组，我过两天熟悉了验证一下。 对了，顺便厚着脸皮问个事，刚刚试了一下条件表达式： 		inum/10!=0?(renum=inum%10,inum=inum/10):(renum=inum,nsign=false); 		/*if(inum/10!=0) 		{ 			renum=inum%10; 			inum=inum/10; 		} 		else 		{ 			renum=inum; 			nsign=false; 		}*/ 实现效果是一样的，第一种看着美观点。问个对我来说很超纲的问题，对于C语言，条件表达式和IF语句哪种更效率更好一点？


Question: 现在边哭边看着这段代码，有大佬可以帮帮我吗？

可以将字符串用空格拆分后放入一个vector,然后反向迭代，发现里面是空的就不打印，你自己加额外空格，搞定收工

先不看代码了，给你提供一种解题思路吧： 1、按照空格将字符串拆分成若干份放到一个数组中， 2、将数组中自有空格的元素去掉， 3、将数组翻转， 4、合并数组重新生成字符串。

这个问题的算法可以更简单一些。例如，对于串“abcd  efg hi”，可以进行以下三步： （1）将整个串反向，“ih gfe dcba” （2）按单词进行反向，“hi efg abcd” （3）按格式（单词间空一个空格）输出。 其中的串反向可以写成一个函数 char * reverseWords(char * s, int len);

比如这样的字符串遍历“abcd efg”拆分成2个单词你会怎么做？很自然想到遍历字符串的字符，如果不是空格字符就一直追加到临时变量数组里，如果遇到空格，说明之前的临时变量数组的信息构成了一个单词，则把临时变量数组的信息作为一个单词保存。所以，两个if就是干这事的，第一个if判断是不是空格，不是空格则把字符追加到stack里，第二个if判断是空格，说明遇到了单词分割符，则把stack的信息保存到res里。 flag的作用就是判断有没有构成单词（即有没有不是空格的字符），如果构成单词（即flag==1），因为单词和单词之间要用空格分开，所以要追加一个空格；如果没有构成单词（即flag==0），比如连续读入多个空格字符”      ”，那么就没有必要追加空格。 最后while是判断有没有遇到非空格字符，比如“abc”这样的字符串，是不会进入if(s[i]==‘ ‘)的，这样进入if(s[i]!=‘ ‘)时保存到stack的信息就没有机会保存到res里，所以最后要做一次判断读入的数据是否有非空格的字符，如果有（即t>0)，则把stack的信息保存到res，比如“abc”这样的字符串，在for循环保存了stack=abc，for循环之外的最后的while才会把stack的信息保存到res 最后的if(t==0)是为了去掉多余的空格，比如上面分析if(flag==1)时，res追加了一个空格，假设这时候for循环刚好结束，那么res的最后是不是正好多了一个空格？所以要去掉这个多余的空格。怎么判断有没有多余的空格，就是最后的两个if(t==0)和if(count>0)，前者表示追加if(flag==1)追加空格后，没有再读到非空格字符（也就是没有再进入if(s[i]!=‘ ‘))，所以t为0；后者表示出现过单词（也就是进入过if(s[i]==‘ ‘)），否则count不会增加。

引用 2 楼 user-5 的回复：执行一遍就很清楚了 #include <stdio.h> #include <stdlib.h> #include <string.h> char * reverseWords(char * s){     int len = strlen(s);     printf("len:%d\n",len);     if(len == 0)         return s;     char *res = (char *)malloc(sizeof(char) * (strlen(s) + 1));     //目测这里加1也行，用于句子末尾追加的\0作为结束符     char *stack = (char *)malloc(sizeof(char) * (strlen(s) + 1));     int i, t = 0;     int count = 0;     int flag = 0; 	 	//遍历一次整个句子，如果不是空格，进栈；如果是空格，出栈     for(i = len - 1;i >= 0;i--)     {         if(s[i] != ' ')         {             stack[t++] = s[i];             printf("stack[%d]:%c\n",t-1,s[i]);             flag = 1;         }         if(s[i] == ' ')              {             while(t > 0)             {                 res[count++] = stack[--t];                 printf("res[%d]:%c\n",t,res[count-1]);             }             if(flag == 1)             {                 res[count++] = ' ';                 printf("== res[%d]:%s\n",count-1,"加空格");             }             flag = 0;         }     } 	//用于处理特殊情况：输入的句子开头有空格     if(t == 0)     {         if(count > 0)         {             count--;         }     }     //用于处理特殊情况：输入的句子没有空格     while(t > 0)      {         res[count++] = stack[--t];     }     //句子末尾需要加\0作为结束     res[count] = '\0';     return res; } int main(void) {      char* ret = reverseWords("example"); 	printf("%s",ret); 	return 0; }最后面的两个特殊情况和t有什么关系？我想不明白

引用 4 楼 weixin_45906870 的回复：[quote=引用 3 楼 qybao 的回复：]为什么+2？是为了数组不越界，其实+1就可以了。 至于思路，那就太简单了，字符串反过来遍历，遇到非空格则临时保存字符，遇到空格则把临时保存的字符反过来保存到最终结果 比如 hello world反过来遍历就是（从len-1倒着遍历） dlrow，临时保存到stack，然后遇到空格，把stack的信息反过来变成world保存到res，然后res加个空格 继续for循环遍历就是 olleh 临时保存到stack，然后for循环结束，代码继续执行到for后面的while t循环，把stack的信息反过来变成hello保存到res 最后res加上‘\0’字符串结束符 所以res最终就是world hello可以解释一下flag=1和flag=0的作用吗？[/quote]能解释一下最后面的while循环和两个人if循环吗？我没看懂

引用 3 楼 qybao 的回复：为什么+2？是为了数组不越界，其实+1就可以了。 至于思路，那就太简单了，字符串反过来遍历，遇到非空格则临时保存字符，遇到空格则把临时保存的字符反过来保存到最终结果 比如 hello world反过来遍历就是（从len-1倒着遍历） dlrow，临时保存到stack，然后遇到空格，把stack的信息反过来变成world保存到res，然后res加个空格 继续for循环遍历就是 olleh 临时保存到stack，然后for循环结束，代码继续执行到for后面的while t循环，把stack的信息反过来变成hello保存到res 最后res加上‘\0’字符串结束符 所以res最终就是world hello可以解释一下flag=1和flag=0的作用吗？

哪看不明白，那就加上打印看程序是怎么执行的


Question: 关于堆排序的一点点问题，求助大佬们，我很菜，勿喷。

//调整（重建）大根堆 void BigHeap_Adjust 这里的函数是错误的。同样地 SmallHeap_Adjust 也是错误的。


Question: [求助]如何在pe文件中插入section，并使得新节执行，执行时安装一个自己的一个handle函数到seh中

利用seh问题是不就转换成怎么把一段汇编代码注入到程序中了？这么做可以吗

引用 1 楼 user-1 的回复: 插入病笃的节奏。 以前c/c++搞过，尾部插入section.然后修改入口点为新section.运行完了自己代码再跳到原oep. 一般没加壳的exe插入，但加壳的一些插不了代码。无法运行 强！但是我主要是想利用seh，不想修改入口点，这样太明显了


Question: 大佬救命，这段代码我看了2小时都没看懂

非常感谢

找奇数回文从第二个元素到倒数第二个元素查找没问题，出现编译错误肯定是你的代码有问题。 一般来说奇数回文和偶数回文长度不可能一样长（奇数不可能等于偶数）。如果真出现回文一样长，那按现在的代码是奇数优先，因为if是判断是大于len才会交换，也就是等于len不交换，所以即使偶数回文长度和奇数回文一样也是奇数回文优先 一个字符算不算回文，这就看回文怎么定义了。顺着输出是该字符自己，逆着输出也是该字符自己，所以顺着和逆着一样，从这个角度看一个字符也算回文

我还发现一个问题，当数组中没有回文字符串时，函数最后会返回数组中的第一个字符，难道一个字符也算回文字符串？

引用 2 楼 user-2 的回复：楼上说的很详细了，我补充下最后两句的意思 s[start + len] = '\0';           return s + start; start是回文字符串在原字符串s的起始位置，len是回文字符串的长度，s[start + len] = '\0'; 把s字符串截断在start + len的位置上了， return s + start;返回了原始字符串s中回文字符串的起始位置地址如果目标数组中既然奇数回文又有偶数回文，再连续经过两个for循环最后return的回文是奇数还是偶数呢？上面的代码好像没有判断啊？

引用 1 楼 qybao 的回复：i从0位置开始不断右移，然后以i位置为中心，分别循环比较left和right的字符是否相等，如果不等，则while循环结束，然后判断left和right相等的字符的长度，如果长度大于最大值len，则说明以i为中心的回文更长，所以重新更新len以及回文的开始位置 举个例子 xabababa 当i移到第一个b位置，left和right字符都是a，是回文（aba），长度为3个字符，大于len0，所以更新len为3，start为1 当i移到第二个a位置，left和right的两个字符是ba，长度一共为5个字符（ababa），大于之前的len3，所以更新len为5，start为1 当i移动到第二个b位置，left和right的三个字符是aba，长度一共是7个字符（abababa），大于之前的len5，所以更新len为7，start为1 当i移动到第三个a位置，left和right的两个字符为ba，长度一共是五个字符（ababa），不大于之前的len7，所以不用更新len和start 后面依次类推  至于为什么用两次for i 循环 因为第一次for是为了找 abcba这种回文，也就是中心位和左右两边的字符不同，所以第一次for循环的left是从i-1开始算的 第二个for是为了找 abba这种回文，也就是没有中心位，就是直接左右对称的回文，所以第二次for的left是从i开始算的第一个for循环的条件为什么不能改成for（int i=1；i小于N-1；i++）？既然是找奇数长度的回文，那么从第二个元素开始右移到倒数第二个元素不可以吗？可是我改成这样却会编译错误，错在哪？


Question: ubuntu系统中gcc的环境变量问题

引用 5 楼 自信男孩 的回复:不是你的问题莫名其妙，而是这个问题莫名其妙。你装的是什么系统？Ubuntu吗？如果是Ubuntu那么应该不需要修改环境变量的。直接可以用，并且是在用户目录下的任何目录里都可以使用。 其实就是我想偷懒。 自建了一个文件夹专门放.c的文件，本来想偷懒在任何位置不用带路径，直接gcc这些的，于是在$PATH中添加了自建文件夹的路径，结果发现gcc不会管$PATH的。 其实看了你的回复，我想了半天，发现我这问题真的就是脱了裤子放屁。

引用 1 楼 自信男孩 的回复:装好系统之后，不需要配置任何环境呢，直接就可以使用gcc。如果需要更高版本的，可以直接用命令安装，安装之后也可以直接使用，也不需要配置环境变量呢。你的问题很奇怪 谢谢谢谢，我是才学习的C语言，包括linux系统也是才接触，很多东西都是在网上面边看边学的，有很多问题可能对于熟悉的人来说莫名其妙的，其实这也是初学者最头疼的地方，以后我会尽量将问题描述清楚的。再次感谢你关注回复这个问题。

引用 2 楼 二进制脑袋 的回复：[quote=引用 楼主 Stariamer 的回复:]初学C语言，正好电脑装了双系统，听网友说linux和C语言最搭配。只是有个小问题一直没有得到解决，希望各位朋友能帮帮忙。  我在电脑里新建了一个“Practice”文件夹，这个路径也加入了linux的$PATH中。现在的问题就是，如果我在此文件夹中打开终端，然后运行gcc hello.c -o hello，可以正确输出一个可执行的hello文件，在终端运行hello，也会正确的输出“hello world!”(毕竟我也是个会用多种语言写“hello world”程序的高手)。如果我从其他位置运行gcc hello.c -o hello，则会提示gcc: fatal error: no input files ，可是我在任意位置运行hello，却能正确的输出“hello world!”。我特意echo $PATH看了一下，Practice”文件夹的位置也的确在$PATH中。对此我感到很迷惑，ubuntu中的$PATH对gcc没有效果吗？  不光ubuntu的$PATH对gcc的输入文件无效，Windows也一样。gcc是不搜索$PATH路径来寻找输入源文件的。你在任意位置运行hello可以运行，那是因为你输入hello时，Shell程序会根据$PATH搜索可执行文件的。[/quote]原来如此，我昨天头疼了一晚上呢，本来打算偷个懒的，看来还是老老实实的在源代码的文件夹里开终端编译吧。谢谢🙏

引用 楼主 Stariamer 的回复:初学C语言，正好电脑装了双系统，听网友说linux和C语言最搭配。只是有个小问题一直没有得到解决，希望各位朋友能帮帮忙。  我在电脑里新建了一个“Practice”文件夹，这个路径也加入了linux的$PATH中。现在的问题就是，如果我在此文件夹中打开终端，然后运行gcc hello.c -o hello，可以正确输出一个可执行的hello文件，在终端运行hello，也会正确的输出“hello world!”(毕竟我也是个会用多种语言写“hello world”程序的高手)。如果我从其他位置运行gcc hello.c -o hello，则会提示gcc: fatal error: no input files ，可是我在任意位置运行hello，却能正确的输出“hello world!”。我特意echo $PATH看了一下，Practice”文件夹的位置也的确在$PATH中。对此我感到很迷惑，ubuntu中的$PATH对gcc没有效果吗？  不光ubuntu的$PATH对gcc的输入文件无效，Windows也一样。gcc是不搜索$PATH路径来寻找输入源文件的。你在任意位置运行hello可以运行，那是因为你输入hello时，Shell程序会根据$PATH搜索可执行文件的。


Question: 可能是库函数出了问题，求解答

引用 1 楼 user-1的回复:环境问题吧，装个vc吧 能给个下载地址吗？

环境问题吧，装个vc吧


Question: 求大佬帮我看看这段代码

完全有可能啊，strsSize是传入的参数，和strs没有直接必然联系，所以strsSize的值可以和strs的长度不同，但是为了运算结果的正确，strsSize和strs的长度要确保一致

我举个例子：当strsSize等于1时，是不是可能存在这种情况strs=｛“abcdefg”，“”，“”｝，即除了第一行字符串，其他行都是空字符串？

strsSize是代表输入的字符串个数（换句话说也是二维数组strs的长度） strsSize为0表示输入的字符串个数为0，也就是没有输入，所以没有共通前缀，即前缀为空 strsSize为1表示输入字符串的个数为1，也就是只有一个输入，所以共通前缀就是字符串本身（相当于字符串自己跟自己比） 不管strsSize是什么，都不会改变strs是二维数组，所以不存在strsSize为1，strs就变成一维数组之说。strsSize为一只是说这个二维数组只有一个元素，也就是只有一个字符串。


Question: 我的代码不知道为什么出现错误

#include <stdio.h> #include <stdlib.h>  int CountDigit( int number, int digit );  int main() {     int number, digit;      scanf("%d %d", &number, &digit);     printf("Number of digit %d in %d: %d\n", digit, number, CountDigit(number, digit));      return 0; } int CountDigit( int number, int digit ) {      int m = number  ;     int total = 0 ;     if( m == 0)     {         return 1 ;     }     while(m != 0)     {         /*         if( m % 10 == digit || m % 10 == -digit )         {             total += 1 ;              m /= 10 ;         }         */         if (abs(m % 10) == digit)             total++;         m /= 10;     }      return total; } 供参考～

把m /= 10 移到if 外面

后面函数有问题  int CountDight(int number, int dight)  {  	int m = munber;  	int total = 0;  	if(!m)  		return 1;  	else  		while(m)  			if(m % 10 == dight || m%10 == -dight)  			{  				total++;  				m /= 10; 			 } 	return total;  }

真的强！！！

引用int CountDigit( int number, int digit ) {      int m = number  ;     int total = 0 ;     if( m == 0 )     {         if(digit == 0)         {              return 1 ;         }        return total;     }     else     {         while(m != 0)         {           if( m % 10 == digit || m % 10 == -digit )           {               total += 1 ;                  m /= 10 ;           }         }      }     return total;  }  我也发现了，但是改完以后在运行会出现运行超时

代码本身就不对 return total要放到while循环的外面，否则循环一次就return了，结果肯定不对 另外，m==0时不应该return 1，要判断digit是否也为0，是才返回1，否则返回0


Question: 《C程序设计教程》中的一道关于switch的题目

case 1没有break，因此继续执行外层switch的case 2

哦我明白了。case1后面没有break，所以case1的语句执行完了，继续执行case2中的n++，所以n总共自加了2次，最后值就等于2了。

1、switch(1)，进case1， 2、子句里，switch(2)，进case2，n++，n变成1，break退出switch(2)的循环， 3、这时候要判断的这个值是2，所以再进case2，n++，n变成2，再break退出外层的switch循环， 4、所以最后打印出来n=2，  过程是这样吧？

跟switch里面常不常量无关，它是多少就case多少

switch(1) 当switch()里面的参数是常量时，后续的case是怎么选择的？

case 1:  没有 break


Question: c语言，新手求大神指点

scanf,strcmp

getchar()只能获取单个字符

输入语句的话，那就是字符串处理了。字符串处理可以参考：fgets, strcmp,strcpy等等函数  else if (c == 'name') 这儿的name应该是字符串，'name'是非法的，字符串比较应该用strcmp

chat c[256]; //用字符串 while(gets(c)!=NULL) { //接收字符串     if(strcmp(c, “hi”)==0) //字符串比较         printf(xxx)     ... }


Question: VC6的Visual Assistant的自动补全怎么用？

引用 1 楼 user-1 的回复:你设置一下VA  多谢，设置界面点不开，跑到他们官方论坛查了一下，发现这个是老兼容性问题。现在项目取消用VC6的界面了，仅仅用他们的命令行来编译。

你设置一下VA


Question: 大佬们，帮我看一下

麻烦问一下有答案了吗

求代码还是求解决代码问题的，建议楼主可以先自己尝试实现，遇到问题再提出来，这样能学到东西。

同问！！你有1、4题的答案了嘛小姐姐

面试题吗

好好写作业，期末考试不愁

都是基础 = = 而且一看就知道是布置的作业  自己琢磨吧   把不懂得代码拿上来问还差不多


Question: 小白c#求帮忙

你发到C语言板块了


Question: 为什么visualC++6.0不能输出长整型啊？

VC 6.0  unsigned __int64 test = 123456789123456789; printf("%I64u\n", test);

64位整型定义 __int64 a; or unsigned __int64 a;

溢出了，a的内存是long类型，存不下这么大的数据的。用long long或long double存放。用long double存放，要用%Lf输出

long是32位的，截断了，可以定义long long


Question: 求大佬帮忙看一下这段代码

第二个问题，不能改成等于，要是没有相等的元素那岂不是就不能二分了

引用 3 楼 李牧大将军 的回复：int searchInsert(int* nums, int numsSize, int target){   //你要理解这里的两个变量 left right 这代表了数组的最左边（即最低值）与最右边（即最高值）的数组下标       int left = 0, right = numsSize, mid;    //=numsSize你可以理解为加上你输入的值 比如{1,3,5,6}加一个你输入的7  最右的下标为4  如果你将值等于numsSize-1那么会导致这个返回值为3 而不是 4     while (left < right) {            mid = left + (right - left) / 2;         if (target <= nums[mid]) {    //上一步将mid赋值 是取数组中间的值 即 nums[mid]   这里<=nums[mid] 是直接将你输入的即将插入的target值与中间的值对比               right = mid;   //如果你插入的值小于中间值  就将数组的最右边right （即最高值）的下标赋值成中间值的mid  即实现二分         }else{             left = mid+1;//如果你插入的值大于中间值  就将数组的最左边left （即最低值）的下标赋值成中间值的mid  即实现二分         }     }   经过上面left与right值的重新赋值 也就是说 以前长度为4的数组变成长度2了  也就可以while循环取中间的值      return left; } 二分的理解 举个例子：     猜数字： 要猜中猜100以内的某个值 你会先猜 50（即target ）                   -》小于-》 你就直接丢掉 50以下的值 （即在（ left = mid+1）51 -100 之间继续猜 ）                   -》大于或等于-》你就直接丢掉 50以上的值（即在（right = mid）0-50 之间继续猜 ） 一直循环                   -》小于-》 你就直接丢掉 75以下的值 （即在（ left = mid+1）76-100 之间继续猜 ）                   -》大于或等于-》你就直接丢掉 25以上的值（即在（right = mid）0-25之间继续猜 ） ......循环直到猜中那最后为什么是return left而不是return right？

这种算法题，最好自己单步调试一下。理解才会深刻。


Question: 请大佬看看c语言这个是哪里出问题了呢？谢谢大家

应该是哈，我去安装，谢谢你

应该是哈，我去安装，谢谢你

没有找到graphics.h这个头文件。你是没有安装这个图形库吧？


Question: 龙芯机器上编译openssl报错

解决了，是脚本在龙芯上默认按32位编译了，改成指定64位编译过去了

怎么解决的，我也碰到这个问题了


Question: C语言，请大神看看到底错在哪里

我想您是不是要求2000-2100年中的闰年啊？ #include<stdio.h> #define lower 2000 #define upper 2100 int main() { 	int year; 	bool r; 	year = lower; 	do { 		r = ((year % 4==0) && (year%100!=0))||(year%400==0); 		if (r) 			printf("%d Yes\n", year); 		else 			printf("%d No\n", year); 		year = year + 1; 	} while (year <= upper); 	return 0; }

引用 1 楼 自信男孩 的回复:判断if (r=0)改成if (r == 0) 除了这个你还要把r = year % 4放在do-while循环里面

= 和 == 的概念不清

判断if (r=0)改成if (r == 0)


Question: 子函数的printf为什么没有在main里调用输出成功？

printf("参数: \np: %s\na: %s\nb: %s\nn %s\nGx %s\nGy %s\n", p, a, b, n, Gx, Gy); 肯定是变量与格式符的匹配问题

调试一下看看，就明白了

匹配，用到一个第三方密码学库

格式是否匹配，从代码里看不出来～


Question: 求解

#include <iostream> int main() { 	while(true) 	{ 	   int a,int b; 	   cin>>a; 	   b = 300 - a; 	   std::cout<<b<<std::endl; 	} 	return 0; }

搞个线程  在里面按1楼输的B = 300 - A; 执行代码   可以加延迟睡眠啥的

写成A+B=300;是个不合法的语句。A+B是一个表达式，表达式是个右值，是不允许写在等号左边的。

这是什么问题？

你这种写法是错误的，A+B得到是常量，不能做左值。

B = 300 - A;


Question: 求大佬帮我看看这段代码是什么意思？

第一问 因为最左的索引是0，假设中心索引是最左的索引0，那么它的右边元素的和是从位置1开始算的 第二问 原因和第一问相同，假设中心索引在0位置，那么右边元素的和是从位置1开始算的，也就是右边的和最大就是从位置1开始到数组最后的元素相加 第三问 上面第一第二问是假设中心索引在0位置时求出的right，那么这个中心索引不断往右移动是什么情况？i++表示中心索引右移，left+=nums[i]表示中心索引右移后，中心索引的左边多了一个元素，要加到左边的总和left里，right-=nums[i]表示中心索引右移后，右边少了一个元素，要从right减出来。至于执行顺序，你自己推算一下就可以，假设当前位置i是中心索引，中心索引右移，那么原来的i位置就成了左边的元素，所以先执行left加和，然后移动中心索引到i++位置，移动过来的i++原来是右边的元素，现在变成中心索引了，所以要从ringt里减出来

你好好想想。 right代表是中心点右侧的数的和。 所以不用算第0个元素，因为左侧至少要包括一个元素，否则不叫对称。


Question: 程序编写

文件读写参考  我用#CSDN#这个app发现了有技术含量的博客，小伙伴们求同去《C语言文件读写（1）-文本文件读操作》, 一起来围观吧 https://blog.csdn.net/zhanghaiyang9999/article/details/107032563?utm_source=app

供参考  #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 256  int main(void) { 	int temp[N] = { 0 }; 	char a[N] = { 0 }, c[N] = { 0 }, ch; 	int i = 0, j = 0, k = 0, count = 0; 	FILE *fp = fopen("test2-2.in", "r"); 	if ( !fp ) 	{ 		printf("文件读取失败！\n"); 		exit(1); 	}  	fscanf(fp, "%s", a); 	count = strlen(a); 	printf("原字符串：%s\n", a);  	for ( i = 0; i < count; i++ ) 	{ 		if ( i % 2 == 0 ) 		{ 			temp[j] = i; 			c[j] = a[i];			 			j++; 		}			 	} 	printf("下标为偶数的元素：%s\n", c);  	 	for ( i = 0; i < j-1; i++ ) 	{ 		for ( k = 0; k < j - 1 - i; k++ ) 		{ 			if (c[k] > c[k+1]) 			{ 				ch = c[k]; 				c[k] = c[k + 1]; 				c[k + 1] = ch;				 			} 		}		 	}  	for (i=0; i<j; i++) 	{ 		a[temp[i]] = c[i]; 	} 	printf("排序后字符串：%s\n", a);  	fclose(fp); 	getchar();     return 0; }


Question: 编写程序

不贴代码，说一下思路，先调用C语言里按行读取文件的api（没有这种api就一个字符一个字符的读取知道碰到\n），到了所在行数，就一个字符一个字符的读取，以空格分割

#include <stdio.h> void disp( int );  void disp(int n) { 	int line=0;		//line：行计数器  	char ch; 	FILE*fp; 	fp = fopen("test1-2.dat","r");		//打开文本文件  	while ( line<n && (ch=fgetc(fp))!=EOF ) { 		putchar(ch);		//显示读入的字符  		if (ch=='\n')		//若读入\n则对line计数  			line++; 	} 	fclose(fp); }  int main(int argc, char** argv) { 	int i,j,k,n; 	FILE*fp; 	if ( (fp = fopen("test1-2.dat","w")) == NULL ) { //采用文本文件保存原始数据 		printf("Open file error."); 		return 0; 	} 	for (i=0; i<10; i++) {		//俺指定格式生成文件  		for (j=0; j<=i; j++) { 			k = i*4+1+j*2; 			fprintf(fp, "%4d", k); 		} 		fprintf(fp, "\n"); 	} 	fclose(fp); 	scanf("%d", &n); 	disp(n); 	return 0; } 请看看以上程序是否满足你的题目要求。

#include<stdio.h> void disp(int n) {	int i,j,k; 	FILE*fp; 	fp=fopen("test1-2.dat","rb"); 	for(i=0;i<n;i++) 	{ 		for(j=0;j<=i;j++) 		{ 			k=getw(fp); 			printf("%d\t",k); 		} 		printf("\n"); 	} 	fclose(fp); }   void main() {  	int i,j,k,n; 	FILE*fp; 	fp=fopen("test1-2.dat","wb"); 	for(i=0;i<10;i++) 	{ 		for(j=0;j<=i;j++) 		{k=i*4+1+j*2; 		putw(k,fp); 		} 	} 	fclose(fp); 	scanf("%d",&n); 	disp(n); }


Question: 一个刚学C语言的人求助

VC++6.0个人感觉挺好用的，我一直用着呢，加油！

#include <stdio.h> int mian() { 	int price = 0; //定义放在所有函数前面   	int change = 0;   //定义放在所有函数前面   	printf("请输入金额（元）:   "); 	scanf("%d",&price); 	change = 100 - price; 	printf("找您%d元\n",change); 	return 0; }

变量先定义，请不要再使用VC++6.0了，推荐使用vs或者vscode，退而求其次用Dev-C++

引用 6 楼 千梦一生 的回复:长见识了。原来C语言这种声明和定义必须要分开 刚去学习了一下。C99之前的标准。变量要在开头声明定义，期间不允许声明定义

长见识了。原来C语言这种声明和定义必须要分开

这个跟编译器版本有关，用新的编译环境试试，应该就不会报错了。

你用的是C语言，所有变量必须在程序开始时定义。而使用C++就不存在这个问题了

要先声明再使用

vc6.0必须把变量声明放在前面;

因为是c语言，change需要放到前面，放到price后面就可以 int change=0;


Question: 求大神帮忙，编辑一个程序

先试着写写，遇到问题再提出来吧～

这些都是基础的内容吧

排序参考一下这个 我用#CSDN#这个app发现了有技术含量的博客，小伙伴们求同去《C语言基础排序算法-冒泡排序》, 一起来围观吧 https://blog.csdn.net/zhanghaiyang9999/article/details/107102728?utm_source=app

引用 1 楼 user-3 的回复:考察内容还挺多，还有排序嗯，确实不少，唉……就这个排序不知道怎么往里面加……

考察内容还挺多，还有排序


Question: 请问为什么把a,b,c三个变量的类型改成float程序就能正常运行呢

double类型输入需要lf


Question: 老师布置的一道C语言题目不是太会做，请教大佬

引用 5 楼 白浅星的回复:刚学C语言，上面的代码确实难为你了，看这个吧，上面那些就不看了.  #include <stdio.h> #include <conio.h> int main() { 	char ch;//字符获取 	int big = 0, small = 0;//统计 	do { 		ch = getchar();//获取首字母 		if (ch >= 'A'&&ch <= 'Z')//判断首字母是否大写 			++big; 		else 			++small; 		while ((ch = getchar()) != ' ' && ch != '\n');//判断完词首后，这里来读取掉剩余的单词，直至遇到空格或者回车结束 	} while (ch != '\n');//如果不是遇到回车就继续读取下一个单词词首 	printf("词首是大写单词的个数:%d", big);//统计完毕，开始输出 	printf("词首是小写单词的个数:%d", small); }  非常感谢大佬

有穷自动状态机  void main() {     // 连续多个空格视为一个；数字不在统计内，“，”等符号不作为分割符     TCHAR * szString = _T("Hello world aabbc Hehe haha 783279 abc,ere              afdsewre");     int state = 1;     int UpperWordsNumb = 0;     int LowerWordsNumb = 0;     for( LPCTSTR pStr = szString; *pStr != _T('\0'); ++pStr )     {           switch( state )           {            case 1:                    if( *pStr >= _T('A') && *pStr <= _T('Z')                    {                            ++UpperWordsNumb;                            state = 2;                    }                    else if( *pStr >= _T('a') && *pStr <= _T('z'))                    {                            ++LowerWordsNumb;                            state = 2;                    }                    break;             case 2:                      if( *pStr == _T(' ') || *pStr == _T('\t') || * pStr == _T('\r') || *pStr == _T('\n'))                           state = 1;                      break;           }     }      printf(_T("大写单词个数：%d\r\n小写单词个数：%d", UpperWordsNumb, LowerWordsNumb )); }

引用 1 楼 user-3的回复:#include <iostream> #include <boost/tokenizer.hpp> #include<cctype> int main() { 	int numUpper{ 0 }; 	int numLower{ 0 };  	std::string s = "Boost C++ libraries hello 234 World"; 	boost::char_separator<char> sep(" "); 	boost::tokenizer<boost::char_separator<char> > tok(s, sep); 	for (auto it = tok.begin(); it != tok.end(); ++it) { 		auto firstChar = (*it)[0]; 		if (isupper(firstChar)) 			numUpper++; 		else if (islower(firstChar)) 			numLower++; 	} 	std::cout << "大写单词个数：" << numUpper << std::endl; 	std::cout << "小写单词个数：" << numLower << std::endl; 	//大写单词个数：3 	//小写单词个数：2 	system("pause"); } 大佬  还有比较简单一点的吗，我们才开始学C语言没多久，这些结构还没学到


Question: 单循环链表建立和打印有什么问题吗

代码太多 我也没仔细看 就看了你的插入   没看见你哪里分配了内存  你只是在main函数开头分配了一个节点的结构体内存    你要在每次插入的时候都malloc分配一个内存

现在链表插入的时候 都不用malloc 分配内存  删除的时候free 释放内存了吗 --- -- --

为什么代码会这么多？就实现输入和打印

代码太多太乱，没细看，但从 node*Set(node*head,node*p) //在尾部插入p节点 void Print(node*head)  这两个子函数中看到逻辑应该是有问题的。 单链表的尾结点必须指向NULL，否则你不知道单链表何时到尾。

支持楼上。 第20行改成：node *p; 在case 1:   后面增加一行  p = (node*)malloc(sizeof(node));


引用 2 楼 浴火_凤凰 的回复:链接的本地数据库还是远程数据库？本地和远程，都一样慢

连接的是同一个服务器  引用 1 楼 user-2 的回复:你俩MySQL版本一样吗？有的MySQL版本就是连接慢

链接的本地数据库还是远程数据库？

你俩MySQL版本一样吗？有的MySQL版本就是连接慢


Question: 经常运行c文件后.exe程序就要权限才能运行操作

不过好好的Windows程序，为什么不使用vc这样的开发工具呢？

win下用gcc编译器，貌似编译信息无法正常显示中文阿。

引用 3 楼 Army_Adviser_ 的回复:你这个应该是上一个运行的程序没关闭   打开任务管理器 看看有没有ld的进程   有的话杀掉就好了问题就在这里。。。。也找不到id进程，按道理应该是这问题，关机后清理进程就正常了

引用 1 楼 Simple-Soft 的回复:有可能是你说的问题，你可以查看一下，另一个可能是需要administer运行程序 用的vs code，已经是administer账户了，感觉是进程在后台运行着。但是任务管理里边也没找到相应进程，头疼哈哈


Question: 平衡二叉树左平衡程序函数的疑惑

我引用的这张图片，不是我上面复制的那段代码，这个其实是右平衡里的变化，我拿过来只是想说一下我当时画的时候画出来了T->bf=lc->bf=EH就这一种情况，后来发现T和lc双旋后变了位置，应该看得是变化后的那个位置的RH,EH,LH里的哪一个符合，还是谢谢您，帮助了我那么久

现在明白这段代码的意思了，我一直当做是根节点的高度修改，却发现根节点最终被其他节点替代，应该是研究根节点变化后的高度，谢谢啦

兄弟你那个是右旋转，并且左树的右树相等

引用 6 楼 真相重于对错的回复:这个代码是严老师的？ 中间大多数关键函数都是严老师的，除了结构体和主函数

这是我引用的一个博主的图片，我最终的效果就是这样的，左右子树高度相等，不知道如何出来的switch(rd->bf){ case LH:lc->bf=EH;T->bf=RH;break;

这个代码是严老师的？

大佬可以给画一个这段代码的变化演示图吗？我可能理解有点问题，画出来的最终都是左右一样高

首先说一下结论，这段代码，没问题。 case RH:rd=lc->rchild; switch(rd->bf){ case LH:lc->bf=EH;T->bf=RH;break;   他的意思是，一个节点左树比右树高2，且这个节点的左子树的右子树比左子树的左节点高。 一般称之为双旋转。 旋转后节点的右部肯定要比他左部高

嗯嗯，第一次编写，还没来得及修改，一直在纠结那个LeftBalance函数里的根节点的左子树的右子树的高度为什么这样修改，希望能得到解释

嗯，有很多错误

这是全部代码

//平衡二叉树 #include <stdio.h> #include <stdlib.h> #define MAXV 25 #define EH 0 #define LH 1 #dedfine RH -1 typedef char infotype; typedef int keytype; typedef struct A{ 	keytype key; 	infotype data;	//其他数据 	int bf;	//记录左右高度信息  	struct A *lchild,*rchild;  }BSTnode,*BSTtree;  //创建平衡树  BSTnode* Create(keytype *k,int n){ 	BSTnode *T;int i; 	for(i=0;i<n;i++) 		InsertBST(T,k[i],taller); 	return T; }   //RR型左旋  void L.rotate(BSTnode *&T){ 	BSTnode *rc; 	rc=T->rchild; 	T->rchild=rc->lchild; 	rc->lchild=T; 	T=rc; }  //LL型右旋  void R.rotate(BSTnode *&T){ 	BSTtree lc; 	lc=T->lchild; 	T->lchild=lc->rchild； 	lc->rchild=T; 	T=lc;  }   //左平衡 void LeftBalance(BSTnode *&T){ 	BSTnode *lc,*rd; 	lc=T->lchild; 	switch(lc->bf){ 		case LH:T->bf=lc->bf=EH;R.rotate(T);break; 		case RH:rd=lc->rchild; 			switch(rd->bf){ 				case LH:lc->bf=EH;T->bf=RH;break;  				case RH:lc->bf=LH;T->bf=EH;break; 				case EH:T->bf=lc->bf=EH;break; 			} 			rd->bf=EH;  			L.rotate(T->lchild); 			R.rotate(T);  	} }   void RightBalance(BSTnode *&T){ 	//暂时未填  } int InsertBST(BSTtree T,keytype k,int &taller){ 	if(T==NULL){ 		T=(BSTtree)malloc(sizeof(BSTnode)); 		T->lchild=T->rchild=NULL; 		T->bf=EH;T->key=k;  		taller=1;	//1表示变高  	} 	else{ 		if(k==T->key){ 			return 0; 			taller=0; 		}  		else if(k<T->key){	//插入左子树  			if(!InsertBST(T->lchild,k,taller))	return 0; 	//插入失败  			if(taller){	//树变高  				switch(T->bf){ 					case EH:taller=1;T->bf=LH;break;	//原本左右子树等高，现在左子树高  					case LH:taller=0;LeftBalance(T);break;			//左平衡  					case RH:taller=0;T->bf=EH;break;				 				} 			} 		} 		else{	//插入右子树  			if(!InsertBST(T->rchild,k,taller))	return 0; 	//插入失败  			if(taller){	//树变高  				switch(T->bf){ 					case EH:taller=1;T->bf=RH;break;	  					case LH:taller=0;T->bf=EH;break;			  					case RH:taller=0;T->bf=EH;RightBalance(T);break;	//右平衡			 				} 			}			 		} 	} 	return 1; }   int main(){ 	int taller;	//记录树是否长高，1为长高 	keytype k[MAXV];int i,n;  	printf("请输入插入的数的个数\n"); 	scanf("%d",&n);  	for(i=0;i<n;i++){ 		printf("请输入第%d个数\n",i+1); 		scanf("%d",&k[i]);  	} 	BSTtree T; 	T=Create(k,n);  	return 0; }

具体没看到你的全部代码，无法回答。

就是我注释的地方，为什么要将T的左子树高度赋值成EH（左右子树相等），然后T的高度为RH（右子树高）。

没看懂你在说啥，


Question: unresolved external symbol

我有点弄晕了，这个简单的函数我后来又试了一下是没问题的，因为我一开始在函数里面有参数，我记得声明时可以只写类型不写参数名称，编译时遇到问题，检查了几遍不知道啥问题，后来才发现是声明时没写参数名，可能我用的编译器版本太老标准太老，总之我记得现在大多数在声明时可以只写类型的，可能早期标准必须声明和定义一模一样吧，谢谢大家了，调来调去有时候真想不到问题出在哪里

你都可以用hrec的其他函数了  那应该是没有问题的    是不是你修改的了文件没有编译到  你要不把文件删除再编译  报错后再恢复 重新编译  这样确保编译器识别了你的修改

对编译和链接的理解还是很成问题的。学校里好象不教这些东西吧？ 引用头文件只是帮助编译器识别函数的“样子”并顺利产生目标文件，这一阶段只是决定如何调用函数，不需要知道函数的实际位置和内容。 但是在链接阶段，链接器需要找到函数的定义。 想一想，这两步，卡在哪一步了。

make编译得包含实现文件

我自己建了个工程试了一下也没问题，我觉得只要找到了函数声明，工程会在整个工程内部自己找定义，不知道为啥这里不行。可是hrec.c的其他函数能调用啊，我读的这套程序比较老了，而且还是用nmake编译，头大

//h 文件  #include "stdio.h" void teset(void);  //c文件  #include "text.h" void teset(void) {     printf("AA"); }   //主程序  #include "stdio.h" #include "text.h"  int main() { 	while(1) 	{ 		teset(); 	} }    测试没有问题.


Question: 请问用C语言四则计算，怎么同时得到商数和余数？

引用 10 楼 chxchxkkk的回复:被除数下面的 scanf("%d", &a); 你把&a也写到双引号里了 大哥，括号后面都要;吗

被除数下面的 scanf("%d", &a); 你把&a也写到双引号里了

引用 7 楼 宇来风满楼的回复:[quote=引用 6 楼 luoquxin的回复:][quote=引用 1 楼 宇来风满楼 的回复:]建议百度啊 兄die，帮我看下哪错了 [/quote] 第7行吧啊啊啊[/quote] 咋改？？？？？？

引用 6 楼 luoquxin的回复:[quote=引用 1 楼 宇来风满楼 的回复:]建议百度啊 兄die，帮我看下哪错了 [/quote] 第7行吧啊啊啊

引用 1 楼 宇来风满楼 的回复:建议百度啊 兄die，帮我看下哪错了

引用 3 楼 chxchxkkk的回复:43 % 3 余数 这只是求余，还要求商

这只是求余，还要求商

43 % 3 余数


Question: 为什么2020年了C语言教材还用VC6.0

最大的不同是for语句里的变量的生存周期。VC6的是外部的，VC2003以上就是for 块内了。这导致了不兼容性

引用 8 楼 江南蜡笔小新 的回复:现在还用VC6，谭老师的教材吧？明日科技

因为VC6教学用比较合适，内容少，对电脑配置要求也低，不过就是标准比较老，还是用的C++98的标准。不过一般来说现在的新的也基本兼容老的，学习来说还是勉强可以用的。

交的是基础是原理

知识点是最基础的，入门再说

我敢说如果让你用命令行敲gcc，你还不一定会用，而且会打击你继续学习C语言的信心

也有很多适合新手的比如DevC++，或者主流的visual studio，设置起来不麻烦啊

其实应该改革下的，仅就操作而言，vc6和vs蛮多地方还是不一样的。不求最新的vs2019，升级到vs2010还是可以的。只是某些人太懒了，另外就是操作起来比较麻烦（体制原因）。

至少现在自己在教研室做项目用的visual studio 2017，周围没有人用VC6.0之类的

没用过vc6，最开始用dev，后来就用vs

不少高校教师照本宣科，学习新的成本他们不想负担，毕竟还要批改作业。

vc6挺好，简单小巧，轻量级。学习够用即可。 哪天感觉vc6用着没对了，就可以换了，那时候就不是老师们教了。  vs呀什么什么的，写代码很好 啊。但跟学C语言又有什么关系

vc++6.0绿色免安装版，占用内存小，界面简单，我一直用她

高版本的VC应该也支持低版本的吧

楼上那些说VC6只是工具，用什么都可以的，应该不是老师就是学生吧。 如果是学生，以后你要是参加了工作，执意要在公司里用VC6，说是你习惯这个，看公司的项目经理能容得下你不； 如果是老师，自己不行就算了，还要耽误学生前途，其心可诛。

都是工具而已，编写过程只有些许差别，看个人习惯或者企业需求

代码就算过不了也只是小改动  一些格式定义啥的变动吧   我觉得 你学的好  随便改改就能用了  原理一直都没变

我自己感觉可能有下边几个原因： 1、学校的教材，注重的是稳定性、正确性等，而不是追求新；学校教的知识，是需要经过很多次沉淀的。 2、第二点我认为老师教的知识基础、方法等，如果掌握了这些，后边再怎么变化，也能应对自如；如果说什么东西有新的出来，就立马当做教材，一方面是教学客观上不太现实，因为教材的编著、审核什么的，本身周期就很长，可能这本教材还没出来，下一个新的版本就又出来了。这样的话，只能以某一版本作为教学的基础，等后边如果时间太长了，再次进行升级替换。 3、我不反对楼上说的几点，只是提出我自己另外的思考。  就这么多了，纯属自己的个人观点~，希望对你有帮助！

因为vc6可以用

只有人去适应知识，哪有知识来适应人呢？你用的工具是vc2019，它用的是gcc，还有人用devc，千奇百怪，知识还是那些知识，遇到通不过的，稍微调整一下就好

引用 3 楼 user-18 的回复:有什么关系呢？知识还是那些知识 说得对极了。不管是用原始的镰刀收割，还是用现代化的大型联合收割机，都是将庄稼从地里收回来，脱粒，变成粮食。


Question: 指针题目-这个题目是怎么算的？

int k=7,m=5; void f(int **s) {     int *t,t=&k;             t指向k     s=&t;                     二级指针s重新指向一级指针t      *s=&m;                 *解引用降级即二级指针s 变为1级指针t 然后将一级指针t指向了m 同时 二级指针s仍然指向的t     printf("%d,%d,%d\n",k,*t,**s);   统计以上 s->t, t->m,  k没有被改变  所以是755 } int main(int argc, char **argv) {     int i=3,*p=&i, **r= &p;     f(r);       要改变2级指针r的指向只能去使用3级指针（但本可以改变i的值 因为**r存储了i的地址  可是f函数中将传入的s重新指向了也就丢掉了i的地址） 所以f函数运行完 指针r仍然是指向指针p的      printf("%d,%d,%d\n", i,*p,**r);     所以最终结果仍然是 333     return 0; }

首先r传给s之后，s和r是两个相互独立的指针。s就是f函数里的局部变量。因此f中对s的修改不影响main函数里的r  t = &k; t里存放了k的首地址。s = &t;那么s 里存放了t的首地址。到这一步，把k, *t, **s打印出来，应该是7, 7, 7; *s = &m;此时*s即t。即t里存放了m的首地址。这样，k, *t, **s打印为7,5，5


Question: for语句问题求解

搞懂了 nice!

按照你的思路设计应该是想这样吧 int main() { int i,j,k; k=0; for(i=1,j=100;i<=50;i++,j--) { k+=i+j; } printf("%d\n",k); return 0;	 }

你上面的K每次循环的值都为i+j=101，而下面的是累加，看得出来效果，你把j--改成j++，就看得出来效果了

k=i+j; 注意一下，循环体是赋值，不是k += i + j; 另外，你怎么知道循环体只执行了一次。如果只执行一次，就因为是k的输出值应该是101吗？因为i为100时，j正好为1了吧。 所以，不是只执行了一次，而是执行了100次，不信，可以在循环体里多加一条打印语句，比如加一条 printf("helloworld!\n"); 看输出几次。

那我是不是要得出5050还得来个变量累加50次k

想啥呢  上面的也循环了100次啊  你不信可以把pritf加到循环里面去  只是你一个加一个减 所以得出了的结果只会是101 int main() { int i,j,k; for(i=1,j=100;i<=100;i++,j--) { k=i+j; printf("%d\n",k); } return 0;	 } 这样你就能看到100条输出了


Question: 求解 哪里错了 。。

p1 = &a; p2 = &b; p3 = &b;  确实是上面这个地方没改成c，刚才该多来测试了一下就是对的，输出为3 2 1

引用 5 楼 Army_Adviser_ 的回复:exchage函数写错了  void exchage(int* c1, int* c2) { int *t = NULL; t = c1; c1 = c2; c2 = t; } 楼主的没有把c地址赋值给p3。 如果按照你的修改，输出的结果是1 2 3，顺序没变。建议测试一下

p3改成取c的地址，我这里用楼主代码运行结果是3  2  1

p1 = &a; p2 = &b; p3 = &b; 还有你p3没取c的地址诶

引用 1 楼 qiu_shaofeng的回复:这是什么疑惑呢 按 大小顺序输出  想知道哪来错了  抱歉没表述完整

引用 1 楼 qiu_shaofeng的回复:这是什么疑惑呢 按 大小顺序输出

这是什么疑惑呢


Question: CENTOS7.4  环境中的C语言程序中  如何将一个int型变量的最低字节的值赋值给一个byte型变量

1楼说的强制char赋值也能实现的   16位强转8位 系统会自动丢掉8位 至于是高八位丢掉还是低8位丢掉就要看系统是大端模式还是小端模式

1、确定平台的大小端问题。有些是大端，有些是小端。 2、确定平台中字节的位数问题。历史上极个别平台一个字节7位，不过现在基本没有了。 3、确定平台中int是多少位的。有些平台int是16位的，有些是32位，说不准还有64位的。

a & 0xff;就是a高位全0，低8位（低字节）保留。  跟进制没关系，内存中存放的都是二进制，随意跟16进制没关系。

如果要取前8位可以这样  int   a = 0x1234 ; byte b = (a>>8)&0xFF ;

int   a = 0x1234 ; byte b = a&0xFF ;  这样位操作不就好了

不知道题目是不是有问题。  我的思路是这样的：变量a是int型，如果是十进制的，可以在转成十六进制的过程中将每位的字符存到数组中，比如，十进制4660对应十六进制0x1234，存到数组中的数据就是a[4]={4,3,2,1}，接着再去给b赋值。  我疑问的是，你说b是byte型，也就是char型，将一个十六进制数强行赋值给它，本身就会发生强制类型转换。  看看楼下怎么说。。。


Question: 算法题求解

k=*(a+M-1);                          //把数组最后一个元素赋值给变量k   for (j=M - 1; j >=0; j--) {    *(a + j +1)= *(a + j);          //循环把数组元素向后移动一位   }   *a = k;                                //数组首元素的值现在是原数组最后一位了

*（a+j+1）=*（a+j）  好像越界了，出现了*(a+4)    *(a+m)相当于a[m]  意思是打印a[0],a[1],a[2],a[3]  *(a+......)可以用a[......]代替  这样应该会好理解一点


Question: C与指针第六章练习题答案是不是有问题还是我做错了？

与实际运行为准


Question: 取消对NULL指针xxx的引用

inputpart1指向了局部变量，因为局部变量的生命周期是从定义开始到函数返回结束，因此输出已经无效的局部变量是未定义性行为～

楼上说得对。代码稍微修改了一下。 #include<stdio.h>  void splitfloat(float x, int *intpart, float *fracpart) {     int count = 0;     while (x >= 1) {         count++;         x -= 1;     }     *intpart = count;     *fracpart = x; } int main(void) {     float x, fracpart1;     int intpart1;     printf("Enter a number: ");     scanf_s("%f", &x);     splitfloat(x, &intpart1, &fracpart1);     printf("intpart is %d, fracpart is %f\n", intpart1, fracpart1);     return 0; }

临时变量地址赋给了指针


Question: 指针数组做main函数参数的问题

argv相当于&argv[i]，要实现楼上结果，需要 printf（“%s\n”，*argv）;

也就是说系统调用的时候不会把argv的首地址传给main函数是吧，还是得在程序中定义一个指针指向argv的首地址对吧

需要分析一下argv的类型，类型是char *[];即指针数组，从楼主的用例上看，楼主的argv数组长度是5. 那么需要了解一下argv++;是偏移多少个字节，楼主想实现argv[0]->argv[1]->argv[2]。。。这样偏移吧，偏移的量是sizeof(argv[0]); 但是argv++;那就是偏移5 * sizeof(argv[0]);已经越界了。所以显示乱码是应为越界是未定义行为；   char *p = argv[0]; while (argc > 0) {     p++;     printf("%s\n", p); //这儿也不应该是argv呢，也应该是argv[0]orargv[i]呢     argc--; }       int i = 0;      while (i < argc) {         printf("%s\n", argv[i]);         i++;     } 供参考～


Question: Leetcode 5.最大回文，运行成功，但却提交错误

很抱歉，我经验不足，忘记贴上题目了，现在补一下。 空字符串确实没没考虑到，感谢指导，我去试试。

没考虑空字符串的情况。

你的第5题的需求在哪呢？那儿的第5题？


Question: 向CMD窗口发送CTRL+C（按下CTRL+C没有执行回调函数就退出了）？

谢谢回复。 我按下ctrl+c后，出现异常，如图, 这是怎么回事？

void main( void ) {  if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleHandler, TRUE ) )  {   printf( "\nThe Control Handler is installed.\n" );   printf( "\n -- Now try pressing Ctrl+C or Ctrl+Break, or" );   printf( "\n    try logging off or closing the console...\n" );   printf( "\n(...waiting in a loop for events...)\n\n" );    while( 1 ){ }  }  else   printf( "\nERROR: Could not set control handler"); } SetConsoleCtrlHandler的使用  换成上面这样就可以了。另外别在vs上面用debug调试，直接编译好，然后双击exe运行。


Question: linux下死锁实现问题

用两把锁交替使用就死锁了，很容易


Question: 关于奇偶链表的问题

如果你的链表是偶数个，那么在用q来判断的话，q指向倒数第二个的时候，p其实已经指向了倒数第一个，q指向倒数第二个它不是NULL，它的next也不是NULL，所以满足while的条件，这时候对p执行p->next=p->next->next,则出错

我说的有问题。。。。忽视

如果改成q!=NULL.... 那么你的代码逻辑错误 到了最后一个节点他依然不是空 q->next=q->next->next就会出错。。。因为q->next是NULL，

p和q一样吗？不一样


Question: C语言-单个字符转ASCII值输出问题

你已经输入了2次了   第一次是2  第二次是回车键 也就是换行 ascii值就是10

键盘输入2回车，变量a读到回车。 char a；后面加一句getchar（）；

引用 1 楼 user-2 的回复:读到了一个换行符 什么意思？说细一点，谢谢啦

读到了一个换行符


Question: 求助，scanf无效

i改变了，abc没有改变 可以参考这份代码: #include <stdio.h>  int main() {     int i = 0;     for (;;) {          scanf("%d", &i);         int a = i / 100;         int b = i % 100 / 10;         int c = i % 10;         getchar();         if (i == a * a * a + b * b * b + c * c * c) {             printf("%d是水仙花数\n", i);         }         else {             printf("%d不是水仙花数\n", i);         }     }     getchar();     return 0; }

在scanf前加一句rewind(stdin);


Question: 程序改错

//#include "stdio.h" #include <stdio.h>   int sort(char *p,int m ) {     int i;     char change , *p1, *p2;     for(i=0;i<=m/2;i++)     {         p1=p+i;         p2=p+(m-1-i);         change=*p1;         *p1=*p2;         *p2=change;     }      return 0; } //main( ) int main() {     int i,n;     char *p,num[20],temp;      printf("Enter n:");     scanf("%d",&n);     temp=getchar();     printf("Enter num[0] num[1] ... num[%d]:",n-1);     for (i=0;i<n;i++)         //scanf("%s",&num[i]);         scanf("%c", &num[i]);     p=num;     sort(p, n);     printf("Result is:\n");     for(i=0;i<n;i++)         //printf("%s ",num[i]);         printf("%c ",num[i]);     return 0; } 供参考～

引用 楼主 Fqxxh的回复:#include "stdio.h" int sort(char *p,int m ) {      int i;     char change , *p1, *p2;     for(i=0;i<=m/2;i++)    {          p1=p+i;         p2=p+(m-1-i);         change=*p1;         *p1=*p2;         *p2=change;    } } main( ) {     int i,n;     char *p,num[20],temp;     printf("Enter n:"); 	scanf("%d",&n);     temp=getchar();     printf("Enter num[0] num[1] ... num[%d]:",n-1);     for (i=0;i<n;i++)         scanf("%s",&num[i]);     p=num;     sort();     printf("Result is:\n");     for(i=0;i<n;i++)         printf("%s ",num[i]); } 学习一下调试技术

sort没传参


Question: 重定义为什么不报错

加上extern，那就不是定义了，而是声明。  如果全局变量不在文件的开头定义，有效的作用范围将只限于其定义处到文件结束。如果在定义点之前的函数想引用该全局变量，则应该在引用之前用关键字 extern 对该变量作“外部变量声明”，表示该变量是一个已经定义的外部变量。有了此声明，就可以从“声明”处起，合法地使用该外部变量

大佬牛啊！

你试一下这样的代码都不会报错 int bbb; int main(){   int bbb;   {     int bbb; } } 因为c++变量作用域在他最近的大括号下

这个extern不是没有生效吗？

作用域不一样，不是同一个变量，不会抱错

没必要纠结这些     这是编译器严谨的问题    有些编译器不会包容  有些则会     你这个只是重复声明    你在.h文件中将bbbb赋值自然会报错    当然 只能说你这个编译器不够严谨  包容了这个小问题

VS是extern了但是我在KEIL里还是定义

extern  没有生效

因为是extern了

.c 文件  #define	_RTC_APP_C_  #include "pch.h" #include <iostream>  int bbbb; //这里定义了    pch.h也定义了  为什么不报重定义  int main() {      	bbbb = 9999; 	std::cout << bbbb; 	system("pause"); }  .h文件 #ifndef PCH_H #define PCH_H #ifdef	_RTC_APP_C_ //在.c里定义 #define	_RTC_APP_E_ #else #define	_RTC_APP_E_	extern #endif //为什么这个不会报重定义错 _RTC_APP_E_  int bbbb;  #endif

重定义为什么不报错


Question: 在ARM上和DSP上做memcpy的速度问题

引用 3 楼 早打大打打核战争 的回复:总线带宽、内存频率考虑了吗  ARM DSP 在同一块芯片上，总线带宽和内存是一样的。 怀疑1 memcpy库针对arm有优化，但是对于DSP没有。        2 DSP 是dma 没有打开cache，无法cache预读取。

总线带宽、内存频率考虑了吗

你確定性能在同一級別？

会不会可能跟其他的硬件差异有关系，比如cpu，内存等等


Question: 求助  为何会出现这种情况  要咋搞得  急急急！！！

程序中最好不使用“fflush(stdin);”这样的函数调用。

嗯，，，，兄弟你倒是要问清楚到底是什么问题

代码发全吧，问题描述清楚一些吧～


Question: 关于使用pthread_detach后出现Segmentation fault的问题

#include <stdio.h> #include <unistd.h> #include <pthread.h>  void *mythread1(void *) {     int i;     pthread_detach(pthread_self());     for(i=0;i<10;i++)     {         printf("this is the 1 pthread,created by zhouzheng!\n");         sleep(1);     }     pthread_exit(NULL); }  void *mythread2(void *) {     int i;     pthread_detach(pthread_self());     for(i=0;i<10;i++)     {         printf("this is the 2 pthread,created by zhouzheng!\n");         sleep(1);     }     pthread_exit(NULL); }  int main() {     int i=0;     int ret =0;     pthread_t id1,id2;     //ret = pthread_create(&id1,NULL,(void*)mythread1,NULL);     ret = pthread_create(&id1,NULL,mythread1,NULL);     if(ret) {         printf("Create pthread error!\n");         return 1;     }     //ret = pthread_create(&id2, NULL, (void*)mythread2,NULL);     ret = pthread_create(&id2, NULL, mythread2,NULL);     if(ret) {         printf("Create pthread error!\n");         return 1;     }     // pthread_join(id1,NULL);     // pthread_join(id2,NULL);     for(;;)     {         printf("this is main pthread\n");         sleep(1);     }     printf("Programme is end!\n");     return 0; }  供参考～  用这个代码试试

把detach放到main里面


Question: C语言读写文件

感谢，数组长度不对

为什么两次输出的d[i]会不一样呢？

1、d数组长度为nb_input，而循环中使用值为nb_output，请核实是否两个数值相同。 2、数组未初始化，不能直接输出结果，请留意是否有初始化语句。


Question: 关于LeetCode相交链表的问题

代码有逻辑问题， 例如：两个链表都有5个元素 a的第三个元素和b的第四个元素相交； 你的循环从头开始，每次移动一个，那么他们两个永远不会相比较，因为每次都是1节点和1节点比，2和2，3和3

这个代码太不科学了，得遍历多少次才能找到啊


Question: VScode下配置C环境问题

我的VScode-c文件夹是在C里 mingw64跟vscode程序是在D盘

最后多了个&


Question: 菜鸟求助大神关于按键双击长按编译

顶一下，有大神指点吗


Question: LeetCode上好多题都不会咋整啊

加油

刚开始照着敲就好了，开始有思路就行，后面在慢慢自己写，然后对比差距和思路，写多了，就好了

复习好基础知识，从easy题开始做。

题和书本差距挺大的

努力的不够，写的不够，基础不够夯实。所以，努力吧～


Question: 链表删除尾节点

学习了一下，发现确实是O（n）。有个人回答的非常有理。  🤔确实单循环链表删除队尾元素都是O（n），因为均需要找到队尾的前驱结点，而找到队尾前驱结点一步是做不到的，均需要遍历。🤔另外好像有一个容易混淆的地方。就是仅设置头指针的循环单链表，查找表尾结点是O（1），删除表尾结点是O（n）。（删除需要找前驱并改变其next域指向，而查找不需要找前驱）

引用 4 楼 自信男孩 的回复:[quote=引用 3 楼 user-3 的回复:]因为删除以后，还要把被删除节点的上一个节点执行被删除节点的下一个节点，不能直接删除。必须遍历，因为是单循环 有理～[/quote] 比较有道理

引用 3 楼 user-3 的回复:因为删除以后，还要把被删除节点的上一个节点执行被删除节点的下一个节点，不能直接删除。必须遍历，因为是单循环 有理～

知道头，知道尾，并且是一个循环链表，那么删除尾节点不很好处理吗？直接删除不就好了吗？还需要循环遍历一次链表吗？  引用 1 楼 user-3 的回复:单循环应该都是N，因为删除任意一个都要遍历

单循环应该都是N，因为删除任意一个都要遍历


Question: 小学生数学测验

读写文件参考这个 https://blog.csdn.net/zhanghaiyang9999/article/details/107032563


Question: 链表

楼主的问题好像从上面的代码看不出来什么。m是指向初始的链表，p已经是指向了下一个节点了。如果不是这个原因，那么楼主需要提供更多的代码～

因为z 和 p 指向同一地址

引用 1 楼 user-3的回复:因为p=p->next 哦，那为啥p里面没有1呢

因为p=p->next


Question: python pdfminer读取pdf文件时出现WARNING:root错误

把PDF另存一下能解决部分问题...

嗯嗯 谢谢回答 但是加了r之后还是显示相同的错误，现在的运行的路径为： read_from_pdf(r'G:\대학원\MD&A\年报\东方航空：2017年年度报告.PDF') 依然出现如图所示的错误，请问还有什么解决方法吗 谢谢指导。具体的错误代码我在网上也没有到，也不知道是什么问题

路径前面加一个r


Question: python pdfminer读取pdf文件时出现WARNING:root错误

希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10581430.html 希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10768339.html

楼主问题解决了吗 ？？我也遇到同样问题


Question: 函数中return这个函数

当编译器检测到一个函数调用是尾递归的时候，它就覆盖当前的活动记录而不是在栈中去创建一个新的。编译器可以做到这点，因为递归调用是当前活跃期内最后一条待执行的语句，于是当这个调用返回时栈帧中并没有其他事情可做，因此也就没有保存栈帧的必要了。通过覆盖当前的栈帧而不是在其之上重新添加一个，这样所使用的栈空间就大大缩减了，这使得实际的运行效率会变得更高。 ----百度百科

引用 楼主 九月qkq92 的回复:谁能帮忙解释一下 下面这段代码的逻辑。谢谢  #include <stdio.h>  int fun(int n, int m) {     if (n == 0 || m == 0)     // 递归出口         return 1;     else         return fun(n - 1, m) + fun(n, m - 1);  // 两次调用递归函数fun } 上面的程序有点像是“阿克曼函数”的递归实现，但还是有区别的。不知道原题的是什么。 阿克曼函数是二元函数，其定义式为： （１）ACK(0, N)＝1＋Ｎ （２）ACK(M,0)＝ ACK(M-1, 1)（Ｍ>０） （３）ACK(M, N) ＝ ACK(M-1，ACK(M, N-1)) （Ｍ>0, Ｎ>０）

还是个尾递归，避免堆栈上溢

如果n等于0或m等于0，那么返回1；否则递归调用自己

百度一下递归


Question: 求大佬指点错误，文件输出空白

void Read_File(list_single * head_Node,char * File_Name) {     FILE *fp;     struct student data;      //错误在这儿，File_Name加了双引号    // fp = fopen("File_Name","r");      fp = fopen(File_Name,"r");     if(fp ==  NULL)     {         printf("error:打开文件失败");         exit(0);     }     while(fscanf(fp,"%s\t%s\t%s\t%f\n",&data.num,&data.name,&data.sex,&data.math) != EOF)     {         insert_Node_by_Head(head_Node,data);//结点插入链表     }     fclose(fp); }

读写文件参考这个 我用#CSDN#这个app发现了有技术含量的博客，小伙伴们求同去《C语言文件读写（1）-文本文件读操作》, 一起来围观吧 https://blog.csdn.net/zhanghaiyang9999/article/details/107032563?utm_source=app


Question: 求助一道oj题目

已经解决了

没有OJ地址吗？

我反复阅读上面的文字，总感觉是自己语文水平不行，搞不太清楚题目到底是什么意思，特别是那个 Q。


Question: 一道C语言的数组题

你是用int类型的n来储存的二进制数。你相当于干了这么一件事。int n=1000亿；这早就超过了int所能储存的数据大小。当然会出错了。你这数据太大一定出错，不然我就是活久见了，哈哈。上然仁兄说的对，建议你把二进制数当作字符串处理，统计出字符串长度，就很好做了。

将输入当做整数，应该当成字符串进行处理，可以将其读入一个字符数组中存储。

上面是非递归解，下面是递归解 #include <stdio.h> int btod(int d) { 	if(d<2) 		return d; 	else 		return btod(d/10)*2+d%10; } int main() { 	int sum,n; 	scanf("%d",&n); 	sum=btod(n); 	printf("%d",sum); 	return 0; }

#include <stdio.h> int main() { 	int i,sum,a[16]={0}; 	long n; 	scanf("%ld",&n); 	i=0; 	while(n!=0) 	{ 		a[i]=n%10; 		n=n/10; 		i++; 	} 	sum=0; 	for(;i>=0;--i) 		sum=sum*2+a[i]; 	printf("%d",sum); 	return 0; }

输入一个二进制数串，当作字符串处理，而不是整数


Question: 新人求助帖

在你的代码上做了些修改，供参考  #include <stdio.h> #include <string.h>  int main() {     char ch[8] = {0};      printf("Input your age\n");     scanf("%s",ch);     int i = 0;     while (ch[i] != '\0')     {         if (ch[i] >= '0' && ch[i] <= '9')         {             i++;         }         else         {             printf("error\n");             printf("Please input your age again\n");             return 0;         }     }      printf("correct\n");     printf("your age is %s",ch);      return 0; }

while循环

可用ascii表判断是否为数字，再将字符转为数字

不能用char，这只能接收一个字符，用int来接收，然后一个循环就好


Question: Linux服务器C语言SMTP发送邮件，邮件内容缺失

如果服务端设置了sotimeout那就要看你手速了，哈哈哈

以前我还cmd控制台telnet 发过邮件。按照smtp协议手工输入代码。


Question: C语言，简单成绩管理系统 帮帮忙看看我哪里错了

float ave( float a[N], int num) { int i; float sum,aver; for(i=0;i<num;i++) sum+=a[i]; aver=sum/num; return aver; }  这里sum要初始化，float sum = 0;

报错信息是啥？


Question: 句柄怎么增加的?

多线程当然要用锁

引用 1 楼 user-1 的回复:句柄4被释放后，马上就会放到空闲队列首部，下次使用一般就会用到了。 句柄是一个long型 嗯  在多线程中句柄 应该是不安全的,一个线程持有  一个线程释放,持有的句柄 理论上是个无效句柄,但是也有可能是下次申请到的


Question: 求大佬指导哪里报错了 C语言

引用 3 楼 Clancey P.M.R.S. Yu 的回复：你定义yi的位置不对，把char yi;搁在最前边（do之前）应该就行了谢谢已经解决了

你定义yi的位置不对，把char yi;搁在最前边（do之前）应该就行了

while循环中yi没有定义啊，把yi的定义放到do前面

--------------------Configuration: 1 - Win32 Debug-------------------- Compiling... 1.cpp E:\C语言\89 一元二次方程\1.cpp(42) : error C2065: 'yi' : undeclared identifier 执行 cl.exe 时出错.  1.exe - 1 error(s), 0 warning(s)     这是报错原因


Question: 求助，输入数字并过滤其中的符号和字母

一个一个检查，如果不是数字和小数点就忽略

感谢各位，我试一下，不会回复楼层

#include <stdio.h> #include <ctype.h> #include <string.h>  #define MAX_INPUT_SIZE  128  char *del_char(char *str);  int main(void) {      char input[MAX_INPUT_SIZE];     float num;      fgets(input, MAX_INPUT_SIZE, stdin);      del_char(input);     puts(input);     sscanf(input, "%f", &num);       printf("%f\n", num);     return 0; }  char *del_char(char *str) {     char *tmp, *back_str;      tmp = back_str = str;     while (*str) {         if (isdigit(*str) || *str == '.')             *tmp++ = *str;         str++;     }     *tmp = 0;      return back_str; } 供参考～  一个一个输入，多个可以考虑加循环

没有配套的代码,但可以给你一个类似的参考代码,只需要在此基础上做些修改就可以了. 如果你还想了解其他的一些常见类型题,可以查看一下这篇文章https://blog.csdn.net/HYNN12/article/details/102610626,希望对你有所帮助.   #include <stdio.h> int main(int argc, const char * argv[]) {     int num_digital = 0;     int num_char = 0;     int num_space = 0;     int i;     char c[100] = "faj f afhka123";     //gets(c);     for (i=0; i<100; i++) {         if (c[i] == ' ') {             num_space ++;         }         if ((c[i] >= 'A' && c[i] <= 'Z')|| (c[i] >= 'a' && c[i] <= 'z')) {             num_char ++;         }         if (c[i] >= '0' && c[i] <= '9') {             num_digital ++;         }     }     printf("数字个数是%d\n字母个数是%d\n空格个数是%d\n",num_digital,num_char,num_space); return 0; } ———————————————— 版权声明：本文为CSDN博主「知之、行之、思之」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。 原文链接：https://blog.csdn.net/HYNN12/article/details/102610626