Question: C语言 检验身份证校正码

楼主当做整数运算还有一个问题 for(i=0;i<18;i++) {    arr[i]=ID%10;    ID=ID/10; }  这里得到的数是从低位向高位进行的, arr[0]就是身份证的第18位， arr[17]才是第一位 而用来和他做乘法的那个数组顺序和他恰好是相反的，是从高位到低位的顺序 所以后面的 for(i=0;i<17;i++)      sum+=arr[i]*a[i]; 这样写也是错误的。     用lld整数可以解决，但是方法上有不同  #include <stdio.h> #include<stdio.h>  // id是17位数， ch是最有一位校验码字符 // 如果合法返回0， 错误号码返回1 int  exam(long long id, char ch ) {     int  sum=0;     int  arr[18];     int  a[]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};     char b[]={'1','0','x','9','8','7','6','5','4','3','2'};     int  i;     long long ID = id;     for(i=0;i<17;i++)     {         arr[i] = ID%10;         ID     = ID/10;     }     for(i=0;i<17;i++)         sum += arr[16-i]*a[i];     sum%=11;     char temp=b[sum];     if( temp != ch) {         printf("%lld%c : %c\n", id, ch, temp);         return 1;     } else         return 0;  } int main() {     long long ID;     int n,i,flag=0;     scanf("%d",&n);     for(i=1;i<=n;i++)     {         char ch;         //指定整数的位数，最后一个当做字符输入         while ( 2!=scanf("%17lld%c", &ID, &ch)) {             fflush(stdin);             printf("输入错误\n\                    身份证号码必须是18位，只有最后一位可以是字母而且只能是x!\n\                    请重新输入:\n");         }         flag += exam(ID, ch);     }     if(0==flag)         printf("All passed");     return 0; }

可以简单一些：  #include <stdio.h>  int main() {   const char v[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};   const char *m = "10X98765432";    char s[19];   int n, i, c, x, p = 0;    scanf("%d", &n);   while (n--)   {     scanf("%s", s);     for (i = c = 0; x = s[i] - 48, i < 17; i++)       x >= 0 && x < 10 ? c += x * v[i] : i = 19;     i == 19 || s[17] != m[c % 11] ? p = puts(s) : 0;   }   if (!p) puts("All passed");    return 0; }

个人觉得你的思路是有些问题的，最后一个可能是X，longlong是不能存的 #include<stdio.h> #include<string.h> int dis[]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; char m[]={'1','0','X','9','8','7','6','5','4','3','2'}; char mp[100][19]; int main(){     int n,num=0,i,j,k,ans=0;     char id[19];     scanf("%d",&n);     for(i=0;i<n;i++){         int sum=0;         scanf("%s",id);         for(j=0;j<17;j++){             sum+=(id[j]-'0')*dis[j];         }         sum%=11;         if(m[sum]==id[17]){             num++;         }         else{             strcpy(mp[ans++],id);         }     }     if(num==n){         printf("All passed\n");     }     else{         for(i=0;i<ans;i++){             puts(mp[i]);         }     }     return 0; }

而且，这个身份证号码，如果尾巴是X，你这个scanf怎么也读不进来x字符啊 用字符串作为输入类型，读入进来再转换

你把exam都代码再放回main里面去吧  然后 下面这两个i++只可以保留一个 for(i=0;i<18;i++) { arr[i++]=ID%10; ID=ID/10; }


Question: 求大佬解答 c语言链表姓名排序问题 没有进行循环

#include <stdio.h> #include <string> #include <ctime>  typedef struct People {     char name[20];     char id[20];     struct People * next; } People;  People * create(int n) {     if ( n<1 ) return NULL;     int i; int v;     v = rand() % 1000;     People * pHead = (People*) malloc( sizeof(People));     sprintf(pHead->name, "name-%03d", v);     sprintf(pHead->id, "id-%03d", v);     People * p = pHead;     for ( i=1; i<n; i++) {         p->next = (People*) malloc( sizeof(People));         v = rand() % 1000;         sprintf(p->next->name, "name-%d", v);         sprintf(p->next->id, "id-%03d", v);         p = p->next;     }     p->next = NULL;     return pHead; };  void printList(People * pHead) {     printf("\n--------- People List ---------\n");     if ( pHead == NULL) return;     People * p = pHead;     while ( p ) {         printf("%s : %s\n", p->name, p->id);         p = p->next;     } }  People * sortList(People * pHead) {     if ( NULL == pHead || pHead->next == NULL ) return pHead;     People * pTH = (People*) malloc( sizeof(People));     pTH->next = pHead;     People * pTail = NULL;     while ( pTH->next->next != pTail ) {         People * pPrior = pTH;         People * pCur   = pTH->next;         People * pNext  = pCur->next;         do  {             if ( strcmp ( pCur->name, pNext->name)>0) {                 pCur->next   = pNext->next;                 pNext->next  = pCur;                 pPrior->next = pNext;                 People * pT = pNext;                 pNext = pCur;                 pCur = pT;             }             pNext  = pNext->next;             pCur   = pCur->next;             pPrior = pPrior->next;         } while( pNext!=pTail);         pTail = pCur;     }     pHead =pTH->next;     free(pTH);     return pHead; }; int main() {     srand(time(NULL));     People * p = create(10);     printList(p);     p = sortList(p);     printList(p);     return 0; }


Question: 大佬们求助，小弟初学C语言，有问题求助

你的第二个程序B似乎没有定义，B应该定义为double类型，输出的时候把%d改成%lf。 第一个程序输入函数scanf中\n去掉。就像程序2就好了。第一个程序的输出也要用%lf


Question: C语言姓名排序后无法输出，求解

按照你自己的思路去改吧。  这样对你自己有好处。 哪怕有问题，哪怕方法麻烦， 走通了，你就进了一大步了  sort要想改好， head节点也是要参与排序的， 而且改了之后，头结点不是它需要返回，那么函数的原型就要是 struct people * sort（struct people * head）；  调用的时候是：  head = sort(head);    用返回值更新调用它的head  要交换指针，你实际上需要三个东西 上一个节点  当前节点  下一个节点 交换的是当前和下一个节点， 但是交换后的结果，需要更改上一个节点的next指针 proir  -->  cur --> next --> more  交换前 proir --> next --> cur --> more    交换后  ptail是控制循环范围的， 第一次排序从头到结尾的 第二次控制，从头到倒数第二个 第三次控制，从头到倒数第三个 .... 因为后面都是排序好的 通过控制 while( tail  == head->next ) 来判断全部排序结束  这仅仅是一种办法。代码会比较麻烦。 但是如果节点数据结构复杂度话， 这个方法效率会很高，比交换数据要高。

那应该怎么改呢

他这个问题不光是复杂的问题，整体上有一堆问题， 没想好从头到尾帮着改呢，还是只给sort的建议  这个sort本来就是一个没有完成的代码，麻烦不仅仅在交换的复杂上， 还在整个交换流程的控制上 比如，head不是空头， 是有效数据，那么头也应该参与交换的， 但是它没法交换，即便交换了也返回不去 有了tail指针，本来是用来控制类似冒泡的排序过程，执行到哪儿的， 也没有利用上   前面的save函数，也只保存当前一个节点， 整个链表只是重复的输出一个节点 输入的时候， 尾巴会多一个一个没有意义的空节点  总之各种问题，整个代码的大体流程是通顺的，可那个细节上好多问题， 都不知道如何给建议了

建议排序用交换数据部分，交换指针部分比较复杂和难处理呢


Question: 求助大神

引用 3 楼 自信男孩 的回复:[quote=引用 1 楼 focuslight 的回复:] 第十行 scanf("%d, &num);  少了一个"  好眼力～[/quote]  有这个眼神的绝对不是老鸟， 老鸟都老眼昏花了

引用 1 楼 focuslight 的回复:第十行 scanf("%d, &num);  少了一个"  好眼力～

还有你的main()写成 int main()

第十行 scanf("%d, &num);  少了一个"


Question: 删除链表中重复结点和删除数值相同的结点有区别吗？

引用 3 楼 qq_43731685 的回复:那么链表中判断结点相同是根据结点的数值还是结点指向方向？ 通常来说是指节点的数据内容（也就是你说的数值），一般节点的指向不会同时指向一个，因为节点的指向通常是下一个节点，每一个节点的下一个节点不一样。

引用 2 楼 qybao 的回复:有区别啊，一个是数组，内存是连续的，删除时要移动删除位置之后的元素，也就是吧被删除的位置的空缺补回来；一个是链表，内存空间不一定连续，删除时不用移动删除节点后面的元素，只需要把指针指向下一个节点就可以。这也是算法的不同点。 那么链表中判断结点相同是根据结点的数值还是结点指向方向？

左手一个100块 右手一个100块 和双手捧着一个100块，很明显不一样


Question: 加油 (ง •̀o•́)ง (ง •̀o•́)ง

对，加油，自己先试试去实现～加油～


Question: 请问这一步错在哪里

我的建议是先把c语言的基本语法学好。 c语言的语法其实很简单，关键词不过5，6十个，背一周差不多也背下来了

你的解法是数学思维，现在的电脑还不能如此智能。 编程语言必须一步一步明确告诉电脑要做什么。 是你告诉电脑，怎么把这道题解出来了。 而不是你列了一个公式，电脑就知道你想干什么了，也许以后的电脑可以。

数学表达式和编程语言的差异建议温习一下，编程有自己的规则，需要再温习一下～

那你不要if就好了

引用 3 楼 user-4的回复:表达式=0，这是神马？把a*x^2+b*x+c=0这行去掉  for example 对于非法输入，LZ自己去处理吧  float a, b, c, d; scanf("%f%f%f", &a,&b,&c); d = b*b - 4*a*c; if (d==0.0) {     printf("x1=x2=%f\n", -b/(2*a)); } else {     printf("x1=%f,x2=%f\n", (-b+sqrt(d))/(2*a), (-b-sqrt(d))/(2*a)); }  谢谢～这个地方题目不是说只考虑两个解的吗


Question: 运行出现ddddddddd不出现数字

void sort(int *a,int n) {     int i,j,max,temp;      for(i=0;i<n-1;i++)     {         max = i;         //for(j = i;j<n;j++)         for(j = i+1; j < n; j++)             if(a[j] > a[max])                 max = j;//把a[i]和a[max]换         if (max != i) {    //需要加一个条件             temp=a[i];             a[i]=a[max];             a[max]=temp;         }     } } 冒泡排序的写法。  供参考～

引用 1 楼 ?Victor.??的回复:d% 这是什么东西  啊 谢谢啊～ 输错了没看出来

d% 这是什么东西


Question: 求详细解答

如果没有C，D选项的话，没有答案。答案应该是1.  原因是参数是值传递。func中的s和main中的s是相互独立的两个指针。func中 对s的操作不影响main中的s。

引用 7 楼 冷风1023 的回复：结果是a[0]的值啊也就是1. 原因在于s=(int *)malloc(sizeof(int));这行给s赋值的新的地址，所以fun函数就没有起到任何作用。嗯嗯，我明白啦

引用 6 楼 真相重于对错 的回复：引用 4 楼 m0_46236484 的回复:[quote=引用 3 楼 真相重于对错 的回复：]传入指针到函数，函数内改变指针，函数结束后，指针不变。但是函数内部改变指针指向的地址，函数结束后那个地址的内容会改变。是函数的地址吗？还是s的地址 跟函数地址有什么关系？  比如 void test(int a){  a=10; } 那么你这么调用 int x=20; test(x); //这里x还是20；不会是10； 指针也是一样，指针其实就是地址，地址就是一个数。表示的内存的某个区域。 所以在函数里改变指针，对外部一点影响也没有，除非改变那个地址的内存区域的内容。[/quote]我不太懂这题咋分析

引用 4 楼 m0_46236484 的回复:引用 3 楼 真相重于对错 的回复：传入指针到函数，函数内改变指针，函数结束后，指针不变。但是函数内部改变指针指向的地址，函数结束后那个地址的内容会改变。是函数的地址吗？还是s的地址 跟函数地址有什么关系？  比如 void test(int a){  a=10; } 那么你这么调用 int x=20; test(x); //这里x还是20；不会是10； 指针也是一样，指针其实就是地址，地址就是一个数。表示的内存的某个区域。 所以在函数里改变指针，对外部一点影响也没有，除非改变那个地址的内存区域的内容。

函数里那个s用malloc重新搞出来的，所以之后操作的不是开始传进来的s

引用 1 楼 真相重于对错 的回复：A,B肯定都不对，还有答案吗？1是答案 我不明白为什么数组名作为函数参数，执行函数后，为什么s的值没有变？难道是没有return s嘛？

A,B肯定都不对，还有答案吗？


Question: 指针与数组

char *p= &str[7]; 指针从这里开始，所以前面的没变

if( *p>='a' && *p<'z' ) (*p)++; (*p)++这是先取引用，然后把引用的值+1。  这两条语句就是让's'变成't'，'t'变成'u'， 'u'变成'v'， 然后 else if( *p == 'z' ) *p = 'a'; 这两条语句就是让'z'变成'a'；   建议楼主还是看明白代码，代码也不复杂，不难分析。主要的就是4条语句。

建议学会调试


Question: str[0] = "g"; 请问结果为什么输出@呢？

"g"是字符串。 字符串在C语言中，其本质是地址（特殊的）。虽说是（特殊的）地址，但确确实实就是地址  不太好给你解释  不妨试一试在打印下一行再加一句： printf("%c\n", str); //也许会有些变化。

str[0] = "g";  这句相当于把地址给了str[0];因为"g"是字符串，如果改成'g'，就可以输出g了。

str[0] = "g"; ----》 g是单个字符，应该用 单引号 'g'。


Question: 啥区别

引用 2 楼 自信男孩的回复:这个没有合适之说吧，if和while都是基本的语言语句，根据需要来使用。 好的，我知道了

这个没有合适之说吧，if和while都是基本的语言语句，根据需要来使用。

if 是判断， while 是循环。

两个都是c语言基本语句


Question: 求助C语言

每一行是一个结构体， 许多行是结构体数组。

赶紧写吧 做出来共享一下， 我们就不用都买excel了， 都用你的， 功德无量啊

真的要实现在表格中输入一个数值，然后求和，挺难的。因为C是控制台的，这个得需要图形编程。以windows为例，需要建立这样N*M个子窗口或控件，然后对每一列或行求和。


Question: 有大神能给帮我讲下这串Dijkstra算法代码吗

引用 3 楼 proorck2019的回复:①情景描述 ②算法简介 ③代码实现 ④测试通过 就是要实现输入起点和终点，找最短路径啊

引用 1 楼 寻开心的回复:你能不看代码，描述清楚Dijkstra算法是怎么工作的吗 如果能，代码就能看 如果不能， 解释也白费  这个要现有理论基础的 其实单源的我懂，这个我不太懂后面这块 dist[j] = dist[k] + G->arcs[k][j];                     t = 1;                     while(path[k][t] != 0) {                         path[j][t] = path[k][t];                         t++;                     }                     path[j][t] = k;                     path[j][t+1] = 0; 不知道t是干嘛的

①情景描述 ②算法简介 ③代码实现 ④测试通过

好的 我再仔细的理解下这个算法


Question: 为什么换了一下顺序就不行啊

注意逗号是英文的才行，输入中文逗号，根据逗号占用的字符不一样（中文和英文）所以会出现你说的这个问题～

别瞎说！ scanf输入多个数字都时候， 输入12，之后别说中间一个空格，你放100个空格也不影响， 甚至敲上八行回车再输入45也不影响正确的输入 空格，tab和回车都会被scanf自动过滤掉的  int main(){     int a, b, n;     n =scanf("%d,%d", &a, &b);     printf("n:%d, a:%d b:%d\n",n, a, b); // 马上输出你获得到a和b的值，以及scanf正确从键盘获取到有效值得个数n     。。。。

手误空格问题。其实如果对于这种情况有疑问，可以试试Debug，我的编译器是Dev-C++，就是点击一个“√”号来Debug的，Visual应该也没啥区别

楼上说的正解，加了空格，实际没读取到45这个值，相当于b没有被赋值，所以出现了随机大数

你第二次输入，除了, 号还加了空格， 就出问题了， 输入要和scanf设定的格式完全一致

scanf后，你跟一句printf，把a和b输出出来，看看是不是你输入的那两个值 为避免这个问题 scanf("%d%d", &a, &b); 中间不要逗号，输入的时候也12 45 这样，数字之间用空格分开

你第二次输入的逗号是中文的吧


Question: 数组名在内存中到底是个什么？

汇编里没有变量名这个概念

数组名在内存里就是一段内存的首地址，数组不能做左值。 定义一个数组，内存就会分配一段内存，而首地址就是用数组名标识的。 就是用数组名能找到申请的这块地址

a不是地址常量 也不相当于地址常量  a表示的是数组占用的内存块 数组占用的内存不会变 a也不会变

示意图画错了 不存在一个 a存储一块内存的地址 a本身表示一块每次

数组确实也是一种数据类型，但是数组算是二等公民，作为函数参数传递时会退化成地址，还不能作为函数的返回值。数组名其实是一个符号，编译后存在符号表中，是定死的不能被改变

这么理解 char a[]="hello"; char *b=a; 显然a不能用于左值，但是可以用于右值。

a相当于数组首地址的常量引用，所以改不了 b是变量，内存信息可以改（内存信息也是个地址，是数组的首地址）

引用 2 楼 真相重于对错 的回复:a 在栈里啊，b不过是指向栈内数据的一个指针。 建议，真要了解这一切，最好把汇编了解一下。 谢谢！有空时会详细看汇编的。

引用 1 楼 寻开心 的回复:a就是数组， b就是指针 两个不同的变量啊  他们的地址都不可以改，他们的值都可以改（const的例外）这个能理解吧 数组有个特殊的地方， 他的名字和他的地址，是同一个东西， 你printf 指定%p， 传参a和&a，结果都一样 它就是特殊， 不能改！！！  b的地址你同样也改不了，改的就是b的值，以及指向的内容 可以b到值你能改，&b 和 b他就不是一个东西， 你printf一下就看到了  好像明白了。  数组名a不是个指针常量，它直接就是数组这种类型的变量。  至于a == &a ,可能是编译器内部自己把a翻译成&a对待了。


Question: c语言中常量在内存中是怎样的？

谢谢！谢谢！谢谢！谢谢！

const 类型限定符   C C 语言 声明  C 类型系统中每一个独立的类型在都有数个该类型的限定版本，对应 const 、 volatile及对于指向对象指针的 restrict 限定符中的一个、两个或全部三个。此页面描述 const 限定符的效果。  编译器可以把声明带 const 限定类型的对象放到只读内存中，而且若程序决不取该 const 对象的地址，则可能完全不存储它。  const 语义仅应用到左值表达式；只要在不要求左值的语境中使用 const 左值表达式，就会丢失其 const 限定符（注意不丢失 volatile 限定符，若它存在）。  指代 const 限定类型对象的左值表达式，和指代拥有至少一个 const 限定类型成员（包含为聚合体或联合体所递归含有的成员）的结构体或联合体的左值表达式，不是可修改左值。具体而言，它们不可赋值：  const int n = 1; // const 类型对象 n = 2; // 错误： n 的类型为 const 限定   int x = 2; // 无限定类型对下 const int* p = &x; *p = 3; // 错误：左值 *p 的类型为 const 限定   struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2}; s1 = s2; // 错误： s1 的类型无限定，但它有 const 成员 const 限定的结构体或联合体类型的成员，取得它所属类型的限定版本（在用 . 运算符或 -> 运算符访问时）。  struct s { int i; const int ci; } s; // s.i 的类型为 int ， s.ci 的类型为 const int const struct s cs; // cs.i 和 cs.ci 的类型都是 const int 若以 const 类型限定符声明数组类型（通过使用 typedef ），则数组类型无 const 限定，但其元素类型有。若以 const 类型限定符声明函数类型（通过使用 typedef ），则行为未定义。  typedef int A[2][3]; const A a = {{4, 5, 6}, {7, 8, 9}}; // const int 的数组的数组 int* pi = a[0]; // 错误： a[0] 拥有 const int* 类型 const 限定的复合字面量不必指代相异的对象；能与恰好拥有重叠表示的其他复合字面量和字符串字面量一同存储它们。  const int* p1 = (const int[]){1, 2, 3}; const int* p2 = (const int[]){2, 3, 4}; // p2 的值可等于 p1+1 _Bool b = "foobar" + 3 == (const char[]){"bar"}; // b 的值可为 1 (C99 起) 指向非 const 类型的指针能隐式转换成指向同一或兼容类型的 const 限定版本的指针。能用转型表达式进行逆向转换。  int* p = 0; const int* cp = p; // OK ：添加限定符（ int 到 const int ） p = cp; // 错误：舍弃限定符（ const int 到 int ） p = (int*)cp; // OK ：转型 注意指向指向 T 指针的指针不可转换为指向指向 const T 指针的指针；对于要兼容的二个类型，其限定必须等同。  char *p = 0; const char **cpp = &p; // 错误： char* 与 const char* 不是兼容类型 char * const *pcp = &p; // OK ：添加限定符（ char * 到 char *const ） 任何修改有 const 限定类型的对象的尝试导致未定义行为。  const int n = 1; // const 限定类型对象 int* p = (int*)&n; *p = 2; // 未定义行为 函数声明中，关键词 const 可出现在用于声明数组类型函数参数的方括号内。它限定数组类型变换到的指针类型。  下列二个声明声明同一函数：  void f(double x[const], const double y[const]); void f(double * const x, const double * const y); (C99 起) 关键词 const  注意 C 从 C++ 接纳了 const 限定符，但不同于 C++ 中， C 中 const 限定类型的表达式不是常量表达式；它们不可用作 case 标号，或用于初始化静态和线程存储期对象、用作枚举项或位域大小。以之为数组大小是，产生的数组为 VLA 。  引用 C11 standard (ISO/IEC 9899:2011): 6.7.3 Type qualifiers (p: 121-123) C99 standard (ISO/IEC 9899:1999): 6.7.3 Type qualifiers (p: 108-110) C89/C90 standard (ISO/IEC 9899:1990): 3.5.3 Type qualifiers 参阅 cv （ const 与 volatile ）类型限定符 的 C++ 文

引用 10 楼 m0_46108109 的回复:[quote=引用 8 楼 寻开心 的回复:]  是不是意味着程序有个最小大小。只有一行的代码，也要占用那么大区域？[/quote]  程序最小代码可以不用， 早期的com文件，可以只占据几个字节 那个图，只是展示了内存管理的方式。 不是意味着所有的区域都要有数据。 何况那个地址并不是真实的物理地址呢，是映射出来的  更多的你要去了解windows或者其他操作系统的内存管理方式了

跟const没关系，这是常数的意思。

引用 8 楼 寻开心 的回复: 是不是意味着程序有个最小大小。只有一行的代码，也要占用那么大区域？

主要看这个变量在哪里定义，如果在函数外，那么该变量存放在数据段，如果在函数内定义，这个变量存放在栈上。

int global; int main() { int local; int *pHeap = (int*) malloc( sizeof(int)); printf("Global:%p. Local/Stack:%p Head:%p\n", &global, &local, pHeap); 这三个指针就明确的帮你定位了， 你看一下他们的指针值就能显著的看出区别 return 0; }

在结构当中定义的LENGTH是结构的一个成员， 结构本身在堆了面，这个成员变量也在堆里面 其实这是个假的const， 通过强制类型转换，你还是可以改掉它的值的 只有分配在只读区域的那些const才是真的改不了的const 你定义的这种const，只是告诉编译器遇到对它的直接修改不允许，强制转换就是绕过它了

引用 4 楼 寻开心 的回复:你可以自己做测试的 取得它的地址，printf用%p，输出它的地址， 看看就能知道了  自己再定义几个不同的变量， 全局的，局部的，动态的， 然后也都取地址，比较一下指针就看到它在哪一个区域了  地址怎么分辨区域？

是的， 它是在堆当中了。

引用 1 楼 寻开心 的回复:不一定， 还是看它是全局变量还是局部变量 局部变量还是在栈里面的 全局变量是在数据区，也不是栈，也不是堆  typedef  struct book { 	const int  LENGTH = 10;  }Book;  Book * book1 = (Book*)malloc(sizeof(Book));      book1中的LENGTH 是不是就在堆中了？


Question: 菜鸟请教，下面C代码什么意思？

宏定义，36u，这儿的u是指unsigned，即无符号数；

C语言不支持下划线 像123_i128这样的看起来就舒服了

你看看常量定义， 字面量 float类型的常量       1.0f double类型的常量   1.0lf，  long类型的常量       1L，   嘿嘿， 自己猜36u，u表示啥

引用 1 楼 寻开心的回复:#define 就是个替换 后面的代码，看到 ANTCDATALEN 都换成(36u)就对了  const int32_t i32TempVir[ANTCDATALEN][AVIRDATALEN] = 就是 const int32_t i32TempVir[(36u)][(71u)] = ..... 36u, 71u 是什么？


Question: 求助，麻烦帮我看一下哪里错了

int ReadScore(int income[], long num[])  {    int I = 0;             do{          i++;         printf("Input person's ID and income:");          scanf("%d%ld", &num[i], &income[i]);    }   while( I<N && num[i]>0 /*&& ReadScore[i] >= 0*/);    // ReadScore[I] 没有这个数组， 不知道你要表达什么    return i;          // 这个I还是有可能是N的情况从while退出，那么返回这个i也不应该。 还是有潜在的风险的 }  int LinSearch(long num[], long x, int n)  { int  i;   for (i=0; i<=n; i++)                  {	 if (num[i] ==  x)  return (i);  } return (-1);                            }

而且数组ReadScore[i]你都没有定义，应该是income[i]打错了吧 还有下面一个函数num[i]=x是什么神仙

ReadScore里面i没有初始化


Question: STM32F407ZGT6使用SPI1与MAX31865通信时异常，一直读到0XFF！

解决了嘛？我也遇到同样问题了  能否交流一下

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

你的SPI1模式配置错误了，要么模式0：低电平和第一个跳变沿采样   模式3：高电平和第二个跳变沿采样。你搞的是低电平和第二个跳变沿采样，混用了


Question: 这样的结构声明错在哪里？

typedef struct film *Item;//为什么不能这样定义？ //struct film* Item; Item = &f; 这儿的Item是类型别名，是struct film *的别名。不是变量，因此Item = &f；是不对的。相当于int = &f一样。

typedef struct film *Item;//为什么不能这样定义？当然可以  问题是这个Item是一个类型呀 类型 = &f 当然错

typedef struct film *Item;//为什么不能这样定义？' 答：是可以这么定义的。但是这条语句的作用是，是将Item重定义成可以替换struct film * 的关键字. 使用时应该这么使用：    #include <stdio.h> struct film { 	char title[10]; 	int rating; }f; typedef struct film *Item;//为什么不能这样定义？ //struct film* Item; Item  pItem = NULL; int main() { 	pItem = &f; 	scanf("%d", &(pItem->rating)); 	printf("%d", pItem->rating); 	return 0; }


Question: c语言在发送http请求时，头部里有中文，后台收到后会出现乱码如何解决

引用 2 楼 user-1 的回复:have a try Windows系统的话可以用MultiByteToWideChar 如把u_name转成unicode #include <windows.h> int len=(int)strlen(u_name); WCHAR uc[len+1]; int r = MultiByteToWideChar(CP_OEMCP, 0, u_name, -1, uc, len+1); 感谢，可以啦 char u_name[50] = "我是中国人ABC"; 	char header_name[100] = "0"; 	char header_end[100] = "0";  	int len_l = (int)strlen(u_name); 	WCHAR *ucp; 	ucp = (WCHAR *)calloc((len_l + 1), sizeof(WCHAR)); 	int r = MultiByteToWideChar(CP_OEMCP, 0, u_name, -1, ucp, len_l + 1);  知识扩充 ------------------------CP_ACP和CP_OEMCP   start---------------------------- Windows API函数MultiByteToWideChar用于多字节编码字符串向宽字符串（即UTF-16 LE）的转码。它的第一个参数的常用值是CP_ACP和CP_OEMCP。这到底指的是什么代码页呢？ 我编了小程序做了实验。  CP_ACP和CP_OEMCP，分别是指当前计算机上的Windows操作系统的Windows代码页与OEM代码页。对于东亚的简体中文、繁体中文、日文、韩文等Win操作系统语言环境，这两种代码页是同一个，如简体中文是代码页936即GB2312字符集，繁体中文是950即大五码字符集，韩文是949、日文是932。对于西方国家的拼音文字语言设置，两个代码页不同。典型的如English_US，其Windows代码页是1252、OEM代码页是437，还有第三个代码页ISO-8859-1又称Latin-1或“西欧语言”，是针对英语法语西语德语等西欧语言的扩展ASCII字符集。这三者（1252、437、8859-1）都是针对英语但并不相同。  为什么会有Windows代码页与OEM代码页的区别呢？因为在八十年代DOS系统时期，还是“字符终端”的屏幕只能够显示的256个字符，这些字符的字形的点阵信息存储在硬件的ROM中。DOS操作系统通过系统中断调用驱动程序把这些字形读出来写入显存。这是由OEM负责字符集中有哪些字符，显示时为什么字形的时代，而且一台PC上只有这么一套字符集/字形，没得选，除非你再差一个带字库的“汉卡”。进入了微软的Windows操作系统时代之后，由于硬件的发展，操作系统有了自己的字形文件，绘制字符时不再真地去读ROM，而是用字形文件（就是字体fonts文件）来把字符的形状写入显存。可以选择用哪种字形：如有衬线的Times NewRome，还是无衬线的Sans Serif。操作系统默认使用的字符集，就由微软来定义了，如English_US使用Codepage1252；简体中文使用Codepage936（即国标2312）. 至于那个OEM436，就是legacy，用于向后兼容。  综上，就这么点事。CP_ACP和CP_OEMCP，分别是UINT的0和1。在WinNls.h中的注释说明分别是“default to ANSI code page”，“default to OEM  code page”。所以，在简体中文Windows，这两个宏表示的都是代码页936.  下述程序代码片段用于测试              UINT codepage=936;     char str[]="我们中国"; //这个char[]必然是多字节编码字符串     DWORD len;     // 得到我们要转换的MyString为UNICODE所需要的UNICODE缓冲区的长度     len = MultiByteToWideChar(codepage, 0, str, -1, 0, 0);     wchar_t *buf=new wchar_t[len+10];     MultiByteToWideChar(codepage, 0, str, -1, buf, len);      setlocale(LC_CTYPE,"");//把当前locale字符环境从C/C++缺省的"C"设置，改为操作系统的设置（即代码页936）     wprintf(L"%s",buf);  //因为这个C标准库函数的实现，是把宽字符输入又转化为多字节字符去显示，所以必须正确设置当前操作系统的多字节编码的代码页  结果： 1. 输入是char str[]="我们中国"; UINT codepage=936或者54936（这是GB18030代码页）或者CP_ACP或者CP_OEMCP，都能正确打印出结果“我们中国”。 2. 输入是char str[]="иい瓣";  UINT codepage=950; 也能正确把上述大五码字符串打印出宽字符串输出结果“我们中国”。 3. 输入是char str[]="鎴戜滑涓浗 ";  UINT codepage=65001; 也能正确把上述UTF-8字符串打印出宽字符串输出结果“我们中国”。  附录： 一个在线GB/BIG5/UTF-8/UNICODE转码的网站http://www.dheart.net/bmzh/index.php  ps. 实际上，简体中文Windows系统的默认代码页936，不是只有6763个汉字的GB2316，正确说法是自1995年Windows95起，代码页936是GBK字符集，包含了20902个汉字。此前，代码页936与GB2316是一样的。GB2316 >> GBK >> GB18030 是向后兼容的。所以编程角度把这三者视作等同，也凑合啦。 ------------------------CP_ACP和CP_OEMCP   end---------------------------- MultiByteToWideChar     函数功能：该函数映射一个字符串到一个宽字符（unicode）的字符串。由该函数映射的字符串没必要是多字节字符组。(此函数把多字节字符串转换成宽字符串(Unicode)，待转换的字符串并不一定是多字节的。) 　　     函数原型： 　　  int MultiByteToWideChar( 　　              UINT CodePage, 　　  DWORD dwFlags, 　　//一组位标记用以指出是否未转换成预作或宽字符（若组合形式存在），是否使用象形文字替代控制字符，以及如何处理无效字符。你可以指定下面是标记常量的组合  LPCSTR lpMultiByteStr, 　　//指向将被转换字符串的字符  int cchMultiByte, 　　//指定由参数lpMultiByteStr指向的字符串中字节的个数。如果lpMultiByteStr指定的字符串以空字符终止，可以设置为-1（如果字符串不是以空字符中止，设置为-1可能失败，可能成功），此参数设置为0函数将失败。  LPWSTR lpWideCharStr, 　　//指向接收被转换字符串的缓冲区  int cchWideChar 　　//指定由参数lpWideCharStr指向的缓冲区的宽字符个数  );


Question: 不懂

谢谢，我知道了

while (*p != '\0')             {                 *p = *(p + 1);                 p++;             } 这个删除空白字符的方法是后面的字符向前覆盖。即后面的字符向前移动一个字符。

不用改吧，我认为原函数写的挺清晰的  void d_blank(char* st) {     char* p;       while (*st != '\0')     {         p = st;         if (*p == ' ')         {             while (*p != '\0')             {                 *p = *(p + 1);                 p++;             }         }         st++;     } }  之所以加进来一个临时指针p，是因为在找到空格时，p已经增量到字符串末尾了。 所以每次循环都要重新赋值下p，在循环尾增量st 然后再检查下一个字符  无论是多个连续空白，还是间隔的空白，都能过滤掉。

引用 2 楼 m0_46108109的回复:假设\0是整个字符串的结尾，且字符串中只有一个\0  当*p == ' '时， 不加while (*p != '\0') *p = *(p + 1); 只是把下一个字符，替换为了空格，下一个字符还在原位置。              while (*p != '\0')             {                 *p = *(p + 1);                 p++;             } 这样处理，就等于把空格之后的所有字符，都向前挪动一格了。 那如果不确定空白字符的数量，该怎么改？

如果是中间有两个空格，该怎么改？


Question: c语言问题 fatal error LNK1169: 找到一个或多个多重定义的符号

引用 4 楼 ljn20010724 的回复:[quote=引用 2 楼 user-2 的回复:]  用vs添加类向导来添加吧。他会自动生成对应.h .cpp  你这个包含.cpp 应该不正确。一般都是include .h 您好，请问就是建立顺序表这种的话是一定要建立头文件对吗？所以我要用类向导来创建一个头文件，然后来链接他们？如果有理解偏差麻烦请见谅，我刚学，谢谢[/quote] 也就是说我的这两个文件是“地位不平等”的吗？我的意思是现在因为我这两个文件都是在源文件下创立的，我要把要引用的文件放在头文件下吗？

引用 3 楼 m0_46108109 的回复:#include "sqlist.cpp"  这句话的意思是，把这个文件也包含了进来。 对于变量是可以的，好像结构也可以。 因为每个变量都可以是文件域 就相当于那个cpp文件不起任何作用。  但是函数不行，函数定义了，就是全局的，即使你没有在另外一个文件中声明 实际上也能在另外一个文件中使用。（这点我脑补的）  这就是文件作用域和外部链接内部链接的区别。 您好，我还是不是很清楚您讲的，可以请您告诉我怎样修改，或许我可以更好的理解，谢谢了

引用 2 楼 user-2 的回复: 用vs添加类向导来添加吧。他会自动生成对应.h .cpp  你这个包含.cpp 应该不正确。一般都是include .h 您好，请问就是建立顺序表这种的话是一定要建立头文件对吗？所以我要用类向导来创建一个头文件，然后来链接他们？如果有理解偏差麻烦请见谅，我刚学，谢谢

求大神求解为什么会出现这样的报错！谢谢了！

这么理解，当所有内容都在一个文件里，那么就不需要声明，编译器遍历一下文件，引用的时候直接链接定义就可以了。但是把所有内容都放在一个文件里，不方便开发。所以有了把不同内容放在不同源文件里的开发模式。同样，这些内容完全也可以不使用声明，编译器只需要遍历一下所有文件，在引用的时候直接调用定义就可以了。但是这样设计必须所有的内容全部写完，才可以编译。如果两个人合作开发的话，一个人必须等待另一个人完成工作，才能完成自己的内容。所以有了声明的设计，声明只是声明了数据类型，例如函数的声明其实只是声明了一个函数指针。大家都包含了一个需要用到的声明文件，就可以不必等其他人定义完，才能工作。这么做开发小工程可以，但是多人开发大工程就会出现问题。a负责一个源文件，他有自己的开发习惯，他声明了一个全局变量。b在自己的文件里也使用了一个同名的全局变量。两个人都不肯放弃自己的习惯。所以有了文件作用域的设计。ab在自己文件中定义的全局变量具有文件作用域，只在自己的文件中可见。那么又如何使ab都可见一个全局变量呢，那就是引用关键字，引用具有外部链接，a和b同时引用了一个同名变量，然后都定义了就会发生重定义错误(这个是我脑补的，一会儿试验一下)。也就是说，没有引用声明的，都是内部链接，具有文件域。引用声明的具有外部链接是全局变量。函数则不同，我想之所以与变量不一致，可能是因为链接的关系。c的编译器和连接器是分成这两部分完成编译的。单独编译a和b同名函数没有任何问题，函数就是个函数指针，也是个变量。但是要链接a和b的同名函数就有问题了，连接器不知道应该链接哪一个函数。当然函数也可以设计成具有文件域，需要在另外文件中使用的时候，在另外文件中引用这个函数。但是c的基本功能就是通过函数库来实现的，假设你开发了一个函数，和函数库中的函数重名，第三方同时使用你的函数和同名函数库中的其他函数时，链接器不知道应该链接哪个。这个是c的缺点，你会发现虽然标准委员会建议淘汰旧函数，使用新函数，即便新旧函数的原型完全一样，新函数也会更名，而不会重载旧函数，就是因为函数都是全局的，不能重复定义。


Question: 算法萌新求教，求时间复杂度

引用 1 楼 user-1的回复:i=1，j循环1次，i=2，j循环2次，i=3，j循环3次，。。。i=n，j循环n次， 所以一共循环 1+2+3+...+n=n*(n+1)/2 所以时间复杂度是n平方，即O(n^2) 大佬你真牛逼，我关注你了


Question: 形参中的数组名是其实是假数组？

形参数组名，编译器就是当成指针处理了。其实也是指针。

数组确实有些特殊   数组名是数据的地址、指针    &数组名， 还是它  这个有点儿像函数指针的使用方法  int (*pFunc)(int);      (*pFunc)(1)  和  pFunc(1)是一样的  都是属于语法的规定

数组名就是指针，例如字符串char*

有一点不同 我看的书里这样说 应该这样写 a = dates2;  写成 a = &dates2; 或 a = &dates2[0]; 都是不专业的

哪怕你参数你写成func(const int a);  函数里面你还可以强制类型转换成非cosnt类型继续改， * (int *)(&a) = 3;  这个和 const char * = "abc";  不能改字符串的值不一样， abc是真的分配在只读内存的，你改不了 函数传参都在系统栈里面，都是可读可写的， 所以随便改吧， 只要你知道自己明确的目的是什么

传参的时候，记住————永远传递的是值！！！ 哪怕是指针， 传递进来的也是指针的值， 不是指针指向的内容；和传递一个普通的类型变量一样，都是值。  这个值，被放到了系统的栈里面， 成为函数体里面的参数变量了， 从此和调用它的变量毫不相干 既然毫不相干，还是个变量，那么你想怎么改怎么改， 反正也跑不出函数这个范围， 对函数外面毫无影响

恭喜你， 终于得道了！    传参的时候，就是一个指针， 根本就不是整个数组进来的，哪怕你参数写成func (int arry[10] ); 函数里面sizeof（arry）返回的依然是指针的大小  作为一个指针， 函数只知道它的指针类型， 不知道它对应的有效数据后面有多长的， 所以后面还必须带一个整数来告知

对了即使是(int*)dates也是存在警告的

是的。写成a[]，只是为了方便理解。 而且，似乎 根本就没有数组，数组名就是一个不可修改的指针。 short dates[SIZE] = {23,24,25,26}; short* p=dates； 通过p就可以操作数组。

11点半了你的帖子居然能出来  void main警告  此处应当是有警告的，其实编译器更希望你传&dates


Question: 学生管理系统的学生成绩的及格率，平均分和年龄最小的问题， 谢谢谢谢！！！

谢谢！！！年龄那里我调出来了，是因为循环那里出的问题

你先自己调着吧。百度vc6如何调试

这是devc++5.11上面的程序 #include<stdio.h> #include<stdlib.h> #include<string.h>     typedef union { 		struct{ 			unsigned int year:12; 			unsigned int month:4; 			unsigned int day:5; 		}; 		unsigned int value; 	}DATE;   typedef enum gender{male,female}GENDER;  typedef struct _student{ 	int id; 	char name[20]; 	float score[4];     GENDER gender;     DATE birthday; }STUDENT;//.定义学生结构体  STUDENT students[40]; DATE d;  int count=0; int min;   // 输入学生信息 void input_student( ) {  	 int i,j,n;      int year,month,day;       for(i=0;i<count;i++) 	 { 		printf("please input id,name:"); 		scanf("%d,%s",&students[i].id,students[i].name); 	   	printf("piease input year-month-day:"); 	    scanf("%d-%d-%d",&year,&month,&day);  	    d.year=year; 	    d.month=month;         d.day=day;  		printf("please input gender(male=0,female=1):");     	scanf("%d",&students[i].gender); 		printf("input score(chinese math english physics):");  		for(j=0;j<4;j++) 		{ 			scanf("%f",&students[i].score[j]); 		}  		printf("if you want to input again ,type 1;if you don't ,type 2:"); 		scanf("%d",&n);  		if(n==2) 			break; 	 }  }  //查找并显示学生信息 void show_student(int i) { 	int j; 	printf("\n"); 	printf("\tthe student is founded and this is all his information:\n"); 	printf("\tid: %d\t",students[i].id);  	printf("name: %s\t",students[i].name); 	printf("birthday: "); 	printf("%4d-%02d-%02d \t",d.year,d.month,d.day ); 	printf("gender: "); 	 	switch(students[i].gender) 	{ 	    case male: 		    puts("男");  			break; 	    case female: 			puts("女"); 			break;  	} 	 	printf("\tchinese math english physics: ");  	for (j=0;j<4;j++) 	{ 		printf("%.2f\t",students[i].score[j]); 	} 	printf("\n"); } 		 //统计平均成绩和及格率   void calculate_student( int n) { 	int i,j,p; 	      int a=0;  	float sum=0; 	  	enum subject{chinese,math,english,physics}; 	printf("\ninput the score you want to know(chinese=0,math=1,english=2,physics=3): "); 	scanf("%d",&p);  	switch(p) 	{ 	case 0: 		puts("the pass rate and avg of chinese:"); 		break; 	case 1: 		puts("the pass rate and avg of math:"); 		break; 	case 2: 		puts("the pass rate and avg of english:"); 		break; 	case 3: 		puts("the pass rate and avg of physics:"); 		break; 	}    	for(i=0;i<n;i++) 	{ 		for (j=p;j<p+1;j++) 		{ 		    sum+=students[i].score[p]; 		    if (students[i].score[p]>=60) 			{ 		    	a++; 			} 		} 		 	}   	      	printf("pass rate=%.2f\n",a/n); 	printf("avg=%.2f\n",sum/n); }  //查找年纪最小的学生 void young_student(int n) { 	 	 int min=students[0].birthday.value;    	 int i;  	 for (i=1;i<count;i++) 	 { 		 if (students[i].birthday.value < min) 		 { 		  			 min=students[i].birthday.value;               		 } 	 }  	 for (i=0;i<n;i++) 	 { 		 if ( students[i].birthday.value==min) 		 { 			show_student(i); 		 } 	 }  }     	     int main(void) { //1.输入学生信息：学号，姓名，性别，出生日期，成绩      int i,n; 	  	   	 char NAME[20];  	 int year,month,day; 	         	 printf ("please input the number of student:"); 	 scanf("%d",&count);  	 n=count;  	 input_student(); 	  //2.查找并显示学生信息 	        printf("\ninput the name you want to know:"); 	 scanf("%s",NAME); 	 for(i=0;i<count;i++) 	 { 		 if (strcmp(students[i].name,NAME)==0) 		 { 	         show_student(i); 		 } 	     else 		 { 			 printf("the name is wrong!!!"); 			 break; 		 } 	 }   	 printf("\n");	   //3.统计平均成绩和及格率       calculate_student(n);   //4. 查找显示年龄最小的学生的信息；  	 young_student( n);  }

warning是这张图片的内容 VC是老师要求的平台，其实devc++这些也是可以的。

嗯嗯，谢谢，那那个及格率出来永远是0.00和那个查找年龄最小的学生是什么问题呢？？？

warning消息，你得贴出来看是什么警告内容，大部分没有什么影响的，你不帖提示不能让别人猜啊。VC6现在没有多少人在用了。

warning没必要管，只要不是error就行

那我想再问一下，那个年龄为什么总是查找不对，是我的代码那个地方出了问题呢？？？

嗯嗯，知道了，谢谢

int year, month, day;//这行代码没用。 这几个变量后面没有使用过

谢谢谢谢，现在第一个类型不一样和第四个调好了 但是还是对二三四的day值没有使用很模糊，可以再讲一下吗？？？谢谢了！

严重性	代码	说明	项目	文件	行	禁止显示状态 警告	C4018	“<”: 有符号/无符号不匹配	Project2	E:\C++application\Project2\Project2\main.cpp	686	 警告	C4101	“day”: 未引用的局部变量	Project2	E:\C++application\Project2\Project2\main.cpp	715	 警告	C4101	“month”: 未引用的局部变量	Project2	E:\C++application\Project2\Project2\main.cpp	715	 警告	C4477	“printf”: 格式字符串“%.2f”需要类型“double”的参数，但可变参数 1 拥有了类型“int”	Project2	E:\C++application\Project2\Project2\main.cpp	674	 警告	C4101	“year”: 未引用的局部变量	Project2	E:\C++application\Project2\Project2\main.cpp	715	  第一个是你的判断左右两边类型不一样。 左边是unsigned int，右边是int  第二、三、五个 day的值没有使用  第四个说printf("pass rate=%.2f\n", a / n); //打印格式是小数，但你的a是整数

很不错，楼主加油

嗯嗯，好，我之后注意

发代码的时候用代码格式发看起来更好些


Question: 为什么要typedef一个结构，为什么不直接用struct

typedef　struct　film　Item; struct　film　Item; 这两条语句差距很大的。第一个是别名一个结构体类型。Item不是变量而是一个类型。即struct film的类型  第二个语句是定义的结构体变量，Item是变量。

懒，那是开个玩笑  方便修改是真的，而且也可以定义多种类型的别名，比如item，*pitem

楼上的观点是正确的，就是为了偷懒，而且也不容易出错

typedef 是定义别名，相当于Item就代表struct film，之后再定义类似的变量，就可以直接用Item来定义了，比如Item data。

方便啊，少写几个字母


Question: 两个整数集合，求交集和并集

并集的话用set，交集用位运算解决

取值范围呢?


Question: 链表问题

我理解错题的意思了

#include<stdio.h> #include<stdlib.h>  struct student {     int n;     struct student* next; };  int number;  struct   student  *create_link() //创建未知链表； {     struct student* p, * head,*q;     p = (struct student*)malloc(sizeof(struct student));     head = p;     scanf("%d", &p->n);      for (int i = 0;; i++)     {         q = (student*)malloc(sizeof(student));         p->next = q;         p = q;         scanf("%d", &p->n);          /*            if ((i == 0) && ((k = getchar()) == '\n'))            {         //p = NULL;         p->next = NULL;         break;         }         else if (i == 0)         {         p->n = (int)(k-'0');         q = (struct student*)malloc(sizeof(struct student));         p->next = q;         p = q;         }         else         {         //scanf_s("%d", &(p->n));         scanf("%d", &(p->n));         if ((k = getchar()) == '\n')         {         p->next = NULL;         break;         }         else         {         q = (student*)malloc(sizeof(student));         p->next = q;         p = q;         number++;         }         }         */         if (getchar() == '\n')             break;     }     p->next = NULL;     return head; }  void print_link(struct student *head) {     struct student *p = head;      while (p) {         printf("%d ", p->n);         p = p->next;     }     printf("\n"); }  int search(struct student *phead, int n) {     struct student *p = phead;      while (p) {         if (p->n == n)             return 1;         p = p->next;     }      return 0; }  struct student * intersection(struct student *la, struct student *lb) {     struct student *lc = NULL;     struct student *pa, *pb, *pc, *prev;      pa = la;     pb = lb;      while (pa && pb) {         if (pa->n == pb->n) {             if (search(lc, pa->n)) {                 pa = pa->next;                 pb = pb->next;                 continue;             }             pc = (struct student *)malloc(sizeof(struct student));             if (!pc)                 exit(0);             pc->n = pa->n;             if (!lc) {                 lc = pc;                 prev = pc;             } else {                 prev->next = pc;                 prev = pc;             }          }         if (pa->n > pb->n)             pb = pb->next;         if (pa->n < pb->n)             pa = pa->next;     }     prev->next = NULL;      return lc; }  int main() {     struct student *p, *q, *t;     //void print(struct student * p,struct student * q);//创建链表且为升序；     p = create_link();     //print_link(p);     q = create_link();     //print_link(q);     /*     if ((p == NULL) ||(q == NULL))         printf("NULL");     else         print(p, q);     */     t = intersection(p, q);      print_link(t);     return 0; }  #if 0 void print(struct student* p,struct student* q)  //打印两个链表的交集 {     struct  student* q1 = q, * p1 = p;     for (int i = 0;; i++)     {         if (p->next != NULL)         {             if ((p->n) == (p->next->n))                 p = p->next;         }         for (int j = 0;; j++)         {             if (q->next != NULL)             {                 if ((q->n) == (q->next->n))                     q = q->next;             }             if (p->n == q->n)             {                  printf("%d ", p->n);                 q = q1;                 break;             }             else             {                 if (q->next == NULL)                 {                     q = q1;                     break;                 }                 else                     q = q->next;              }          }         if (p->next == NULL)             break;         else             p = p->next;     } } #endif  供参考～

求两个非降序单链表的交集，例如将单链表1->2->2->3 和 2->2->3->3->5->7 的交集产生新单链表 2->3，只能输出结果，不能修改两个单链表的数据。  【输入形式】  第一行为第一个单链表的各结点值，以单个空格分隔。  第二行为第二个单链表的各结点值，以单个空格分隔。  【输出形式】  交集的单链表，以升序排列(无重复值)，值与值之间以单个空格分隔。


Question: 不能正确执行scanf（）函数，如何解决

scanf("%c", &answer); 这条语句前加一个getchar();吧 因为这条语句是%c，正好匹配输入缓存里的'\n'。这个'\n'是上一个输入留下的。

for( ; ; )         {                 printf("\n Enter a value:");                 scanf("%lf", &value);                 total += value;                 ++count;                  printf("\n Do you want to enter another value?(Y or N):");                 getchar();                 scanf("%c", &answer);                  if(tolower(answer) == 'n')                         break;         }  加一个getchar()，大概原因是第一个scanf存在换行符，恰好用在了第二个scanf上，先用getchar()把换行符吸收了，就可以了


Question: 新手求教double和float

简单说 float可以表示 0.0000000 那么 double可以表示 0.00000000000000(只是比喻，具体取值范围请看书)

sizeof 一个是单精度，一个是双精度 浮点运算消耗时间，一般的数值运算，小数点后面太多的位数没有意义。 C的设计原则是效率，所以在不需要双精度的地方用单精度。 但是为了支持数学运算，好像还有llf，不知道实现一样不一样。


Question: C语言快速排序用数组实现交换swap为什么不能用数组类型，一定要用指针类型？可以使用数组类型吗？

打错一个字，最后一句话是:那传入值:图一又该怎么解释呢？

传入值:图一: 传入值:图二: 传入地址:图一: 传入地址:图二:  果然，我现在又举了几个例子，发现如果是传入数字，swap只改变形参的值，不改变实参的值。但如果是传入地址，那么swap通过交换(改变)形参的地址，从而交换(改变)实参的地址，从而改变实参的值。   但是我不理解chxchxkkk三楼说的，传入变量在函数退出时，变量值也清空了，是C语言中在函数里面定义的局部变量确实会在函数结束之后被释放掉这个意思吗？     那传入值:图一有该怎么解释呢？

数组类型作为参数和指针作为参数是同等的效果，数组类型作为参数其实就是指针作为参数。  swap用指针的原因是修改的是调用swap的实参，如果用普通变量，那么根据参数传递是值传递，形参是局部变量，交换了形参只是交换了局部变量，对于实参没做任何修改。

传入变量在函数退出时，变量值也清空了，所以要传入指针才能修改主函数里的变量值

嗯嗯，打错了。  传入数字，是在swap函数内创建了x,y的副本a,b，交换的是被调函数内的创建的副本a,b的值，无法作用于实参。  对于传入的实参x，y没有影响。因为x,y是在main函数内创建的，所以它们要等到整个程序结束的时候才会释放。

哦哦，明白了，但是这句话“对传入的实参a，b没有影响”应该是"对于传入的实参x,y没有影响"吧，回答了我就结贴了。

果然，我现在又举了几个例子，发现如果是传入数字，swap只改变形参的值，不改变实参的值。但如果是传入地址，那么swap通过交换(改变)形参的地址，从而交换(改变)实参的地址，从而改变实参的值。[/quote]  传入数字，是在swap函数内创建了a,b的副本，交换的是被调函数内的创建的副本a,b的值，无法作用于实参。更不是说改变了形参的值，“形参”就是形式参数，是用来表示传入实参的类型的，是拿来看的，没有具体的值。 在你的这个函数中，通过传入两个实参的地址，直接交换了实参的值，并不是说通过交换实参的地址，从而改变实参的值。  但是我不理解chxchxkkk三楼说的，传入变量在函数退出时，变量值也清空了，是C语言中在函数里面定义的局部变量确实会在函数结束之后被释放掉这个意思吗？     那传入值:图一有该怎么解释呢？[/quote] 函数结束之后函数内创建的局部变量会被释放，也就是创建的副本a,b被释放掉了，对传入的实参a，b没有影响，所以你输出的交换后的值还是5，8。因为a,b是在main函数内创建的，所以它们要等到整个程序结束的时候才会释放。

传入指针是修改的是a[i]和a[j]的值，传入数组时只是传进去两个数字，swap里的修改不会影响a[i]a[j]的值，只是函数里面的形式参数p  q被改变。


Question: 哪位好心人帮我一下，解释一下这道题

引用 1 楼 后入赵丽颖的回复:字母通过改变ASCII值变化成其它字母 谢谢一楼的同学

引用 3 楼 初学小菜的回复:就是字符的加减，写的复杂了些而已 问题解决，谢谢大家

引用 3 楼 初学小菜的回复:就是字符的加减，写的复杂了些而已 谢谢初学小菜，

就是字符的加减，写的复杂了些而已

直接强制转化就行呀 不需要其他操作，比如一个int a=1;要转化成char ch; 直接ch=a+96就可以

字母通过改变ASCII值变化成其它字母


Question: C语言用函数实现在n个整数中找到最大的k个数

排序然后顺序去取就可以了。排序方法，建议楼主从网上搜一下：冒泡，选择，快排都可以的。

排序前是个数组，排序后也是个数组，操作数组的能力不够强啊。

参考以下帖子吧，这种问题，有不少人问过了 https://bbs.csdn.net/topics/395884394

这孩子没救了， 怎么排完序还不会了呢  哪怕错了，你也把自己代码贴出来吧 看代码说话

引用 3 楼 weixin_46476023 的回复:[quote=引用 1 楼 與蘤舊縐的回复:]排序之后取你需要的数不就行了  初学的话排序一般就冒泡了 就是排完序不会取了[/quote]  从大到小取k个  一个for循环，i=k;i>0;i--不就行了

引用 1 楼 與蘤舊縐的回复:排序之后取你需要的数不就行了  初学的话排序一般就冒泡了 就是排完序不会取了😭😭

你也可以找多次最大值，每次找出后把最大的删了

排序之后取你需要的数不就行了  初学的话排序一般就冒泡了


sprintf(N[j-1],"%d",j); 这里似乎得用个工具函数，ltoa

10^9+7 你认为这样定义的数是多大？^运算是按位异或 10的二进制是.1010 ，9的二进制 是1001，二者异或是0011就是3 ，3+7 等于10

你这程序什么输入？ 怎么溢出的？

10=8+2    1010 9=8+1 1001 --------- 0011=3  10^9+7 = 10 10*200*2 = 4000  = 4kB  看上去堆栈溢出的可能性不太大。 帮你运行一下。

char s[200][10^9+7];把这儿改成11试试，是不是没保存\0


Question: 测试函数运行时间

多谢！我已经找到方法了 用for循环 //循环多次调用 #define MAXK 1e7 for(i = 1;  i <= MAXK;  i++)

引用 2 楼 初学小菜 的回复：不是无法显示，是你这个程序复杂度太低，算的太快了， 你在计时的中间可以加一下这个 k=1000000000； while(k){ 	k--; }  在跑一下就有时间啦我的目的是：想要测试有秦九昭和没有秦九昭算法，函数的运算速度

为什么无法出现测试时间？


Question: 超级简单问题求助

我只想说，现在初中生的信息课都能做这个题 这个和专业真实屁关系都没有的，也和学业基础没啥关系  回去看书吧  你知道大学和高中初中小学相比最大的区别在哪儿吗？ 就是要开始自学了， 老师不会再带你一步一步的做题了， 大学就是要培养自学能力的，这个从大一进来的授课方式上就不同了 以前老师给你讲道理，给你板书一步步的解题，甚至留作业批改， 还回过头来逐个辅导 这个事儿，从进入大学的门就没啦， 没啦， 没啦  这是步入大学必须转变的东西 大学只教你知识框架，告诉你什么类型的题目用什么公式和方法解， 不告诉你为什了么 不再带你一步步的计算，告诉你个最终结果剩下的自己玩儿去吧  从这个课程上早点体验到这个转变，挺好

必须学，又不学，就很怪。算了吧，没人帮你，天道酬勤。加油，楼主。 只有自强之人才更容易为他人所愿意帮助

不是不做 我是真的不会   我的专业和这个无关 但必须学  这是我第一次接触c语言 上了2节课老师就让做这个 我是真的不会

这么简单题都不做，那就不要学了。


Question: 蓝桥杯十六进制转八进制简易思路

引用 17 楼 寻开心的回复:牺牲空间换时间，打表可以大幅度提高效率 3个16进制 = 4个八进制  这对很长的数据来说，很有优势 3个16进制才多少位啊， 12bits， 最大值也不过4096吧，这点内存开销不算什么 嗯，学到了。

引用 15 楼 zhoujun233 的回复:有没有什么好的教学视频，，打表我不会，c函数库一个都不会标准库这个靠时间积累 没什么特别好的做法  做题多了接触多了自然知道了 这里不知道 sprintf/sscanf 问题不大 无非是手写 int转4位八进制字符串 / 3位十六进制字符串转int  打表这个记一下用两下就懂了 算是一种基础数据结构 后面学数据结构 算法之类的课程会接触到

有没有什么好的教学视频，，打表我不会，c函数库一个都不会

引用 12 楼 lin5161678的回复:[quote=引用 10 楼 lin5161678 的回复:] #include <stdio.h> int main(int argc, char *argv[]) { 	//打表  	char table[0x1000][10]; 	for(int i=0; i<0x1000; ++i) 		sprintf(table[i], "%04o", i); 	//输入 预留偏移以便对齐	 	char strSrc[1024] = "000"; 	scanf("%s", strSrc + 3); 	//输出 计算对齐  	int nlen = strlen(strSrc + 3); 	for(char* pstrSrc = strSrc + nlen % 3; *pstrSrc; pstrSrc+=3) 	{ 		int nTmp = 0; 		sscanf(pstrSrc, "%3x", &nTmp); 		printf("%s", table[nTmp]); 	}  	puts("");  	return 0; } 没怎么雕琢 最开始会有多余0的现象 小问题 没做处理 理解代码 不要生搬硬套[/quote] 这个我刚刚查了下，百度，的确这样更简单。c函数库没有学，不会用

引用 5 楼 zhoujun233 的回复：[quote=引用 3 楼 初学小菜的回复:]他这么写不是很麻烦嘛。。。。 这个思路不就是利用二进制完成转化嘛，四位换成3位。。 emmm，那要怎么写?第二次些博客了。有些题目看起来简单，可实践起来比较难，这题要求十六进制位数很多位。我之前写了个用单纯用整型加数学方法的代码。可是提交上去蓝桥杯就显示运行错误。求教教我如何写好一篇好博客[/quote]字符串存就行，管它多少位呢，有二进制的思想，打表➕判就简单了

引用 10 楼 lin5161678 的回复:#include <stdio.h> int main(int argc, char *argv[]) { 	//打表  	char table[0x1000][10]; 	for(int i=0; i<0x1000; ++i) 		sprintf(table[i], "%04o", i); 	//输入 预留偏移以便对齐	 	char strSrc[1024] = "000"; 	scanf("%s", strSrc + 3); 	//输出 计算对齐  	int nlen = strlen(strSrc + 3); 	for(char* pstrSrc = strSrc + nlen % 3; *pstrSrc; pstrSrc+=3) 	{ 		int nTmp = 0; 		sscanf(pstrSrc, "%3x", &nTmp); 		printf("%s", table[nTmp]); 	}  	puts("");  	return 0; } 没怎么雕琢 最开始会有多余0的现象 小问题 没做处理 理解代码 不要生搬硬套

引用 9 楼 zhoujun233 的回复:而且你的码表是不是有些多呀，3位十六进制有多少数呀！多少位重要吗? 加声明数组在内 3行代码的事

引用 7 楼 lin5161678的回复:挺简单的题目 怎么你实现这么复杂 1位十六进制对应4位二进制 1位八进制对应3位二进制 3位十六进制对应 12位二进制  12位二进制对应 4位八进制 整理一下 3位十六进制对应4位八进制 一个循环打表 处理的时候 做好对齐分割 扫一圈完事 而且你的码表是不是有些多呀，3位十六进制有多少数呀！

引用 7 楼 lin5161678的回复:挺简单的题目 怎么你实现这么复杂 1位十六进制对应4位二进制 1位八进制对应3位二进制 3位十六进制对应 12位二进制  12位二进制对应 4位八进制 整理一下 3位十六进制对应4位八进制 一个循环打表 处理的时候 做好对齐分割 扫一圈完事 可是你输入的一定是3倍数的十六进制嘛？

引用 4 楼 千梦一生的回复:我理解中16进制转8进制应该很简单啊。 我开始看到这题也是这样想的，可题目要求这个十六进制的位数很大，不能用数值运算，只能用字符串一位一位的运算

引用 3 楼 初学小菜的回复:他这么写不是很麻烦嘛。。。。 这个思路不就是利用二进制完成转化嘛，四位换成3位。。 emmm，那要怎么写?第二次些博客了。有些题目看起来简单，可实践起来比较难，这题要求十六进制位数很多位。我之前写了个用单纯用整型加数学方法的代码。可是提交上去蓝桥杯就显示运行错误。求教教我如何写好一篇好博客

我理解中16进制转8进制应该很简单啊。

引用 1 楼 user-5的回复:前段时间有人发帖问过这个问题 毕竟是蓝桥杯题目，，看的人还是比较多的

前段时间有人发帖问过这个问题


Question: 变量顺序问题？

放在外面，每次结果不对的时候sn也可能被累加了，循环到对的那次，sn已经大于i了

引用 3 楼 qq_20466297 的回复:[quote=引用 2 楼 真相重于对错的回复:]在for内部定义，每次循环都是0 在for外边定义，结果会保存 百度一下变量的生命周期 为什么Sn在外对结果什么也不输出？[/quote] 学会调试， f10 单步执行   f11 单步执行，遇到子函数就进入并且继续单步执行。

引用 2 楼 真相重于对错的回复:在for内部定义，每次循环都是0 在for外边定义，结果会保存 百度一下变量的生命周期 为什么Sn在外对结果什么也不输出？

贴一下代码好吗 看不清呀


Question: 结构体中如何使用数组

这里有两个概念： 1、int num跟 char num[N]的区别，前者存的是整形数据，后者存的是字符串数据 2、看你需求，这里可以使用int num也可以使用char num[N]，只要你后续函数里根据不同类型进行处理就好了。

可以使用int，只要以后把这个成员按int处理就可以。 因为像邮政编码什么的，一般当字符串处理。

求大佬看一下


Question: 求100以内的偶数的和，为什么出现了多个数值，但最终结果是对的

你把 printf ( "%d\n" , sum );  拿出来 放在for循环外面试试

for ( i = 1; i <= 100; i++ ) { if ( i%2==0 ) { sum = sum + i; } printf ( "%d\n" , sum );   } 看一下这段代码，你的printf是在for循环里面的，也就是说，每一次偶数相加你都输出了一遍sum 如果只是想要最后的结果，把这个printf放到外面一层就可以了！ #include <stdio.h>  void main ()  { int sum = 0; int i; for ( i = 1; i <= 100; i++ ) { if ( i%2==0 ) { sum = sum + i; } } 	printf ( "%d\n" , sum );  }


Question: 大佬们能不能看一下这个怎么改了，整了一天了。。。

代码没排版，所以没怎么细看 除了2L说的代码书写问题，处理逻辑上也有一些问题 比如case 2后面没有break

你这个问题应该很好找，排除法依次排除即可，我一分钟不到就找到了。。

你的排版太乱了，这样影响你查看BUG的，2个地方，一个是main后面多了一个;，一个是printf_shezhi少了后半截花括号

我用的编译器是vc++6.0，老是出这两个错误 error C2447: missing function header (old-style formal list?) fatal error C1004: unexpected end of file found


Question: C语言while的使用

前后都不执行了。只会一直执行while (1) ;这也是死循环。  建议楼主自己写个程序测试一下～

只有几行代码，其实你可以把代码写出来运行一下。

这是典型的死循环，这个程序执行过程是这样的： 语句①--->语句②--->while(1) ; 到这里，一直没有跳出while循环，一直在执行一个空的语句 所以while循环下面的语句③④都没有执行，而上面的语句①②只执行了一次。

这是一个按键控制蜂鸣器的代码，按k1蜂鸣器响，按k2蜂鸣器就不响，但是如果我一直按着k2不送开的话，按上面说的：那代码就一直处在while（！k2）；的位置，也就不会往下运行，蜂鸣器也还是响的，可我不管是长按k2还是短按，蜂鸣器都不再响

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16;	  //对数据类型进行声明定义typedef unsigned char u8; sbit k1=P3^1; sbit k2=P3^0; sbit beep=P1^5; u8 start=0; /******************************************************************************** 函 数 名         : delay* 函数功能		   : 延时函数，i=1时，大约延时10us*******************************************************************************/ void delay(u16 i) {	 while(i--);	 } void sound() {	   u8 i=100;	   while(i--) 	{		beep=~beep; 		delay(100);		} } void keypros() { 	if(k1==0)			 //开始 	{	 	delay(1000);	 	if(k1==0)	 	{ 			start=1; 	} 		while(!k1);	 } 	if(k2==0)			  //停止 	{ 		delay(1000); 		if(k2==0) 		{			start=0;				}	 	while(!k2); 	} }/******************************************************************************** 函 数 名       : main* 函数功能		 : 主函数* 输    入       : 无* 输    出    	 : 无*******************************************************************************/ void main() { 		while(1) 	{	 	keypros();	 	if(start==1)	 	{			sound();		} 		else		{			beep=1;		}			 }		 }

不会重复执行while前面的语句 展开你就懂了 while (1) {      ; }  会一直执行while里面的空语句，也就是执行完语句1和语句2，就停在while(1)上了，什么都不做。

是的，一直在死循环中


Question: 查链表中的数据找到后strcmp后判断条件为什么要加上&&才能运行成功

引用 9 楼 m0_46108109的回复:这么写没错啊，你写成什么了报错？ 把并且前面去掉了

这么写没错啊，你写成什么了报错？

原来如此谢谢大佬

如果没有这个&&， 只剩下后面的strcmpy， 那么当chalist是NULL的时候， chalist->x 这个操作就会让程序崩溃了

引用 1 楼 qq_33097303 的回复:你把赋空放到后面就不用&&了把&&不写就会出问题

加&&， 就是为了防备 chalist 是 NULL的情况 如果它是NULL， && 后面的部分就不会被调用，从而避免了空指针操作出异常

引用 1 楼 qq_33097303 的回复:你把赋空放到后面就不用&&了#define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <malloc.h> # include <string>  struct studant { 	char x[50]; 	struct studant* next; };  //创建链表 <2>   靠插入来完成链表 /*struct studant* Apex() { 	struct studant* AApex = (struct studant*)malloc(sizeof(struct studant)); 	AApex->next = NULL; 	return AApex; }*/  //创建链表 <1>    先制作链表再来操作链表 struct studant* apex(void) { 	int i, g; 	struct studant* papex; 	papex = (struct studant*)malloc(sizeof(struct studant)); 	papex->next = NULL;  	struct studant* aapex = papex; 	aapex->next = NULL;  	printf("需要多少个链表："); 	scanf("%d", &g); 	while (getchar() != '\n') continue; 	for (i = 0; i < g; i++) 	{ 		struct studant* paapex = (struct studant*)malloc(sizeof(struct studant)); 		paapex->next = NULL; 		printf("输入第%d个链表内的数据：", i + 1); 		scanf("%s", paapex->x); 		while (getchar() != '\n') continue; 		paapex->next = aapex->next; 		aapex->next = paapex; 	} 	return papex; }  //插入节点 struct studant* zjlist(struct studant* ppapex, char a[50]) { 	struct studant* qqapex; 	qqapex = (struct studant*)malloc(sizeof(struct studant)); 	strcpy(qqapex->x, a); 	qqapex->next = ppapex->next; 	ppapex->next = qqapex; 	return qqapex; }  //函数 头插法插入链表（增） void sclist(struct studant* llist) { 	char z; 	char zz[20]; 	int i = 1; 	printf("是否开始(y/n):"); 	scanf("%c", &z); 	while (getchar() != '\n') continue; 	if (z == 'y' || z == 'Y') 		while (z == 'y' || z == 'Y') 		{ 			while (getchar() != '\n') continue; 			printf("\n链表%d\n", i++); 			printf("输入数据："); 			scanf("%s", zz); 			zjlist(llist, zz); 			while (getchar() != '\n') continue; 			printf("\n是否继续(y/n)："); 			scanf("%c", &z); 			if (z == 'y' || z == 'Y'); //判断是否继续创建插入链表 			else 				break; 		} }  //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 { 	struct studant* Freelist = freelist->next; 	struct studant* SFreelist = freelist; 	if (Freelist->next == NULL) 	{ 		printf("链表为空！无法删除！！\n"); 		return; 	} 	while (Freelist && strcmp(Freelist->x, a) != 0) 	{ 		SFreelist = Freelist; 		Freelist = Freelist->next; 	} 	if (strcmp(Freelist->x, a) == 0) 	{ 		SFreelist->next = Freelist->next; 		free(Freelist); 		printf("\n成功删除！！\n"); 	} 	else 		printf("没有相关数据！无法删除！！\n"); }  //打印遍历链表 void bllist(struct studant* bllist) { 	struct studant* bblist = bllist->next;//让指针指向头结点的地址然后从下一个节点开始打印（因为头结点不存放数据  会乱码  ） 	if (bblist != NULL) 		while (bblist != NULL) 		{ 			printf("%s\n", bblist->x); 			bblist = bblist->next; 		} 	else 		printf("链表为空！\n"); }   void List(); void xzcz(); void chalist(); void quitfree(); struct studant* list = apex();   int main(void) { 	List(); 	xzcz();  	return 0; }   void xzcz() { 	char a, b, c; 	char v[50]; 	int f = 1; 	while (f) 	{ 		int b = 0; 		printf("操作链表：\n"); 		printf("<1>增加链表\n"); 		printf("<2>删除链表\n"); 		printf("<3>遍历链表\n"); 		printf("<4>查询链表\n"); 		printf("<5>退出程序\n"); 		printf("请输入："); 		scanf("%d", &b); 		if (b > 5 || b < 0) 			printf("\n输入错误！！\n\n"); 			switch (b) 			{ 			case 1: 				while (getchar() != '\n') continue; 				printf("要增加链表吗(y/n)："); 				scanf("%c", &a); 				if (a == 'y' || a == 'Y') 				{ 					while (getchar() != '\n') continue; 					sclist(list); 					bllist(list); 				} 				break; 			case 2: 				while (getchar() != '\n') continue; 				printf("\n要删除链表吗(y/n)："); 				scanf("%c", &b); 				if (b == 'y' || b == 'Y') 				{ 					while (getchar() != '\n') continue; 					printf("输入要删除的数据："); 					scanf("%s", v); 					shanlist(list, v); 				} 				break; 			case 3: 				while (getchar() != '\n') continue; 				printf("是否要再次遍历(y/n)："); 				scanf("%c", &c); 				if (c == 'y' || c == 'Y') 				{ 					while (getchar() != '\n') continue; 					bllist(list); 				} 				break; 			case 4: 				chalist(); 				break; 			case 5: 				quitfree(); 				f = 0; 				break; 			} 	}  }  void List()//自定义个数建好链表 { 	char a, b, c; 	char v[50];  	bllist(list);//遍历链表 	// 	printf("要增加链表吗(y/n)："); 	scanf("%c", &a); 	if (a == 'y' || a == 'Y') 	{ 		while (getchar() != '\n') continue; 		sclist(list); 		while (getchar() != '\n') continue; 		bllist(list); 	}  	// 	printf("\n要删除链表吗(y/n)："); 	scanf("%c", &b); 	if (b == 'y' || b == 'Y') 	{ 		while (getchar() != '\n') continue; 		printf("输入要删除的数据："); 		scanf("%s", v); 		while (getchar() != '\n') continue; 		shanlist(list, v); 	}  	bllist(list);  	// 	printf("是否要再次遍历(y/n)："); 	scanf("%c", &c); 	if (c == 'y' || c == 'Y') 	{ 		while (getchar() != '\n') continue; 		bllist(list); 	} }  void chalist() { 	char a[50]; 	printf("输入要查找的数据："); 	scanf("%s", a); 	while (getchar() != '\n') continue; 	struct studant* chalist = list; 	while (strcmp(chalist->x, a) != 0) 	{ 		chalist = chalist->next; 		if (chalist == NULL) 			break; 	} 	if (chalist && strcmp(chalist->x, a) == 0)//chalist为NIULL后没有找到数据 	{ 		printf("查找到的数据：\n"); 		printf("%s\n\n", chalist->x); 	} 	else 		printf("\n没有找到指定的数据！\n"); }  void quitfree() { 	struct studant* quit = list; 	struct studant* exit = list->next; 	while (quit != NULL) 	{ 		quit = exit; 		if (quit == NULL && exit == NULL) 		{ 			printf("\n退出程序！\n成功清空链表！！\n"); 			break; 		} 		exit = exit->next; 		free(quit); 	} 	list->next = NULL; }

引用 1 楼 qq_33097303的回复:你把赋空放到后面就不用&&了 是头结点的赋空还是

你把赋空放到后面就不用&&了


原来是局部变量移动到全局变量时，和另一个全局变量名称冲突 重命名就行了


Question: 为啥我这goto语句不执行啊

fflush(stdin);不是针对所有的编译器都有效的，因为对于一些编译器这个函数操作stdin是未定义行为。  建议用getchar();替换fflush();  未执行goto，是因为执行goto语句的条件没满足。很有可能fflush(stdin)没有起作用，建议用getchar();  另外，command是char类型，"yes"是字符串不是字符。这个是一个bug。  #include <stdio.h>  int main () {     double num1,num2;     char character,command;     double value; lable:     printf("请输入第一个数:\n");     scanf("%lf",&num1);     printf("请输入第二个数:\n");     scanf("%lf",&num2);     printf("请输入计算符号\n");     //fflush(stdin);     getchar();    //for '\n'     scanf("%c",&character);     getchar();    //for '\n'     switch(character)     {         case'+':             value=num1+num2;             printf("两式相加结果为：%lf\n",value);             break;         case'-':             value=num1-num2;             printf("两式相减结果为：%lf\n",value);             break;         case'*':             value=num1*num2;             printf("两式相乘结果为：%lf\n",value);             break;         case'/':              value=num1/num2;             printf("两式相除的结果为%lf\n",value);                break;      }     printf("是否还要继续进行运算，请在下方输入y/n\n");     fflush(stdin);     scanf("%c",&command);     getchar();   //for '\n'      //if(command=='yes')     if(command=='y')     {         //fflush(stdin);          goto lable;      }     else         printf("请关闭程序\n");      return 0; }  供参考～

因为判断失败，command只取了'y'。scanf("%c",&command);


Question: C语言输入几行字符然后统计

引用 4 楼 寻开心 的回复:char *p = fgets(buf, sizeof(buf), stdin); //从标准输入读入行 if (p == NULL || buf[0] == '\n') break; //如果EOF或者没有输入数据则结束循环（如果是Ctrl+z则判断p==NULL就可以了） lines++; 这样不行的。  buf开的再大，理论上输入的内容都可能比它还大 这样直接的line ++ 是不对的 fgets可以把回车符读入进来， 要根据这个判断line++ 然后要特别注意最后一行，有可能直接遇到feof而没有遇到回车，那就还需要加上遗爱湖特殊处理最后一行 确实，要考虑输入大于buf长度的情况。 int main(int argc, const char * argv[]) {     int chars=0, words=0, lines=0, whitespaces=0, uppercase=0, lowercase=0, digits=0, flag=0, len=0;     char buf[256];     while (1)     {         char *p = fgets(buf, sizeof(buf), stdin); //从标准输入读入行         if (p == NULL || buf[0] == '\n') break; //如果EOF或者没有输入数据则结束循环（如果是Ctrl+z则判断p==NULL就可以了）         len = (int)strlen(buf);         for (int i=0; i<len; i++)         {             if (buf[i]>='0' && buf[i]<='9')             {                 digits++;             }             else if (buf[i]>='A' && buf[i]<='Z')             {                 uppercase++;                 flag++;             }             else if (buf[i]>='a' && buf[i]<='z')             {                 lowercase++;                 flag++;             }             else if (isspace(buf[i])) {                 whitespaces++;                 if (flag>0)                 {                     words++;                     flag = 0;                 }                 if (buf[i]=='\n') {                     lines++;                     len = 0;                 }             }             chars++;         }     }     if (flag>0) words++;     if (len>0) lines++;     printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", chars, words, lines, whitespaces, uppercase, lowercase, digits);     return 0; }

#include<stdio.h> #include<stdlib.h> #include<string.h>   typedef struct Stat {     int nChars;     int nWords;     int nLines;     int nWhitespaces;     int nUppercase;     int nLowercase;     int nDigits; } Stat;  // 统计每行的内容，如果最后一个字符不是回车'\n'返回1，否则返回0 int statistics (const char * str, Stat * pStat) {     int len = (int) strlen(str);     int bNewWord = 0; // 标记是否是一个新的单词的开始     for ( int i=0; i<len; i++) {         char ch = str[i];         pStat->nChars ++;         if ( ch == '\n')             pStat->nLines ++;         else if (ch == ' ' || ch == '\t') { //空格和tab             pStat->nWhitespaces ++;             bNewWord = 0;         } else if ( '0' <= ch && ch<='9' ) {             pStat->nDigits++;             if ( bNewWord == 0 ) {bNewWord=1; pStat->nWords++;}         } else if ( 'a'<=ch && ch<='z'){             pStat->nLowercase ++;             if ( bNewWord == 0 ) {bNewWord=1; pStat->nWords++;}         } else if ( 'A' <=ch && ch<='Z') {             pStat->nUppercase++;             if ( bNewWord == 0 ) {bNewWord=1; pStat->nWords++;}         } else {             // 标点符号等其他情况，非空白，非数字，非大小写字母的情况             // ! 也作为独立的单词参与统计的话，下面这行就打开，否则注释掉             if ( bNewWord == 0 ) {bNewWord=1; pStat->nWords++;}         }     }     if ( str[len-1] != '\n')         return 1;  // buffer读满了，还没有结束一行的情况；或者eof到了但是没有回车     else         return 0; };  int main() {     Stat st = {0};     FILE * fp = stdin; // 如果是是文件，就fp=fopen什么的自己处理吧     // 可以通过减少BUFERSIZE的大小来测试，一行长度超过buffer的例子 #define BUFFERSIZE 256     char buffer[BUFFERSIZE];     char *p=NULL;     int  value = 0;     // fgets只有在遇到错误或者到达feof的时候返回null     while ( (p = fgets(buffer, BUFFERSIZE, fp)) != NULL ) {         value = statistics(buffer, &st);     };     if (feof(fp)) st.nLines += value;     fclose(fp);     printf("Chars:%d Lines:%d Words:%d Digit:%d Uppercase:%d Lowcase%d\n",\            st.nChars, st.nLines, st.nWords, st.nDigits, \            st.nUppercase, st.nLowercase);     return 0; }

这个也没有特别的地方，只是繁琐了一些 写一个控制程序，用来读取字符流，一次一行，直到遇到EOF， 楼主没有明确来自文件还是来自键盘输入流 再写一个基于一个字符串（一行输入）的统计函数，在控制流程当中调用它，来统计所需的各个情况

调用函数isupper(); islower();isdigit()，isspace()等等

就是一行一行从标准输入读入统计就可以了 不知道你说使用EOF是指什么？是Ctrl+z还是说输入EOF作为输入结束的关键字？ for example int main(int argc, const char * argv[]) {     int chars=0, words=0, lines=0, whitespaces=0, uppercase=0, lowercase=0, digits=0, flag=0;     char buf[256];     while (1)     {         char *p = fgets(buf, sizeof(buf), stdin); //从标准输入读入行         if (p == NULL || buf[0] == '\n') break; //如果EOF或者没有输入数据则结束循环（如果是Ctrl+z则判断p==NULL就可以了）         lines++;          for (int i=0; i<strlen(buf); i++)         {             if (buf[i]>='0' && buf[i]<='9')             {                 digits++;             }             else if (buf[i]>='A' && buf[i]<='Z')             {                 uppercase++;                 flag++;             }             else if (buf[i]>='a' && buf[i]<='z')             {                 lowercase++;                 flag++;             }             else if (isspace(buf[i])) {                 whitespaces++;                 if (flag>0)                 {                     words++;                     flag = 0;                 }             }             chars++;         }     }     if (flag>0) words++;     printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t", chars, words, lines, whitespaces, uppercase, lowercase, digits); }


Question: C语言数组里既有汉字又有数字，怎么比较数组内容是否相同

char * p1 = "不明白你要比较什么"; char p2[] = "不明白你要比较什么"; size_t len = p1_len = strlen(p1); strncmp(p1, p2, p1_len) == 0;  这样就行啊  你写那些循环搞毛线

引用 2 楼 u012538549的回复:直接strncmp就可以比较    汉字也是由二进制组成的  一个汉字占用多个字节，每个字节高位都是1   没有冲突 我用这个方法比较时，完全找不到相同元素，count一直为0,代码如下 for(j=0;j<160;j++)      { 	           fgets(StrLine2[j],1024,fp2);  //读取一行          count=0；          for(i=0;i<110;i++) 		 { 		 	fgets(StrLine1[i],1024,fp1); 			if(strncmp(StrLine2[j],StrLine1[i],3)==0) 				count++;          } 这个是什么原因

用什么方法可以比较类似这样的数组

引用 4 楼 user-3的回复:[quote=引用 3 楼 Lgoloria 的回复:] [quote=引用 2 楼 u012538549的回复:]直接strncmp就可以比较    汉字也是由二进制组成的  一个汉字占用多个字节，每个字节高位都是1   没有冲突 我用这个方法比较时，完全找不到相同元素，count一直为0,代码如下 for(j=0;j<160;j++)      { 	           fgets(StrLine2[j],1024,fp2);  //读取一行          count=0；          for(i=0;i<110;i++) 		 { 		 	fgets(StrLine1[i],1024,fp1); 			if(strncmp(StrLine2[j],StrLine1[i],3)==0) 				count++;          } 这个是什么原因 [/quote]fp1 需要重置  [/quote] 后面跟上rewind(fp1)还是没效果……

用strcmp/strncmp/memcmp都可以比较呢？  调用这些函数也是一个字符一个字符的比较。

引用 3 楼 Lgoloria 的回复:[quote=引用 2 楼 u012538549的回复:]直接strncmp就可以比较    汉字也是由二进制组成的  一个汉字占用多个字节，每个字节高位都是1   没有冲突 我用这个方法比较时，完全找不到相同元素，count一直为0,代码如下 for(j=0;j<160;j++)      { 	           fgets(StrLine2[j],1024,fp2);  //读取一行          count=0；          for(i=0;i<110;i++) 		 { 		 	fgets(StrLine1[i],1024,fp1); 			if(strncmp(StrLine2[j],StrLine1[i],3)==0) 				count++;          } 这个是什么原因 [/quote]fp1 需要重置


Question: 求大神解答为什么会出现这样的错误：LINK : fatal error LNK1104: 无法打开文件“stdio.lib”

还有这个错误：error LNK2019: 无法解析的外部符号 _main，该符号在函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中被引用

补充：用的编译器是VS 2017


Question: C语言打开图片文件

可以使用fopen函数，具体用法可以man或者上网查询。


Question: 关于c语言char型与int型在unsigned条件下的输出值问题。

弄懂了！！谢谢各位这么细心帮我找出错误！

printf 函数是不定参数的，即函数参数没有定义类型， 而且参数类型不固定，而是根据  %d  %s ... 来分析后面的每个参数长度。 所以  如你的写法问题很大  ，  windows  vc，编译器有很大容错性（当然也不是好事 ）,  linux 可能 错的更离谱请强转。 %d  对应 int ,  所以这里要强转 (int)b,    另外：  unsigned int  b = -1  ,  和 int b = -1,  在内存中是一样的。  既然是%d， 都认为是int , 都是 -1

while(++a>0) { b=a; }	 这句到什么时候可以退出循环呢？ 显然是a=0；那么此时b是多少呢， b是0xFF也就是255  至于printf的输出的问题，和itoa都问题，其实都是一个函数的参数过程当中的类型转换的问题 传参都是传递值， 当参数和类型不匹配的时候，怎么处理呢？ 那就是类型转换  无论a是unsigned char还是unsigned int a-1 这个减法本身就是整数减法（ 因为1是整数）， a是0，减法的结果就是-1， 这就没有什么好说的了  差异出现在unsgined char b和unsigned int b上了 前者b 是0xff，后者是0xffffffff 传参的时候，从unsigned char 转换成int的时候， int值就是255 而从unsigned int 到int的时候， 实际上是越界了， int越界的处理结果是自动回绕，结果依然是0xFFFFFFFF的二进制  不用想到那么复杂，最简单的测试如下：    unsigned char bc = 0xff;     unsigned int  bn = 0xffffffff;     int ic = bc;     int in = bn;     printf("%d %d\n", ic, in);

用%u，或者这么理解。 因为char虽然是一字节，但是占用的是int 字节。 当用%d显示的时候，char的高位是0，所以翻译成255了

%d是输出一个有符号的10进制int类型 %u,输出一个10进制的无符号数 所以你的输出格式有问题0XFFFFFFFF就是%d就是-1

unsigned int类型的数据应该用%u输出，如果用%d输出，那么会按照有符号数格式输出。  unsigned char类型的数据用%d输出是属于类型提升，a = -1;即对于unsigned char来讲，是255.因为是无符号数。255提升int类型，即255.


这个表达式等同于取a+4的地址，然后解引用。

好像是指针数组的*a[4]

看不懂就拆开


Question: for还有这样的用法？

连续三个判断，相等且各自不为零。

引用 4 楼 寻开心的回复:for（j=0；p[j]==a[i]&&a[i]&&p[j]；i++，j++）；  等价于  j = 0； for (;  p[j]==a[i]  && a[i] && p[j];  ) {          i++;          j++; }  for（ ；； ）这个语句的两个分号分割出来的三段，就是三个表达式 第一个表达式， 这里的j=0 是最先执行的， 而且只执行一次 然后， 就执行第二表达式， p[j]==a[i]  && a[i] && p[j]  这个表达式的结果决定要不要执行花括号里面的代码 最后都第三个表达式， 是在花括号内语句全部执行完， 再次进行第二个表达式判断之前执行的 所以，拆开那个语句，就是前面给到样子了  p[j]==a[i]  && a[i] && p[j] 是三个bool运算，  而且是短路计算 先判断p[j]==a[i]是不是相同，如果不相同，后面的都不判断直接返回false了 如果相同才继续判断a[i]， 它只要不是0， 都是表示真； 是真就继续后面的判断，否则整个表达式就返回false了 最后才判断p[j]  for（表达式1； 表达式2； 表达式3） {} 三个表达式，都可以是复杂度多个语句，中间用逗号分割的 好感动我真的好感动

for是三个表达式语句，因此中间的那个是判断表达式，虽然由 && &&连起来的，但是判断的是最后的结果。

引用 2 楼 贵阳老马马善福专业维修游泳池堵漏防水工程 的回复:也就是 for (j = 0 ; p[j] == a[i] && a[i] != 0 && p[j] != 0; i++,j++) ; 也就是 j = 0; while (p[j] == a[i] && a[i] != 0 && p[j != 0]) { i++; j++; } 这就是我说的，咱们的大学教C语言的，大多数都是野路子，教学生的不是编程，而是街头杂耍。 对，老师就是念着ppt教我们，几乎没教过怎么写代码

p[j]==a[i]&&a[i]&&p[j] 就是p[j]  and  a[i] 一样 并且都不是0


Question: 哥哥姐姐们有没有会编程计算表达式的值啊，这个程度怎么写呀，刚学C语言不太明白明白

是不是4.8？

5/2 是个考点，整数相除，取商的整数部分。 5%2是另一个考点，取余数，也是整数。

引用 4 楼 木  土  硎的回复:#include <studio.h> int main(){ float f=5.0/2.0; printf("%f",3.6+f+1.2+5%2); return 0; } 好的 谢谢谢谢

引用 2 楼 m0_46466604 的回复:[quote=引用 1 楼 ?Victor.??的回复:]#include<stdio.h> int main() { 	float f; 	f = 5.0/2; 	printf("%f",3.6+f+1.2+5%2); 	return 0; } 没有太具体的要求，写法很多呀 fioat代表什么意思呀  我刚开始学 简单点好复杂的看不懂[/quote] float必须有呀，（先不说double了），不然5/2就得2了，结果不对了，学一学就懂了，至于float是什么,我建议你还是找本书看看吧

引用 1 楼 ?Victor.??的回复:#include<stdio.h> int main() { 	float f; 	f = 5.0/2; 	printf("%f",3.6+f+1.2+5%2); 	return 0; } 没有太具体的要求，写法很多呀 fioat代表什么意思呀  我刚开始学 简单点好复杂的看不懂


Question: 哪里错了(´;︵;`)

#include<stdio.h> #include <stdlib.h> #include <math.h>  int main() 	{ 	int a,b,c; 	scanf("%d %d",&a,&b); //input 23 -150 	c=a+abs(b); 	printf("%d",c); 	return 0; }

#include "stdafx.h" #include<math.h> int main(int argc, char* argv[]) {     int a,b,c;     scanf("%d%d",&a,&b);     //input   23 -150 	printf("%d+%d",a,b);     c=a+abs(b);     printf("%d\n",c);  	return 0; }  不知对不对

解决了，谢谢你。加了个while语录

引用 13 楼 weixin_46371549 的回复:[quote=引用 12 楼 自信男孩的回复:][quote=引用 11 楼 weixin_46371549 的回复:] [quote=引用 8 楼 自信男孩的回复:]#include<stdio.h> #include <stdlib.h>  int main() {     int a,b,c;      scanf("%d,%d",&a,&b);      c=a+abs(b);     printf("%d",c);     return 0; }  供参考～  需要引入<stdlib.h>头文件 还是错误的[/quote]  我已经在Linux下编译运行了，没问题。你说的错误是编译问题，还是运行问题？[/quote] 答案错误，在PTA上显示。[/quote]  上面不是跟你提示了吗？你的scanf中为啥在双引号里加一个逗号呢？你没发现这个问题？

引用 14 楼 m0_46108109的回复:把逗号改成空格 scanf("%d,%d",&a,&b); 这样OK了，谢谢  #include<stdio.h> #include<stdlib.h> #include<math.h>     int main()  {    int a,b,c;    while(scanf("%d%d",&a,&b)!=EOF);     c=a+abs(b);     {         printf("%d",c); }    return 0; }

把逗号改成空格 scanf("%d,%d",&a,&b);

引用 12 楼 自信男孩的回复:[quote=引用 11 楼 weixin_46371549 的回复:] [quote=引用 8 楼 自信男孩的回复:]#include<stdio.h> #include <stdlib.h>  int main() {     int a,b,c;      scanf("%d,%d",&a,&b);      c=a+abs(b);     printf("%d",c);     return 0; }  供参考～  需要引入<stdlib.h>头文件 还是错误的[/quote]  我已经在Linux下编译运行了，没问题。你说的错误是编译问题，还是运行问题？[/quote] 答案错误，在PTA上显示。

引用 11 楼 weixin_46371549 的回复:[quote=引用 8 楼 自信男孩的回复:]#include<stdio.h> #include <stdlib.h>  int main() {     int a,b,c;      scanf("%d,%d",&a,&b);      c=a+abs(b);     printf("%d",c);     return 0; }  供参考～  需要引入<stdlib.h>头文件 还是错误的[/quote]  我已经在Linux下编译运行了，没问题。你说的错误是编译问题，还是运行问题？

引用 8 楼 自信男孩的回复:#include<stdio.h> #include <stdlib.h>  int main() {     int a,b,c;      scanf("%d,%d",&a,&b);      c=a+abs(b);     printf("%d",c);     return 0; }  供参考～  需要引入<stdlib.h>头文件 还是错误的

还是错误的唉😔

#include<stdio.h> #include <stdlib.h>  int main() {     int a,b,c;      //scanf("%d,%d",&a,&b);   //input 50,-50     scanf("%d%d",&a,&b);     //input   23 -150      c=a+abs(b);     printf("%d",c);     return 0; } 供参考～

题目要求测试数据有多组，处理到文件尾！   不知道怎么搞

引用 4 楼 MorgenChen的回复:请把题目要求复制详细点，输出格式是什么样子？ 就这一点。还有这个 输入样例:  在这里给出一组输入。例如：  23 -150  输出样例:  在这里给出相应的输出。例如：  173

引用 4 楼 MorgenChen的回复:请把题目要求复制详细点，输出格式是什么样子？ 输入格式:  测试数据有多组，处理到文件尾。每组测试数据在同一行输入2个整数a,b。  输出格式:  每组输出a+|b|的值

请把题目要求复制详细点，输出格式是什么样子？

引用 2 楼 寻开心的回复:abs是math.h头文件包含的 还是不对唉😔

abs是math.h头文件包含的

a.c: In function ‘main’: a.c:5:9: warning: implicit declaration of function ‘abs’ [-Wimplicit-function-declaration]      c=a+abs(b);          ^~~ a.c:4:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]      scanf("%d,%d",&a,&b);      ^~~~~~~~~~~~~~~~~~~~


Question: 哪里错了，这个？？(´;︵;`)

引用 6 楼 自信男孩的回复:# include<stdio.h> int main() {     int a,b;     scanf("%d %d",&a,&b);      printf("%d + %d = %d\n",a,b,a+b);     printf("%d - %d = %d\n",a,b,a-b);     printf("%d * %d = %d\n",a,b,a*b);     if (b != 0)         printf("%d / %d = %d\n",a,b,a/b);     printf("%d %% %d = %d\n",a,b,a%b);      return 0; }  供参考～  注意b不能为0，另外%是特殊字符，因此用%% 好的，谢谢😜

为什么 是   %%    百度也不知道

可能只写一个或用转义符，编译器实现起来麻烦吧。我也不知道为什么。

引用 2 楼 m0_46108109的回复:printf("%d %% %d = %d\n", a, b, a % b); 为什么是两个%%

printf("%d %% %d = %d\n", a, b, a % b);

a.c: In function ‘main’: a.c:10:17: warning: conversion lacks type at end of format [-Wformat=]      printf("%d % %d = %d\n",a,b,a%b);                  ^ a.c:5:2: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]   scanf("%d %d",&a,&b);   ^~~~~~~~~~~


Question: 这里有c->的形式可以用吗？

谢谢各位  ！

这样用是没问题的。等价于:int b = 5;  因为c是指针，存放的是地址。通过malloc相当于在堆上申请了空间，*c = 5;即将5放到堆上申请的空间里。 int b = 5;b是在栈或数据段申请的空间，并将5放在申请的空间里。

int * c = (int * )malloc(sizeof(int *)); int *和int的大小不一定相等。 .才对应的-> *对应的&

如果c是结构体指针就可以，否则c没有成员


Question: 表达式必须是可操作性的左值问题？

引用 3 楼 千梦一生 的回复:else？ struct再if里 你这行表达式在else里 是这样的吗？那是2张截图  属于代码的不同片段  问题不是这里

else？ struct再if里 你这行表达式在else里 是这样的吗？

数组名不能做左值。可以考虑用strcmp/memcpy实现赋值

number是数组名，数组名不能被赋值。


Question: 求解c语言文件问题

你结构体下面 mess *head 要用malloc 生成 不能直接这样

厉害啊  我的哥0 0

和我一样  都在写成绩管理系统  我在文件的时候困了老半天

看了好几遍也没发现无误

fprintf(fp,"%ld\t%s\t%s\t%d%d\t    %s\t%s\t%s\t\r\n",         p->number,p->name,p->sex,p->year,p->month,p->add,         p->phone,p->mail);         p=p->next;  愁死个人， 这样写，两个数字都挨在一起了。 一个2一个3， 你这样写输出的是23， 回头fscanf能分出来才见鬼了呢 就一个输出整那么多没有的干嘛呢 这种数据文件你还讲究个什么排版啊， 老老实实的去写： fprintf(fp,"%ld %s %s %d %d %s %s %s\n", \          p->number, \          p->name,  p->sex, \          p->year,    p->month, \          p->add,     p->phone,   p->mail);

是不是突破了64k文件长度限制？有多少数据项？通常c语言文件长度不大于64k，否则会出错。需要使用长文件时，需要使用专用的头文件。

用二进制读写，调整一下输出的指针的起始位置

用二进制读写

引用 20 楼 m0_46108109的回复:void save() { 	mess* p = head; 	fp = fopen("d:\\stu.txt", "ab+");  //<<-- 	system("cls"); 	if (head == NULL)   //<<-- 	{ 		printf("保存失败，信息为空。"); 		system("pause"); 		system("cls"); 		return; 	} 	while (p != NULL) 	{ 		fprintf(fp, "%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\t\r\n", 			p->number, p->name, p->sex, p->year, p->month, p->add, 			p->phone, p->mail); 		p = p->next; 	} 	fclose(fp); 	printf("保存成功。\n"); 	system("pause"); 	system("cls"); 	return; } 你数据没有保存对 这里修改了哪里

我有点晕了。现在是数据储存位置错了，提取没有问题

引用 22 楼 寻开心的回复:draw函数启动的时候，屏幕输出什么了？  Start reading data from file ...... 1 陈 ------Finish--------  还是什么也木有 屏幕输出的就是你说的这个

while中间， 在scanf之后，还有一个printf呢，那个有没有输出内容？  如果这里都可以正常输出，那么错误也没有发生在draw函数里面啊 你的那个异常，是执行到哪儿出现的

引用 13 楼 寻开心 的回复:head一开始是NULL，但是你的录入操作等，折腾后就不是NULL了 还有那个n，表示有多少个， 这个要和head一样初始化为0 draw读取到时候，也要对n进行同步，才能计数  你的这个数据文件，你打开看了没有，里面都是什么样子的数据，确定正确吗？ 很是怀疑呢， 前面的input都是错的， 后面的save怎么可能正确执行下来的 如果save执行的不对， 比如，写入的name的长度超长，超过了数组的大小， 读取进来必然会把mess变量撑死 现在是严重的怀疑你的数据文件就不对   还有就是你怎么确定的问题是出在draw函数里面的呢？ 你可以在draw函数上做一点改造：  printf("\nStart reading data from file ......\n")  while(!feof(fp))     {         p=(mess*)malloc(sizeof(mess));         fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",         &p->number,p->name,p->sex,&p->year,&p->month,p->add,         p->phone,p->mail); printf("%d %s\n", p->num, p->name);         p->next=head;         head=p;     } printf("\n------Finish--------\n");   看看屏幕输出了什么  数据错了

fprintf(fp, "%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\t\r\n", 这里错了。

引用 13 楼 寻开心的回复:head一开始是NULL，但是你的录入操作等，折腾后就不是NULL了 还有那个n，表示有多少个， 这个要和head一样初始化为0 draw读取到时候，也要对n进行同步，才能计数  你的这个数据文件，你打开看了没有，里面都是什么样子的数据，确定正确吗？ 很是怀疑呢， 前面的input都是错的， 后面的save怎么可能正确执行下来的 如果save执行的不对， 比如，写入的name的长度超长，超过了数组的大小， 读取进来必然会把mess变量撑死 现在是严重的怀疑你的数据文件就不对   还有就是你怎么确定的问题是出在draw函数里面的呢？ 你可以在draw函数上做一点改造：  printf("\nStart reading data from file ......\n")  while(!feof(fp))     {         p=(mess*)malloc(sizeof(mess));         fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",         &p->number,p->name,p->sex,&p->year,&p->month,p->add,         p->phone,p->mail); printf("%d %s\n", p->num, p->name);         p->next=head;         head=p;     } printf("\n------Finish--------\n");   看看屏幕输出了什么 输出了打印的那两句英文

引用 15 楼 m0_46108109的回复:void save() {     mess *p=head;     fp=fopen("d:\\stu.txt","ab+"); 前面保存的就不对。 难道用二进制打开，可以用文本方式读写吗？ 文件里是我输入的内容

哦哦，我想起来了，这个问题我曾经问过。在linux下只有一种文件格式。 at等同于ab，这个源码应该是linux上的所以没问题。


Question: mmap映射地址访问问题

引用 4 楼 flyfreely2008 的回复:引用 3 楼 自信男孩 的回复:[quote=引用 2 楼 flyfreely2008 的回复:] [quote=引用 1 楼 自信男孩 的回复:] 超过肯定是不能访问的。 问题是根本没超过啊。。。。。您看一下分配的地址空间和我访问的空间 401000000000这个地址很大呀，你说一下起始地址的16进制是多少？确定是这个地址吗？[/quote] 这个是自定义的起始地址呀，64位的机子。。。拜托不懂就不要乱回答啦 让懂得人回答一下吧。。。谢谢啦[/quote] 不回答了，让懂得人给你回答一下。我也等着懂得人，本人“不懂”。

已经解决了，是因为/dev mount的空间太小，所以导致mmap地址即使分配出来了也不可用

我也遇到了类似的问题, 请问是如何定位到这个原因的? mmap分配的时候如果空间不足不是应该返回(void*)-1吗? 是有某种情况, 即使分配成功了但是可用的size跟传入的size不符的情况?

引用 3 楼 自信男孩 的回复:引用 2 楼 flyfreely2008 的回复:[quote=引用 1 楼 自信男孩 的回复:] 超过肯定是不能访问的。 问题是根本没超过啊。。。。。您看一下分配的地址空间和我访问的空间 401000000000这个地址很大呀，你说一下起始地址的16进制是多少？确定是这个地址吗？[/quote] 这个是自定义的起始地址呀，64位的机子。。。拜托不懂就不要乱回答啦 让懂得人回答一下吧。。。谢谢啦

引用 2 楼 flyfreely2008 的回复:引用 1 楼 自信男孩 的回复:超过肯定是不能访问的。 问题是根本没超过啊。。。。。您看一下分配的地址空间和我访问的空间 401000000000这个地址很大呀，你说一下起始地址的16进制是多少？确定是这个地址吗？

超过肯定是不能访问的。


Question: 指针与二维数组，求二维数组的最大值

引用 1 楼 m0_46108109 的回复：pa=a； for（i=0；i<n*m;i++,pa++） pa=a; max=*pa; max<*(p+i); max=*(p+i);谢谢！


Question: C语言排序问题

数组下标从0开始的，有时候for循环要注意下标问题，如果你只开了num个，那么就要从0-（num-1）,若是到num，会数组越界，结果虽然不会改变，但你交到OJ上会爆，所以在开数组的时候一般习惯开目标个数+1，然后从1开始操作

建议多在编译器上编写和测试。

用黑色的，黑色的符合人类思考习惯。 就是先取出第一个，然后和第二个比 取出第n个和n+1比


Question: 大佬们看看我这哪里出错了

#include<stdio.h> #include<math.h>  int main(void) {     int a, b, c;     double delate;     double x1, x2;      //scanf("%f %f %f",&a,&b,&c);     scanf("%d %d %d",&a,&b,&c);     delate = (b * b) - (4 * a *c);      if (delate>0)     {         printf("该二元一次方程组有两个解\n");         x1 = (-b + sqrt(b * b - 4 * a *c))* 1.0/2 * a;         x2 = (-b - sqrt(b * b - 4 * a *c)) * 1.0/2 * a;         //printf("x1 = %f,x2 = %f\n",x1,x2);         printf("x1 = %lf,x2 = %lf\n",x1,x2);     }     else if (delate == 0)     {         printf("该二元一次方程组有一个解\n");         x1 = (-b) / 2 * a;         x2 = x1;         //printf("x1 = %f,x2 = %f\n", x1, x2);         printf("x1 = %lf,x2 = %lf\n", x1, x2);     }      else     {         printf("该二元一次方程组无解\n");      }      return 0; }  供参考～  注意a, b, c定义的都是int  另外，double的输出格式是%lf

x1 = (-b + sqrt(b * b - 4 * a *c))/(2 * a); 这里得加个括号


Question: 请问大佬这个问题

引用 9 楼 自信男孩 的回复:[quote=引用 2 楼 lin5161678 的回复:]  printf("%d\n",strlen(c));        //5 这个才是不确定      printf("%d\n",sizeof(b));        //不确定  sizeof 结果全部确定 注意b的strlen(b)是确定的。因为b指向的是字符串。[/quote]我就当你回复错了

引用 2 楼 lin5161678 的回复:printf("%d\n",strlen(c));        //5 这个才是不确定      printf("%d\n",sizeof(b));        //不确定  sizeof 结果全部确定 注意b的strlen(b)是确定的。因为b指向的是字符串。

引用 7 楼 寻开心 的回复:字符数组的名字被当字符串指针使用的时候， 字符串函数不管它到底是数组还是字符串，只会按照strlen自己的逻辑来处理，从指针指向的地址开始，一直向后找到'\0'为止， 什么时候找到什么时候返回；所以，c数组的有效范围内没有0， strlen找到什么时候找到0，天知道 好的，谢谢大佬，明白了

sizeof是算内存占用量 strlen是遇到0字符才返回长度但是不算0在内 数组就是数组， 只是同样类型的若干个数据连续排列 字符串是遇到0才算结束，定义的常量尾巴都是默认带0的 字符数组可以用来当字符串用，但是毕竟不是字符串， 所以要注意自己补上0——在合适的位置

#include<stdio.h> #include<string.h> int main() {     char a[] = "abcde";     char* b = "abcde";     char c[] = {'a','b','c','d','e'};     printf("%d\n",sizeof(a));      //6  尾巴是有0字符的，也占内存     printf("%d\n",strlen(a));        //5 尾巴0字符不占字符串长度     printf("%d\n",strlen(c));        //5 这个才是没谱的，c数组后面遇到0才会结束strlen的长度     printf("%d\n",sizeof(b));        //不确定 这个是指针类型的内存大小，32位系统下4，64位下是8     printf("%d\n",sizeof("abcde"));  //6 这个同样要算尾巴0的内存空间     return 0; }

引用 1 楼 自信男孩 的回复:对，sizeof是统计数组的长度。数组的长度就会包含'\0'。 而strlen是计算字符串的有效长度，不包括'\0' 我的理解是字符串后面会有'\0' 字符数组没有，这么理解对吗？ 还有 printf("%d\n",strlen(c));这个为什么是不确定呢？

引用 2 楼 lin5161678 的回复:printf("%d\n",strlen(c));        //5 这个才是不确定      printf("%d\n",sizeof(b));        //不确定  sizeof 结果全部确定 抱歉，打错了，请问那个为什么是不确定呢？


Question: [求助求助]删除链表为什么会失败

引用 13 楼 自信男孩的回复:不明白你的意思，你要实现成什么样子的？ 刚刚写查找链表出了问题然后加上了&&就能够运行了因为我只写了while(strcmp(头结点->x，a)!=0)

引用 13 楼 自信男孩的回复:不明白你的意思，你要实现成什么样子的？ 基本都懂了就是为什么while(Freelist && strcmp(freelist->x, a) != 0)为什么要&&freelist

引用 1 楼 自信男孩的回复:#define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <malloc.h> # include <string.h>  struct studant {     char x[50];     struct studant* next; };  //创建链表 <2>   靠插入来完成链表 struct studant* Apex() {     struct studant* AApex = (struct studant*)malloc(sizeof(struct studant));     AApex->next = NULL;      return AApex; }  //创建链表 <1>    先制作链表再来操作链表 struct studant* apex(void) {     int i, g;     struct studant* papex;     papex = (struct studant*)malloc(sizeof(struct studant));     papex->next = NULL;      struct studant* aapex = papex;     aapex->next = NULL;      printf("需要多少个链表：");     scanf("%d", &g);     while (getchar() != '\n');     for (i = 0; i < g; i++)     {         struct studant* paapex = (struct studant*)malloc(sizeof(struct studant));         paapex->next = NULL;         printf("输入第%d个链表内的数据：", i + 1);         scanf("%s", paapex->x);         while (getchar() != '\n');         paapex->next = aapex->next;         aapex->next = paapex;     }     return papex; }  //插入节点 struct studant* zjlist(struct studant* ppapex, char a[50]) {     struct studant* qqapex;     qqapex = (struct studant*)malloc(sizeof(struct studant));     strcpy(qqapex->x, a);     qqapex->next = ppapex->next;     ppapex->next = qqapex;     return qqapex; }  //函数 头插法插入链表（增） void sclist(struct studant* llist) {     char z;     char zz[20];     int i = 1;     printf("是否开始(y/n):");     scanf("%c", &z);     while (getchar() != '\n');     if (z == 'y' || z == 'Y')         while (z == 'y' || z == 'Y')         {             printf("\n链表%d\n", i++);             printf("输入数据：");             //scanf("%s", &zz);             scanf("%s", zz);             while (getchar() != '\n');             zjlist(llist, zz);             printf("\n是否继续(y/n)：");             scanf("%c", &z);             while (getchar() != '\n')                 ;             //if (z == 'y' || z == 'Y');   //判断是否继续创建插入链表             if (z != 'y' || z != 'Y')    //判断是否继续创建插入链表                 break;         } }  //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     if (Freelist->next == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     while (Freelist->x != a)     {         SFreelist = Freelist;         Freelist = Freelist->next;         if (Freelist->next == NULL)         {             break;         }     }     if (Freelist->x == a)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");     }     else         printf("没有相关数据！无法删除！！\n"); }  //打印遍历链表 void bllist(struct studant* bllist) {     struct studant* bblist = bllist->next;//让指针指向头结点的地址然后从下一个节点开始打印（因为头结点不存放数据  会乱码  ）     if (bblist != NULL)         while (bblist != NULL)         {             printf("%s\n", bblist->x);             bblist = bblist->next;         }     else         printf("链表为空！\n"); }  int main(void) {     char a;     char v[50];     struct studant* list = Apex(); //apex();     bllist(list);//遍历链表     //     printf("要增加链表吗(y/n)：");     scanf("%c", &a);     while (getchar() != '\n')         ;     if (a == 'y' || a == 'Y')     {         sclist(list);         bllist(list);     }     //     printf("\n要删除链表吗(y/n)：");     scanf("%c", &a);     while (getchar() != '\n');     if (a == 'y' || a == 'Y')     {         printf("输入要删除的数据：");         //scanf("%s", &v);         scanf("%s", v);         shanlist(list, v);     }     //     printf("是否要再次遍历(y/n)：");     scanf("%c", &a);     printf("\n");     while (getchar() != '\n');     if (a == 'y' || a == 'Y')     {         bllist(list);     }      return 0; } 供参考～ 好像一样啊怎么参考

不明白你的意思，你要实现成什么样子的？

引用 9 楼 自信男孩 的回复:[quote=引用 8 楼 int i； 的回复:] [quote=引用 7 楼 自信男孩 的回复:] //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     //if (Freelist->next == NULL)     if (Freelist == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     //while (Freelist->x != a)     while (Freelist && strcmp(Freelist->x, a) != 0)     {         SFreelist = Freelist;         Freelist = Freelist->next;         /*         if (Freelist->next == NULL)         {             break;         }         */     }     if (strcmp(Freelist->x, a) == 0)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");         return;     }     //else         printf("没有相关数据！无法删除！！\n"); }  供参考～  楼主的程序只能创建一个节点和删除一个节点。这个比较好就是这个改成这样好像会跳过[/quote]  就是只能输入y/Y才能继续呢。[/quote]  注释又不行了

引用 9 楼 自信男孩 的回复:[quote=引用 8 楼 int i； 的回复:] [quote=引用 7 楼 自信男孩 的回复:] //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     //if (Freelist->next == NULL)     if (Freelist == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     //while (Freelist->x != a)     while (Freelist && strcmp(Freelist->x, a) != 0)     {         SFreelist = Freelist;         Freelist = Freelist->next;         /*         if (Freelist->next == NULL)         {             break;         }         */     }     if (strcmp(Freelist->x, a) == 0)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");         return;     }     //else         printf("没有相关数据！无法删除！！\n"); }  供参考～  楼主的程序只能创建一个节点和删除一个节点。这个比较好就是这个改成这样好像会跳过[/quote]  就是只能输入y/Y才能继续呢。[/quote] 为什么在前面单独使用函数后后面if才能打印呢

引用 7 楼 自信男孩 的回复://删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     //if (Freelist->next == NULL)     if (Freelist == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     //while (Freelist->x != a)     while (Freelist && strcmp(Freelist->x, a) != 0)     {         SFreelist = Freelist;         Freelist = Freelist->next;         /*         if (Freelist->next == NULL)         {             break;         }         */     }     if (strcmp(Freelist->x, a) == 0)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");         return;     }     //else         printf("没有相关数据！无法删除！！\n"); }  供参考～  楼主的程序只能创建一个节点和删除一个节点。果然是大佬  就是有时候最后输入遍历不出来

引用 8 楼 int i； 的回复:[quote=引用 7 楼 自信男孩 的回复:] //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     //if (Freelist->next == NULL)     if (Freelist == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     //while (Freelist->x != a)     while (Freelist && strcmp(Freelist->x, a) != 0)     {         SFreelist = Freelist;         Freelist = Freelist->next;         /*         if (Freelist->next == NULL)         {             break;         }         */     }     if (strcmp(Freelist->x, a) == 0)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");         return;     }     //else         printf("没有相关数据！无法删除！！\n"); }  供参考～  楼主的程序只能创建一个节点和删除一个节点。这个比较好就是这个改成这样好像会跳过[/quote]  就是只能输入y/Y才能继续呢。

引用 7 楼 自信男孩 的回复://删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     //if (Freelist->next == NULL)     if (Freelist == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     //while (Freelist->x != a)     while (Freelist && strcmp(Freelist->x, a) != 0)     {         SFreelist = Freelist;         Freelist = Freelist->next;         /*         if (Freelist->next == NULL)         {             break;         }         */     }     if (strcmp(Freelist->x, a) == 0)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");         return;     }     //else         printf("没有相关数据！无法删除！！\n"); }  供参考～  楼主的程序只能创建一个节点和删除一个节点。这个比较好就是这个改成这样好像会跳过

引用 4 楼 自信男孩的回复:你是说测试的结果一样吗？ 结果是的，不知道为什么

早上刚起来还以为我自己写的注释打开电脑发现是改了

你是说测试的结果一样吗？

引用 2 楼 int i； 的回复:[quote=引用 1 楼 自信男孩的回复:]#define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <malloc.h> # include <string.h>  struct studant {     char x[50];     struct studant* next; };  //创建链表 <2>   靠插入来完成链表 struct studant* Apex() {     struct studant* AApex = (struct studant*)malloc(sizeof(struct studant));     AApex->next = NULL;      return AApex; }  //创建链表 <1>    先制作链表再来操作链表 struct studant* apex(void) {     int i, g;     struct studant* papex;     papex = (struct studant*)malloc(sizeof(struct studant));     papex->next = NULL;      struct studant* aapex = papex;     aapex->next = NULL;      printf("需要多少个链表：");     scanf("%d", &g);     while (getchar() != '\n');     for (i = 0; i < g; i++)     {         struct studant* paapex = (struct studant*)malloc(sizeof(struct studant));         paapex->next = NULL;         printf("输入第%d个链表内的数据：", i + 1);         scanf("%s", paapex->x);         while (getchar() != '\n');         paapex->next = aapex->next;         aapex->next = paapex;     }     return papex; }  //插入节点 struct studant* zjlist(struct studant* ppapex, char a[50]) {     struct studant* qqapex;     qqapex = (struct studant*)malloc(sizeof(struct studant));     strcpy(qqapex->x, a);     qqapex->next = ppapex->next;     ppapex->next = qqapex;     return qqapex; }  //函数 头插法插入链表（增） void sclist(struct studant* llist) {     char z;     char zz[20];     int i = 1;     printf("是否开始(y/n):");     scanf("%c", &z);     while (getchar() != '\n');     if (z == 'y' || z == 'Y')         while (z == 'y' || z == 'Y')         {             printf("\n链表%d\n", i++);             printf("输入数据：");             //scanf("%s", &zz);             scanf("%s", zz);             while (getchar() != '\n');             zjlist(llist, zz);             printf("\n是否继续(y/n)：");             scanf("%c", &z);             while (getchar() != '\n')                 ;             //if (z == 'y' || z == 'Y');   //判断是否继续创建插入链表             if (z != 'y' || z != 'Y')    //判断是否继续创建插入链表                 break;         } }  //删除链表 void shanlist(struct studant* freelist, char a[50])//头结点 和 要删除的数据（找到链表）：从头结点开始找到相关数据删除 {     struct studant* Freelist = freelist->next;     struct studant* SFreelist = freelist;     if (Freelist->next == NULL)     {         printf("链表为空！无法删除！！\n");         return;     }     while (Freelist->x != a)     {         SFreelist = Freelist;         Freelist = Freelist->next;         if (Freelist->next == NULL)         {             break;         }     }     if (Freelist->x == a)     {         SFreelist->next = Freelist->next;         free(Freelist);         printf("\n成功删除！！\n");     }     else         printf("没有相关数据！无法删除！！\n"); }  //打印遍历链表 void bllist(struct studant* bllist) {     struct studant* bblist = bllist->next;//让指针指向头结点的地址然后从下一个节点开始打印（因为头结点不存放数据  会乱码  ）     if (bblist != NULL)         while (bblist != NULL)         {             printf("%s\n", bblist->x);             bblist = bblist->next;         }     else         printf("链表为空！\n"); }  int main(void) {     char a;     char v[50];     struct studant* list = Apex(); //apex();     bllist(list);//遍历链表     //     printf("要增加链表吗(y/n)：");     scanf("%c", &a);     while (getchar() != '\n')         ;     if (a == 'y' || a == 'Y')     {         sclist(list);         bllist(list);     }     //     printf("\n要删除链表吗(y/n)：");     scanf("%c", &a);     while (getchar() != '\n');     if (a == 'y' || a == 'Y')     {         printf("输入要删除的数据：");         //scanf("%s", &v);         scanf("%s", v);         shanlist(list, v);     }     //     printf("是否要再次遍历(y/n)：");     scanf("%c", &a);     printf("\n");     while (getchar() != '\n');     if (a == 'y' || a == 'Y')     {         bllist(list);     }      return 0; } 供参考～ 好像一样啊怎么参考[/quote]  代码一样吗？ 我看着是修改了呢？  //scanf("%s", &v);         scanf("%s", v);


Question: 学生班级管理程序求助，谢谢谢谢

谢谢谢谢，我明白了，之前还没注意到原来这里也有问题，谢谢

初学的时候， 不要假定自己的scanf回来的数就一定是对的 scanf之后马上把刚才读入的数printf一次，看看  注意利用好scanf函数都返回值， 如果scanf格式指定输入3个数，正确输入后scanf会返回3， 如果不全正确返回的就是正确获得到的数  以刚才的例子 scanf("%d,%s,%f",&students[i].id,students[i].name,&students[i].score); 如果你输入的是 123 xyz  34 那么scanf返回就是1， 只有第一个id被正确读取到，后面没有遇到逗号，其他的输入都没有正确的被返回 如果你输入的是123,xyz,34 也未必能正确的读取到三个 有的编译器可以，有的编译器会认为xyz,34 都是字符串， 安全带做法，老实的指定scanf（"%d%s%d"）; 输入123 xyz 34这样的最好 非要用逗号， 需要这样指定 scanf("%d,%[^,],%d", &....)

printf("please input id,name,score:"); scanf("%d,%s,%f",&students[i].id,students[i].name,&students[i].score); // 这个scanf都格式要求输入的形式是     123, name, 89 // 如果输入的时候不带逗号，读取不到正确的数字 printf("piease input year-month-day:"); scanf("%d%d%d",&year,&month,&day); // 这个scanf格式的要求是输入 2000 12 20  这里，如果真的按照提示 2000-12-20输入反而是错的,，  会把month和day读成-12和-20 输入格式必须和指定的格式匹配，如果希望用户如数2000-12-20这种 scanf("%d-%d-%d", &year, &month, &day);这样输入2000-12-20才可以正确获得输入

谢谢谢谢！！！

#include<stdio.h> #include<stdlib.h> #include<string.h>   typedef union {     struct{         unsigned int year:12;         unsigned int month:4;         unsigned int day:5;     };     unsigned int value; }DATE;  int compare_date(DATE d1, DATE d2) {     if (d1.value==d2.value)     {         return 0;     }     else if (d1.value<d2.value)     {         return -1;     }     else         return 1; }  typedef enum gender{male,female}GENDER;  typedef struct _student{     int id;     char name[20];     float score;     GENDER gender;     DATE birthday; }STUDENT;  STUDENT students[40]; DATE d; int count=0;     void main() {     //1.输入学生信息：学号，姓名，性别，出生日期，成绩     int i;     char NAME[20];     int year,month,day;       printf ("please input the number of student:");     scanf("%d",&count);      for(i=0;i<count;i++)     {         printf("please input id,name,score:");         scanf("%d,%s,%f",&students[i].id,students[i].name,&students[i].score);         printf("piease input year-month-day:");         scanf("%d%d%d",&year,&month,&day);         d.year=year;         d.month=month;         d.day=day;           printf("please input gender(male=0,female=1):");         scanf("%d", &students[i].gender);         switch(students[i].gender)         {             case male:                 puts("男");                 break;             case female:                 puts("女");                 break;         }     }          //2.查找并显示学生信息     for(i=0;i<count;i++)     {         if(strcmp(students[i].name,NAME)==0)         {             printf("the information of student(id,name,score,birthday,gender):");             for (i=0;i<count;i++)             {                 //printf("id:%s",students[i].id);                 printf("id:%d", students[i].id);                 //printf("name:%d",students[i].name);                 printf("name:%s",students[i].name);                 printf("the birthday of student:");                 printf("%4d-%02d-%02d",d.year ,d.month ,d.day );                 printf("gender:");                 switch(students[i].gender)                 {                     case male:                         puts("男");                         break;                     case female:                         puts("女");                         break;                 }              }         }         else         {             printf("error");         }     }      //3.统计平均成绩和及格率      //4. 查找显示年龄最小的学生的信息；  }  供参考～ 代码有些地方有问题，建议对比看一下自己的问题～  ./test please input the number of student:2 please input id,name,score:1,Lucy,88 piease input year-month-day:2020 3 3 please input gender(male=0,female=1):0 男 please input id,name,score:2,John,99 piease input year-month-day:2021 4 3 please input gender(male=0,female=1):1 女 errorerror 输入的内容。 建议楼主对比一下自己的输入。


想问一下楼主  ，也是vs2019，终端上能用cls ，但是 也遇到了这个问题

楼主怎么解决的啊

引用 1 楼 自信男孩的回复:[quote=引用 楼主 m0_46078443 的回复:] 加了stdlib.h Windows.h Conio.h就是不行，system(pause) 可以用，没有任何报错就是清不了屏 建议在终端上试一下cls看一下能不能执行。如果不可以，建议用clean/clear试试[/quote] 已解决谢谢了

引用 1 楼 自信男孩的回复:[quote=引用 楼主 m0_46078443 的回复:] 加了stdlib.h Windows.h Conio.h就是不行，system(pause) 可以用，没有任何报错就是清不了屏 建议在终端上试一下cls看一下能不能执行。如果不可以，建议用clean/clear试试[/quote] cmd上可以codeblock也可以。。

引用 楼主 m0_46078443 的回复:加了stdlib.h Windows.h Conio.h就是不行，system(pause) 可以用，没有任何报错就是清不了屏 建议在终端上试一下cls看一下能不能执行。如果不可以，建议用clean/clear试试


Question: c

首先能执行printf的条件是y % 3 == 0即是3的倍数。所以是9， 6， 3 因此结果是852；选B。


Question: 程序运行一半自动停止

你贴的代码，和程序的执行有关系吗  贴的这部分代码，还么有执行到就退出了吧， 那贴这些代码有什么用？！


Question: 二级指针两个题目

第一题选C 第二题选D

这主要是考查函数栈局部变量和参数拷贝（值传递）以及指针方面的知识  第一题（答案是C） void f(int **s) //s和mian的r是两个不同函数栈的局部变量，只是值相同（参数复制），也就是r的值==s的值（也就是r和s指向相同的地址，是main的p变量的地址），所以*r==*s（都是相同地址p的内存信息）。 {     int *t=&k;     s=&t;*s=&m; //这里是重新给s赋值，也就是s重新指向了一个和r指向不同的地址（r没变，还是指向原来的地址），所以s和r不再有关联，修改*s不再影响*r。     printf("%d,%d,%d,",k,*t,**s); }   int main() {     int i=3,*p=&i,**r=&p;     f(r);     printf("%d,%d,%d\n",i,*p,**r);//上面说了，r的值没变，所以*r没变（也就是p没变），**r也没变（也就是*p没变）     return 0; }  第二题（答案是D） void f(int **s) //参考第一题的解释 {     int *t=&k;     *s=t;//这里不是给s重新赋值，而是给s指向的地址重新赋值（第一题的解释知道s指向的地址和r指向的地址一样，是main的p变量的地址），所以改变*s也就是改变*r（p的内存信息改变）     printf("%d,%d,%d,",k,*t,**s); }   int main() {     int i=3,*p=&i,**r=&p;     f(r);     printf("%d,%d,%d\n",i,*p,**r); //上面说了*r改变，p也改变（*r就是p），所以*p也就改变了     return 0; }


Question: 太难了

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

和某帖同款代码，一个老师教的吗  诶哦诶福  LF %lf

scanf("%if",&I); 改成 scanf("%lf",&I);

#include <stdio.h>  int main() {     double I;     printf("请输入当月利润\n");     //scanf("%if",&I);     scanf("%lf",&I);     if (I>=0&&I<100000)     {         I=I*0.1;         printf("应发奖金%lf\n",I);     }     else if(I>100000&&I<=200000)     {         I=100000*0.1+(I-100000)*0.75;         printf("应发奖金%lf\n",I);     }     else if(I>200000&&I<=400000)     {         I=100000*0.1+(I-200000)*0.5;         printf("应发奖金%lf\n",I);     }     else if(I>400000&&I<=600000)     {         I=100000*0.1+(I-400000)*0.3;         printf("应发奖金%lf\n",I);     }     else if(I>600000&&I<=1000000)     {         I=100000*0.1+(I-600000)*0.1;         printf("应发奖金%lf\n",I);     }     return 0; } 供参考～  另外，似乎还缺少一个else，对于输入大于1000000的数值确实没有任何输出。


Question: 为什么不能输出东西啊

scanf少一个%吧。 建议直接贴代码，发图片也建议图片不要转向了。

scanf("%lf",&I)  LF

scanf后面应该是%lf，另外缺少yelse，对于大于1000000的输入值确实没有输出内容。


Question: 求大神帮忙看看代码，为啥不能合并

感谢大哥，问题完结

#include <iostream>  using namespace std;  #define ok 1 #define error 0 #define overflow -1 #define maxsize 10  typedef int status; typedef int elemtype;//定义线性表类型  typedef struct{     elemtype*elem;     int length; }sqllist;  status linlist(sqllist &L); status create(sqllist &L); status show (sqllist &L); status insert(sqllist &L,int i,elemtype e); void unio(sqllist &La,sqllist Lb);  int main() {      sqllist list,list2;      if(linlist(list)==ok)         cout<<"初始化完成"<<endl;     else         cout<<"内存溢出"<<endl;      if(linlist(list2)==ok)         cout<<"初始化完成"<<endl;     else         cout<<"内存溢出"<<endl;      cout<<"请创建第一个线性表"<<endl;     if(create(list)==ok)         cout<<"数据输入完成"<<endl;     else         cout<<"数据创建失败"<<endl;      show(list);     cout<<"请创建第二个线性表"<<endl;      if(create(list2)==ok)         cout<<"数据输入完成"<<endl;     else         cout<<"数据创建失败"<<endl;      show(list2);      unio(list,list2);     cout<<"合并以后的线性表为"<<endl;     show(list);      return 0; }  status linlist(sqllist &L) {     L.elem = new elemtype[maxsize];     if(!L.elem)         return overflow;     L.length = 0;      return ok; }  status create(sqllist &L) {     int n;     cout<<"请问你要输入的元素有几个"<<endl;     cin>> n;     if(n > maxsize || n < 0)         return error;      cout<<"你输入的元素"<<endl;     for(int i=0; i<n; i++)         cin>>L.elem[i];      L.length = n;      return ok; }  status insert(sqllist &L,int i,elemtype e) {      //if(i < 1 || i > L.length)     if(i < 1 || i > L.length+1)    //如果插入的是在L之后，那么 i > L.length就不符合有要求了         return error;                                      //i不合法     else if(L.length==maxsize)         return overflow;                                   //i溢出     //else     for(int j = L.length-1;j>=i-1;j--)         L.elem[j+1] = L.elem[j];                             //插入后元素后移      L.elem[i-1] = e;                                     //将新元素e放入第i个位置     L.length++;      //show(L);    //debug     return ok; }  status show (sqllist &L) {     for(int i=0;i<L.length;i++)         cout<<"第"<<i+1<<"个元素是"<<L.elem[i]<<endl;     return ok; }  void unio(sqllist &La,sqllist Lb) {     int i=0,j=0, inc = 0;     //status insert(sqllist &L,int i,elemtype e);     while(i < La.length && j < Lb.length)     {         while(La.elem[i] < Lb.elem[j] && i < La.length)             i++;         if(i < La.length) {             /*             //if(La.elem[i]=Lb.elem[j])             if(La.elem[i] == Lb.elem[j])             j++;             else             {             insert(La,++i, Lb.elem[j]);             j++;             }             */             if (La.elem[i] == Lb.elem[j]) {                 j++;                 continue;             }             insert(La, ++i, Lb.elem[j]);             j++;         }     }     while(j < Lb.length){         //cout<<"+++"<<Lb.elem[j]<<endl;         insert(La, ++i, Lb.elem[j]);         j++;     } } 供参考～  楼主的问题在insert函数里的第一个判断条件。


Question: 指针与循环结构

数组名是数组的首地址，就像char *p = a;时，首地址的值也保存到p中。

数组名可以当成数组的首地址，也就是一个数字，地址可以进行加减运算的。

这个首地址就是Hello的第一个字母H是吧，那么a+1就是往后一个到e，a+2就是到l，最后输出的就是ello！这样？                 llo！

p<a+2表示p指向的地址小于a+2得到的地址，则循环，循环中p指向的地址会增大1个单位（char类型则增大1个字节）

数组名是数组的首地址，地址可以计算，a+2表示a的首地址+2个字节（char类型）的长度的地址


Question: 求助求助，老师留的基础作业

float的精度问题，不是程序计算错误～

浮点数有精度问题，后面就不能百分百准确了


Question: C语言-双向循环链表

引用 1 楼 proorck2019的回复:不错，继续努力。 刚开始接触，做的不对，不好，还请见谅

不错，继续努力。


Question: vs scanf_s 报错

scanf_s("%d %s %f", &stu1.id, stu1.name, sizeof(stu1.name), &stu1.score); \n问题，有点懵，到底要不要像printf那样放换行符啊，不是这两个函数是对应的吗

去掉换行符  就正确了

不需要加换行符

有什么错误呢？ sizeof(stu1.name)改成20试试


Question: 求助

如何提高数据存储、数据查询的效率

引用 2 楼 user-2 的回复：[quote=引用 1 楼 user-2 的回复:] 看看吧  #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM 100   //为测试方便，定义成100个整数，可以根据需要自已改变数量  void RandNumFile() { 	int i = 0, j = 0; 	FILE *fp = fopen("A.txt", "w"); 	if (fp == NULL) 	{ 		printf("文件不存在。\n"); 		return 0; 	}   	srand((unsigned int)time(NULL)); 	for (i = 0; i < NUM; i++) 	{ 		j = rand() % NUM; 		fprintf(fp, "%d", j); 		fprintf(fp, " "); 	} 	fclose(fp); 	printf("文件写入成功。\n"); }  void ReadNumFile(int ArrNum[]) { 	int i; 	FILE *fp1 = fopen("A.txt", "r"); 	if (fp1 == NULL) 	{ 		printf("文件不存在。\n"); 		return 0; 	} 	for (i = 0; i < NUM; i++) 	{ 		fscanf(fp1, "%d", &ArrNum[i]); 	} 	fclose(fp1);	 }  void FindNumToFile(int ArrNum[]) { 	int i,x; 	 	for (i = 0; i < NUM; i++) 	{ 		printf("%d\t", ArrNum[i]); 		if ((i + 1) % 10 == 0) 		{ 			printf("\n"); 		} 	} 	while (1) 	{ 		printf("请输入要查询的数(输入-1退出)：\n"); 		scanf("%d", &x); 		if (x < 0) 		{ 			printf("退出查询！\n"); 			break; 		} 		 		for (i = 0; i < NUM; i++) 		{ 			if (x == ArrNum[i]) 			{ 				printf("%d在文件中。\n", x); 				break; 			} 			/*else 			{ 				continue; 			}*/ 		} 		if (i == NUM) 		{ 			printf("%d不在文件中。\n", x); 		} 	}	 }  int main() { 	int ArrNum[NUM] = { 0 }, x = 0; 	RandNumFile();  	ReadNumFile(ArrNum); 	 	FindNumToFile(ArrNum); 		 	 	printf("\n");	  	system("pause");  	return 0; }   #define _CRT_SECURE_NO_WARNINGS 这是VS2019上用的，如果是devc++，可以去掉这一句[/quote]谢谢你，我试试看

引用 3 楼 自信男孩 的回复：有内存和时间限制吗？即空间复杂度和时间复杂度要求吗？  如果有空间复杂度的要求，可以考虑边读边对比。 如果有实践复杂度的要求，可以先读到内存，再对比。没有限制

引用 1 楼 user-2 的回复:看看吧  #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM 100   //为测试方便，定义成100个整数，可以根据需要自已改变数量  void RandNumFile() { 	int i = 0, j = 0; 	FILE *fp = fopen("A.txt", "w"); 	if (fp == NULL) 	{ 		printf("文件不存在。\n"); 		return 0; 	}   	srand((unsigned int)time(NULL)); 	for (i = 0; i < NUM; i++) 	{ 		j = rand() % NUM; 		fprintf(fp, "%d", j); 		fprintf(fp, " "); 	} 	fclose(fp); 	printf("文件写入成功。\n"); }  void ReadNumFile(int ArrNum[]) { 	int i; 	FILE *fp1 = fopen("A.txt", "r"); 	if (fp1 == NULL) 	{ 		printf("文件不存在。\n"); 		return 0; 	} 	for (i = 0; i < NUM; i++) 	{ 		fscanf(fp1, "%d", &ArrNum[i]); 	} 	fclose(fp1);	 }  void FindNumToFile(int ArrNum[]) { 	int i,x; 	 	for (i = 0; i < NUM; i++) 	{ 		printf("%d\t", ArrNum[i]); 		if ((i + 1) % 10 == 0) 		{ 			printf("\n"); 		} 	} 	while (1) 	{ 		printf("请输入要查询的数(输入-1退出)：\n"); 		scanf("%d", &x); 		if (x < 0) 		{ 			printf("退出查询！\n"); 			break; 		} 		 		for (i = 0; i < NUM; i++) 		{ 			if (x == ArrNum[i]) 			{ 				printf("%d在文件中。\n", x); 				break; 			} 			/*else 			{ 				continue; 			}*/ 		} 		if (i == NUM) 		{ 			printf("%d不在文件中。\n", x); 		} 	}	 }  int main() { 	int ArrNum[NUM] = { 0 }, x = 0; 	RandNumFile();  	ReadNumFile(ArrNum); 	 	FindNumToFile(ArrNum); 		 	 	printf("\n");	  	system("pause");  	return 0; }   #define _CRT_SECURE_NO_WARNINGS 这是VS2019上用的，如果是devc++，可以去掉这一句


Question: switch语句

switch中没有break。当i=1时，跳转到case 1，由于没有break，所以case 2，case 3和default都会执行。当i=2时，跳转到case 2,由于没有break，因此case 3和default都会执行；当i=3时，一次类推～

引用 6 楼 weixin_46457534的回复:[quote=引用 1 楼 user-5 的回复：]首先我们看到i=1，进入循环之后case 1，就执行k+=1这个语句，然后紧接着执行k+=2，再紧接着执行k+=3，最后输出k 接下来我们i=2进入循环，直接到case 2，执行k+=2，紧接着执行k+=3，输出k 最后i=3进入循环，直接执行k+=3，输出k 之所以会执行与case什么无关的内容是因为你没有在每个case后面加一句break；为什么第二次会直接到case 2，第三次会直接到default呢？[/quote] 因为case相当于if，在case 1部分i==2，不等于，所以就跳过了。

swith(i)就是判断i是什么就会跳到相应的case去啊 比如i是1，就跳到case 1，i是2就跳到case 2，等等。但是如果case没有break，就会继续执行下一个case，比如i是1，执行完case 1后，因为没有break，就会继续执行case 2，等等。如果希望i是1的时候只执行case 1，那么要在case 1的最后加break，即 case 1: k+=1; break;

引用 4 楼 qybao 的回复：算了，就剩最后一个循环，直接也写了吧 每次循环输出一个值 第一次循环i==1，进入case1，计算得到k=0+1=1，因为case没有break，继续进入case2，计算得k=1+2=3，因为没有case没有break，继续进入default，计算k=3+3=6，然后执行打印，6 第二次循环，i==2，case1不满足，跳过，进入case2，计算k=6+2=8，因为case没有break，继续进入default，计算k=8+3=11，然后执行打印，11 第三次循环，i==3，case1，case2不满足，进入default，计算k=11+3=14，然后执行打印，14请问这是怎么判断case是否满足的呢？

引用 1 楼 user-5 的回复：首先我们看到i=1，进入循环之后case 1，就执行k+=1这个语句，然后紧接着执行k+=2，再紧接着执行k+=3，最后输出k 接下来我们i=2进入循环，直接到case 2，执行k+=2，紧接着执行k+=3，输出k 最后i=3进入循环，直接执行k+=3，输出k 之所以会执行与case什么无关的内容是因为你没有在每个case后面加一句break；为什么第二次会直接到case 2，第三次会直接到default呢？

请问这是怎么判断case是否满足的呢？

是不是因为没加break所以搞不懂 如果不加break,就会把剩下的也执行了


Question: 【TJOI2013】单词，一个神奇的问题

#include<stdio.h> #include<string.h> int cheak(char *a,char *b)//从b中找a {     int la,lb,i,j,flag,sum=0;     la=strlen(a);     lb=strlen(b);     for(i=0;i<=lb-la;i++)//遍历i遍     {         flag=1;         j=0;         while(j<la)//j表示a[a]的第j个字符         {             if(a[j]!=b[i+j]){flag=0;break;}             j++;         }         if(flag) sum++;     }     return sum; }  int main() {     int i,j,sum,n;     char *a[201];      scanf("%d",&n);     for(i=0;i<n;i++) {         a[i] = (char *)malloc(sizeof(char) * 128);         if (!a[i])             exit(0);         scanf("%s",a[i]);     }     for(i=0;i<n;i++)     {         sum=0;         for(j=0;j<n;j++)             sum=sum+cheak(a[i],a[j]);//从aj中找ai         printf("%d\n",sum);     }     for (i = 0; i < n; i++)         free(a[i]);     return 0; }  供参考～  出现段错误是必然的。因为a是野指针数组。使用之前需要先申请空间，其实就是让指针指向可读可写的内存位置，堆是其中的内存。

建议你做oj题目不要用指针，直接全局就行，考虑不好的话就会出现野指针或者内存泄漏，都会报RE

这个指针数组的每个元素都是野指针


Question: 大佬请看看

引用 8 楼 寻开心 的回复:for (int I=0; I<5; I++)     for(j=5-i; j<6; j++ )   第一轮最后两个比； 第二轮，最后三个比； 第三轮，最后四个比， .... 它能保证，最后都若干个数都是排好大小的 谢谢大佬，我最近脑子总是很混乱

i到5就可以了

验证最好的例子是，想升序，demo就用降序的例子

for (j = 5 - i; j < 6; j++) 二层循环有问题。  for (j = 0; j < 6-i-1; j++)     if (a[j] > a[j+1]) {     xxxx }

答案是没有问题的，就是内层循环和平时写的不太一样，效果是一样的 正常的话是for(int j=0;j<5-i;j++)

引用 2 楼 寻开心 的回复:嗷， 不对，写的有问题  j=5-i，  i可以是5的， 那是j是0，   if (a[j] < a[j - 1]) 这个j-1 就成-1了  想法是可以的， 但是写法是错的 j<6改成j>0?

是对的 只是泡泡是朝下冒的， 外星球的逻辑呗


Question: 新人小白

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

可以拓宽一下知识，书本上知识点讲的不够详细，可以考虑买点书籍，从其他书上可以找到课本上讲的不细的地方。 编程主要还是理论和实践相结合，多用实践去检验和验证理论～

我也是大二，嘻嘻，自己学呗，课本上学不到啥的，可以相互交流


Question: 【新手求助】程序运行出现乱码

scanf是格式化输入函数，所谓格式化，就是scanf的第一个参数里（双引号里）是什么就要输入什么。 建议楼主对比一下自己的输入

scanf("\"%s\"",name);修改为scanf("%s",name) 或者输入时输入："name"试试

引用 1 楼 m0_46108109 的回复:为什么用两个引号？ 我猜楼主是想输出“ ”，想用转义字符

输入不要瞎写，里面只能是“%s”,把多余去掉就能得到想要的

为什么用两个引号？


Question: 都有什么可以重复定义，重复定义的后果是什么？

谢谢，我有点明白了。 假设一个头文件被多个源文件引用。 我和这种情况搞混了。  这样每个源文件中被定义的同名变量，都有自己的文件域。

你的代码里面， 那些函数都是声明，并不是定义 变量都是定义， 但是不同时#include 两个头文件，也不会有冲突   extern int i; 这样就是声明， 就不会有冲突  #define对应的部分才是宏定义

#define是可以重复定义的啊 后者替代前者  函数，变量可以重复声明，但是不能重复定义 宏不是，宏是可以重复的 编译器会给警告，但是可以继续用的

重定义应该编译都不会通过吧，如果重定义了，那么应该用哪个呢？编译器也很为难吧，程序不能出现是是非非，真真假假的情况～


Question: 求教大佬哪里错了

大家不用再回复了，我知道哪里有问题了 C的指针移动到下一个的时候，应该先移动pa指针，再把C链接到pb，不能反过来，否则pa的指针被改变了

引用 10 楼 寻开心的回复:哦，sorry，我看错了。 要求是：  a1 b1 a2 b2..... 还以为是a1 a2 ...am  bm+1，...bn呢  这样的话你的代码没看出别的问题，除了后面的free    //  free(A);     //  free(B);  改成    A->next = NULL;    B->next = NULL; 因为A和B都是传参进来的， 你在这里free他们， 并不能把结果通过参数带回去， 调用者并不知道A和B已经变成了野指针了   而且这种写法的前提假定链表都具有空的头节点的，因为A和B本身（头结点）并么有被挂到C的下面呢 就是因为一直错所以再随便写了几行上去 不管了，这个平台经常各种bug，不过谢谢你啦(*°∀°)=3

引用 8 楼 寻开心的回复:C利用A和B都空间构成， 这句话怎么解释  他们的指针和他们的内存，直接使用一个头，那么是不是从头到尾都带过来了呢  A是一列火车，B是一列火车， C是一个空车头 你把A车头拿走，把第一节车厢挂C后面，是不是C就是整个A原来的全部车厢了呢 C利用AB的结点构成，意思就是把AB每个结点往C上面放，就相当于把AB两只火车每节车厢都拆开，然后一个一个往C后面接

引用 6 楼 寻开心的回复:我怎么觉得是下面的这种逻辑才对呢 void lnk_merge(LinkList A, LinkList B, LinkList C) {     if (A->next) {                // 如果A有数据          C->next = pa;         // 那么C下，挂的必然是A的数据          A->next = NULL;    // 而无论何种情况，A下的所有数据都要移交到C的          if ( B->next ) {         // 如果B下有数据， A和B都要起头并进比较谁更长                Node * pA=A, Node * pB=B;               while (pA->next && pB->next ) {  // 同步比较谁更长                     pA = pA->next;                     pB = pB->next;               }               if ( pB->next ) {                   // A到头了，B还有                   pA->next = pB->next;     // B的后半截接到A的后面                   pB->next = NULL;           // B到此截断               } else if ( pA->next ) {                  //B到头了，A还有。 什么也不需要做； 可以删除，留此只是做说明               } else {                  // A和B等长，也不需要做什么；可以删，留此也是做说明而已               }          }      }     else if (B->next) {  // A没有数据，那么如果B有数据， B数据挂到C下面，B情况        C->next = B->next;        B->next = NULL;     } } 题目意思是要链表AB轮流插入C哦，我看你的想法好像是把B接到A的尾巴

引用 4 楼 自信男孩的回复:[quote=引用 3 楼 DYf3244 的回复:] [quote=引用 1 楼 自信男孩 的回复:] 建议直接贴代码，可以帮你调试一下～ void lnk_merge(LinkList A, LinkList B, LinkList C) {     Node *pa, *pb, *r;     pa = A->next;     pb = B->next;     r = C;     if (A->next == NULL && B->next == NULL)         return;     while (pa && pb) {         r->next = pa;         r = pa;         r->next = pb;         r = pb;         pa = pa->next;         pb = pb->next;     }     if (pa) {         r->next = pa;     } else {         r->next = pb;     }     free(A);     free(B); }[/quote] 所有的代码，创建和显示的功能呢？[/quote] 没有，就是系统用数据检测你的函数能不能实现功能

引用 3 楼 DYf3244 的回复:[quote=引用 1 楼 自信男孩 的回复:] 建议直接贴代码，可以帮你调试一下～ void lnk_merge(LinkList A, LinkList B, LinkList C) {     Node *pa, *pb, *r;     pa = A->next;     pb = B->next;     r = C;     if (A->next == NULL && B->next == NULL)         return;     while (pa && pb) {         r->next = pa;         r = pa;         r->next = pb;         r = pb;         pa = pa->next;         pb = pb->next;     }     if (pa) {         r->next = pa;     } else {         r->next = pb;     }     free(A);     free(B); }[/quote] 所有的代码，创建和显示的功能呢？

引用 1 楼 自信男孩 的回复:建议直接贴代码，可以帮你调试一下～ void lnk_merge(LinkList A, LinkList B, LinkList C) {     Node *pa, *pb, *r;     pa = A->next;     pb = B->next;     r = C;     if (A->next == NULL && B->next == NULL)         return;     while (pa && pb) {         r->next = pa;         r = pa;         r->next = pb;         r = pb;         pa = pa->next;         pb = pb->next;     }     if (pa) {         r->next = pa;     } else {         r->next = pb;     }     free(A);     free(B); }

引用 1 楼 自信男孩的回复:建议直接贴代码，可以帮你调试一下～ 这个是我们学校的一个网站，就只是写一个函数实现某个功能

建议直接贴代码，可以帮你调试一下～


Question: C语言编程

谢谢大家的帮忙，问题解决啦

int num=531; 改成  int num=0; scanf(“%d”, &num); 就可以了

把赋值改成输入不就行了

引用 1 楼 自信男孩 的回复：#include <stdio.h>  void print_number(int n);  int main(void) {     int num = 531;      print_number(num);      printf("\n");      return 0; }  void print_number(int n) {     if (n == 0)         return;      print_number(n/10);     printf("%d ", n % 10); }  供参考～如果是从键盘输入，用scanf的话，请问怎么改呢

那如果是从键盘输入任意数的话，请问该怎么改呢？