Jack's Blog

流淌的心,怎能阻拦,吹来的风,又怎能阻挡。

C语言学习四

C语言中main函数return的总结

在函数中,如果碰到return 语句,那么程序就会返回调用该函数的下一条语句执行,也就是说跳出函数的执行,回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句,那么整个程序就会停止,退出程序的执行。

return是C++预定义的语句,它提供了种植函数执行的一种放大。当return语句提供了一个值时,这个值就成为函数的返回值.

说到return,有必要提及主函数的定义,下面是从网络上找到的资料,好好消化吧,对了解主函数中返回值的理解有很大的帮助.

很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着 The definition void main( ) { /* ... */ } is not and never has been C++, nor has it even been C.( void main( ) 从来就不存在于 C++ 或者 C )。下面我分别说一下 C 和 C++ 标准中对 main 函数的定义。


1. C
在 C89 中,main( ) 是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的经典巨著 The C programming Language 2e(《C 程序设计语言第二版》)用的就是 main( )。不过在最新的 C99 标准中,只有以下两种定义方式是正确的:
int main( void )
int main( int argc, char *argv[] )
(参考资料:ISO/IEC 9899:1999 (E) Programming languages — C 5.1.2.2.1 Program startup)
当然,我们也可以做一点小小的改动。例如:char *argv[] 可以写成 char **argv;argv 和 argc 可以改成别的变量名(如 intval 和 charval),不过一定要符合变量的命名规则。

如果不需要从命令行中获取参数,请用int main(void) ;否则请用int main( int argc, char *argv[] ) 。
main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统)。

如果 main 函数的最后没有写 return 语句的话,C99 规定编译器要自动在生成的目标文件中(如 exe 文件)加入return 0; ,表示程序正常退出。不过,我还是建议你最好在main函数的最后加上return 语句,虽然没有这个必要,但这是一个好的习惯。注意,vc6不会在目标文件中加入return 0; ,大概是因为 vc6 是 98 年的产品,所以才不支持这个特性。现在明白我为什么建议你最好加上 return 语句了吧!不过,gcc3.2(Linux 下的 C 编译器)会在生成的目标文件中加入 return 0; 。

2. C++
C++98 中定义了如下两种 main 函数的定义方式:
int main( )
int main( int argc, char *argv[] )
(参考资料:ISO/IEC 14882(1998-9-01)Programming languages — C++ 3.6 Start and termination)
int main( ) 等同于 C99 中的 int main( void ) ;int main( int argc, char *argv[] ) 的用法也和 C99 中定义的一样。同样,main 函数的返回值类型也必须是int。如果main函数的末尾没写return语句,C++98 规定编译器要自动在生成的目标文件中加入 return 0; 。同样,vc6 也不支持这个特性,但是 g++3.2(Linux 下的 C++ 编译器)支持。

3. 关于 void main
在 C 和 C++ 中,不接收任何参数也不返回任何信息的函数原型为“void foo(void);”。可能正是因为这个,所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的!main 函数的返回值应该定义为 int 类型,C 和 C++ 标准中都是这样规定的。虽然在一些编译器中,void main 可以通过编译(如 vc6),但并非所有编译器都支持 void main ,因为标准中从来没有定义过 void main 。g++3.2 中如果 main 函数的返回值不是 int 类型,就根本通不过编译。而 gcc3.2 则会发出警告。所以,如果你想你的程序拥有很好的可移植性,请一定要用 int main 。

4. 返回值的作用
main 函数的返回值用于说明程序的退出状态。如果返回 0,则代表程序正常退出,否则代表程序异常退出。下面我们在 winxp 环境下做一个小实验。首先编译下面的程序:
int main( void )
{
return 0;
}
然后打开附件里的“命令提示符”,在命令行里运行刚才编译好的可执行文件,然后输入“echo %ERRORLEVEL%”,回车,就可以看到程序的返回值为 0 。假设刚才编译好的文件是 a.exe ,如果输入“a && dir”,则会列出当前目录下的文件夹和文件。但是如果改成“return -1”,或者别的非 0 值,重新编译后输入“a && dir”,则 dir 不会执行。因为 && 的含义是:如果 && 前面的程序正常退出,则继续执行 && 后面的程序,否则不执行。也就是说,利用程序的返回值,我们可以控制要不要执行下一个程序。这就是 int main 的好处。 如果你有兴趣,也可以把 main 函数的返回值类型改成非 int 类型(如 float),重新编译后执行“a && dir”,看看会出现什么情况,想想为什么会出现那样的情况。顺便提一下,如果输入 a || dir 的话,则表示如果 a 异常退出,则执行 dir 。


5. 那么 int main(intargc,char*argv[],char*envp[])呢?
  这当然也不是标准 C 里面定义的东西!char*envp[] 是某些编译器提供的扩展功能,用于获取系统的环境变量。因为不是标准,所以并非所有编译器都支持,故而移植性差,不推荐使用。
到了这里,你应该了解为什么主函数定义为 int返回类型,而且函数体里面有return 0;这个语句了吧.
下面具体说说我对return的应用的理解。

只要一个函数的返回值是数字型的,那么就可以返回0(即return 0),其实你返回多少都没问题。一 般情况下,C++做出来的函数都要求返回一个值,当函数执行正常,且达到了一般情况下的目的,那么就返回0表示正确的调用了该函数,这个0就是返回给主调 函数以通知没有出错的;如果函数调用中出错,或者没有按照一般情况执行,那么就返回1,以告知主调函数采取响应策略;如果你在某个函数所在类的定义所在的 头文件中定义了一组状态值(一般都是负整数),那么函数就可以返回不同的值以告之主调函数具体发生了什么异常或错误,这种情况一般用于函数功能独立性较差 的的情况。所以一般不鼓励把函数返回类型定义为void,至少返回应该是int,而在函数的最后加上return 0.语句:
int func(参数列表)
{
……
……
……
Return 0;
}
在函数中,如果碰到return 语句,那么程序就会返回调用该函数的下一条语句执行,也就是说跳出函数的执行,回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句,那么整个程序就会停止,退出程序的执行。
如果你定义一个函数有返回类型,可以想下面那样调用:
int func()
{
int value;
……
……
……
return value;
}
int main()
{
int intvalue;
intvalue=func();
……
……
teturn 0;
}


return语句后面具体是什么内容,这就要具体情况具体分析了:
(1) 在返回类型是char的函数中,return后应该是char类型的值;
(2) 在返回类型是int的函数中,如果是要停止函数的调用,最好应该为0;其他的按照你的目的而定,只要是int 类型就行了
(3) 在返回类型是结构类型的函数中,return后应该是结构的一个实例对象。
总之,函数定义为什么样的返回类型,该函数中return后就应该是相应类型的值。

C语言学习三

二元一次方程解法

#include<stdio.h>
#include<math.h>
#define eps 1e-6
main()
{
    float a,b,c,d;
    printf("Please enter the coefficients a,b,c:");
    scanf("%f,%f,%f",&a,&b,&c);
    if(a==0)
    printf("It is not a quadratic equation!\n");
    else
    {
        d=sqrt(fabs(b*b-4*a*c));
        if(fabs(b*b-4*a*c)<eps)
        printf("x1 = x2 = %.2f\n",(-b+d)/2/a);
        else if(b*b-4*a*c>eps)
        printf("x1 = %.2f, x2 = %.2f\n",(-b+d)/2/a,(-b-d)/2/a);
        else
        printf("x1 = %.2f+%.2fi, x2 = %.2f-%.2fi\n",-b/2/a ,d/2/a ,-b/2/a ,-d/2/a);
    }
}

注意:在这个程序中,最好不要用pow函数

因为:pow是有精度损失的

          计算机没这么聪明,能判断出你的是int型pow,计算机全部当double处理了

pow(2,2) = 3.999999999
pow(2,2) + 0.05 = 4.0499999
然后强制转化就会成为4了

eg

for(i=1;i<=  (int)(pow(m,1.0/3)+0.05); i++)

附上第一次的麻烦代码:

#include<stdio.h>
#include<math.h>
#define   EPS 1e-6
#include "windows.h"
main()
{
    float a,b,c;
    float d;
    printf("Please enter the coefficients a,b,c:");
    scanf("%f,%f,%f",&a,&b,&c);
    d=sqrt(b*b-4*a*c);
    if(a==0)
    printf("It is not a quadratic equation!\n");
    else{
    if(b*b-4*a*c==0)
    printf("x1 = x2 = %.2f\n",(-b+d)/(2*a));
    else if(b*b-4*a*c>0)
    printf("x1 = %.2f, x2 = %.2f\n",(-b+d)/(2*a),(-b-d)/(2*a));
    else
    printf("x1 = %.2f+%.2fi, "  "x2 = %.2f-%.2fi\n",-b/(2*a),sqrt(fabs(b*b-4*a*c))/(2*a),-b/(2*a),sqrt(fabs(b*b-4*a*c))/(2*a));
         
    }


 

C语言学习二

1.

亲密数_1
2500年前数学大师毕达哥拉斯就发现,220与284两数之间存在着奇妙的联系:
220的真因数之和为:1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为:1+2+4+71+142=220
毕达哥拉斯把这样的数对称为相亲数。

相亲数,也称为亲密数,如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。
从键盘任意输入两个整数m和n,编程判断m和n是否是亲密数。若是亲密数,则输出“Yes!”,否则输出“No!”

程序运行示例1
Input m, n:
220,284↙
Yes!

程序运行示例2Input m, n:
224,280↙
No!

输入格式: "%d,%d"
输出格式:
输入提示信息:"Input m, n:\n"
输出提示信息:"Yes!\n"
              "No!\n"

 

#include<stdio.h>
judgeclose(a,b);
main()
{
    printf("Input m, n:\n");
    int m,n;
    scanf("%d,%d",&m,&n);
    if(judgeclose(m,n)==1)
    printf("Yes!\n");
    else
    printf("No!\n");
}
judgeclose(a,b)
{
    int i,j,k=0;
    int s[20]={0},t[20]={0},e[20]={0},f[20]={0};
    for(i=1;i<=a;i++)
        for(j=2;j<a;j++)
        {
            if (i*j==a)
            {
            s[k]=i;
            t[k]=j;
            k++;
            }
        }
     for(i=1;i<=b;i++)
        for(j=2;j<b;j++)
        {
            if (i*j==b)
            {
            e[k]=i,f[k]=j;
            k++;
            }
        }
        int s1=0,s2=0;
    for(i=0;i<20;i++)
    {
        s1+=s[i]+t[i];
        s2+=e[i]+f[i];
    }
   s1=s1/2+1;
   s2=s2/2+1;
    if(s1==b&&s2==a)
        return 1;
    else return 0;
}

看我写的这串垃圾代码。。。

要是考试肯定半个小时构思+写肯定写不完。。。

再看看同一类型题大神的方法:

2.

链接)一个数对(x,y)是亲和数对,当且仅当 x 的非自身的因数之和等于 y,且 y 的非自身的因数之和等于 x。如果(x,y)是亲和数对,那么认为(y,x)是与之相同的亲和数对。若 A<=x<=B,则称亲和数对(x,y)在[A,B]范围内。现输入范围 A 和 B,求 [A,B] 内所有亲和数对个数。例如 [200,1200] 内有两个亲和数对 (220,284) 和 (1184,1210),因为 220 的非自身因数和 1+2+4+5+10+11+20+22+44+55+110=284,284 的非自身因数之和为 1+2+4+71+142=220。
解一:解法骨架是枚举 [A,B] 范围内所有 x,算出 x 的非自身正因数之和 y(y < x),若 y 的非自身因数之和为 x,则代表找到了一个亲和数对。于是得到了一个直观的朴素解法。
解二:但显然上述解法效率过低。为了避免重复计算,我们创建一个 res[x] 数组保存 x 的因子和。于是得到了比解一快得多的解法。
解三:但是上述解法仍然太慢。问题在哪里?容易知道,时间主要耗费在了计算因子上(% 和 / 是同一个CPU指令,耗费时间相同)。我们不妨换一种思维方式,枚举因子 i,并把因子 i 加到 res[i*j] 里面,当枚举结束时,res[x] 就是 x 的因子和。这个方法快在两个方面:(1)机器算乘法本来就比除法快;(2)没有多余的整除判断。于是我们得到了最快的解法,并且代码比上面两种解法更为简洁。下面的代码利用了全局变量默认为空,没有 memset(res, 0, sizeof res)。

#include <stdio.h>
int res[100000005];
int main() {
  int A, B, ans=0;
  scanf("%d%d", &A, &B);
  for(int i = 1; i <= B; ++i)
    for(int j = 2; i*j <= 2*B; ++j)
      res[i*j] += i;
  for(int x = A; x <= B; ++x)
    if(res[x] > x && res[res[x]] == x) ++ans;
  printf("%d\n", ans);
  return 0;
}

需要说明的是

(要运行这个程序,我们需要在C99并添加新的头文件或C++编译器下进行!)

于是差距就出现了:手动滑稽hhh

Plus:C++真的比C语言简便好多啊

From:Kai

3.

完全数
完全数(Perfect Number),又称完美数或完数,它是指这样的一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和,恰好等于它本身,即m的所有小于m的不同因子(包括1)加起来恰好等于m本身。注意:1没有真因子,所以1不是完全数。计算机已经证实在10300以下,没有奇数的完全数。例如,因为6 = 1 + 2 + 3,所以6是一个完全数。
从键盘任意输入一个整数m,编程判断m是否是完全数。若m是完全数,则输出“Yes!”,并同时打印出每一个完美数的全部因子,以验证这个数确实是一个完美数。若m不是完全数,则输出“No!”
程序运行示例1
Input m:
28↙
Yes!
1,2,4,7,14

程序运行示例2
Input m:
6↙
Yes!
1,2,3

程序运行示例3
Input m:
1↙
No!

输入信息提示:"Input m:\n"
输入格式: "%d"

输出格式: "%d"
输出因子时用逗号间隔,格式为:  ","
判断是完全数,输出信息提示:"Yes!\n"
判断不是完全数,输出信息提示: "No!\n"

//有了上一道题作为基础,这道题就显得很简单了//

#include<stdio.h>
judgetrue(a);
main()
{
    printf("Input m:\n");
    int m;
    scanf("%d",&m);
    judgetrue(m);
}
judgetrue(a)
{
    int i,j,k=0;
    int s[20]={0},t[20]={0};
    for(i=1;i<=a;i++)
        for(j=2;j<=a;j++)
        {
            if (i*j==a)
            {
            s[k]=i;
            t[k]=j;
            k++;
            }
        }
    int s1=0;
    for(i=0;i<20;i++)
    {
        s1+=s[i];
    }
    if(s1==a)
    {
        printf("Yes!\n");
        for(i=0;i<20;i++)
        {
            if(s[i]!=0)
           {
               printf("%d",s[i]);
               if(s[i+1]!=0)
                printf(",");

           }
        }

    }
    else
    printf("No!\n");
}

4.

五个水手在岛上发现一堆椰子,先由第1个水手把椰子分为等量的5堆,还剩下1个给了猴子,自己藏起1堆。然后,第2个水手把剩下的4堆混合后重新分为等量的5堆,还剩下1个给了猴子,自己藏起1堆。以后第3、4个水手依次按此方法处理。最后,第5个水手把剩下的椰子分为等量的5堆后,同样剩下1个给了猴子。请用迭代法编程计算并输出原来这堆椰子至少有多少个。
**输出格式要求:"y = %d\n"

#include "stdio.h"
int can(int k)
{
   int i;
   for (i=1;i<=5;i++)
   {
       if ((k-1)%5!=0||k<  5) return 0;
       k=(k-1)/5*4;
   }
   return 1;
}
int main()
{
   int ans=1;
   while (!can(ans)) ans++;
   printf("y = %d\n",ans);

   return 0;
}

5.求1000内的

#include<stdio.h>
#define m 1000
judgetrue(a);
main()
{
    int i;
    for(i=2;i<=m;i++)
    judgetrue(i);
}
judgetrue(a)
{
    int i,j,k=0;
    int s[100]={0};
    for(i=1;i<=a;i++)
        for(j=2;j<=a;j++)
        {
            if (i*j==a)
            {
            s[k]=i;
            k++;
            }
        }
    int s1=0;
    for(i=0;i<100;i++)
    {
        s1+=s[i];
    }
    if(s1==a)
    {
        printf("\n%5d\n",s1);
        for(i=0;i<20;i++)
        {
            if(s[i]!=0)
           {
               printf("%5d",s[i]);
           }
        }

    }
    else;
}

你可以发现:我每个程序都是在原程序的基础上进行修改而成的。

所以我把这些程序上传在了这个博客上,以备后事之需。

C语言练习一

1.

奥运参赛国出场次序:
输入奥运会参赛国国名,并按照字典序对其进行排序。
要求:参赛国数量不超过150个,每个国家的名字不超过9个字符。
提示:‘\0’占一个字符。

#include <string.h>
#include <stdio.h>
#define N 151
#define MAX_LEN 10
void SortString(char str[][MAX_LEN], int n);

int main()
{
    int i, n;
    char name[N][MAX_LEN];
    printf("How many countries?");
    scanf("%d",&n);
    getchar();
    printf("Input their names\n");

    for(i=0;i<n;i++)
        gets(name[i]);

    SortString(name, n);
    printf("Sorted results:\n");
    for(i=0;i<n;i++)
    {
        puts(name[i]);
    }
    return 0;

}

void SortString(char str[][MAX_LEN], int n)
{
    int i,j;
    char temp[MAX_LEN];

    for(i=0;i<n;i++)
    {
        for(j=i+1;j<n;j++)
        {
            if(strcmp(str[j],str[i])<0)
            {
                strcpy(temp,str[i]);
                strcpy(str[i],str[j]);
                strcpy(str[j],temp);
            }
        }
    }
}

2.

统计正整数中指定数字的个数
从键盘输入一个正整数number,求其中含有指定数字digit的个数。例如:从键盘输入正整数number=1222,若digit=2,则1223中含有 3个2,要求用函数实现。
函数原型为:int CountDigit(int number,int digit);

程序运行结果示例1:
Input m,n:
1222,2↙
3

程序运行结果示例2:
Input m,n:
1234,6↙
0

输入格式: "%d,%d"
输出格式:
输入提示信息:"Input m,n:\n"
输出格式:"%d\n"

#include<stdio.h>
int CountDigit(int number,int digit);
main()
{
    printf("Input m,n:\n");
    int m,n;
    scanf("%d,%d",&m,&n);
    printf("%d\n",CountDigit(m,n));
}
int CountDigit(int number,int digit)
{
    int c=0;
    while(number)
    {
        if(digit==number%10)
        {c++;
        number=number/10;
        }
    }
    return c;
}

3.冒泡程序

#include<stdio.h>
#define LEN 10
void bubble(int dat[], int length);
main( )
{
    int  data[LEN]={0}, i;
    for (i=0; i<= LEN-1; i++)
    {
        scanf("%d",&data[i]);
    }
    bubble(data,LEN);
    for(i=0; i<= LEN-1; i++)     
        {
            printf("%8d", data[i]);
        }
}
void bubble(int dat[], int length)
{
        int head, tail,round,i;
        int t;
        head = 0;
        tail = length - 1;
 
    for (round = head; round <= tail; round++)
        for (i = tail; i >= round+1; i--)
            if ( dat[i] < dat[i-1] )
            {
                t=dat[i];             
                dat[i]=dat[i-1];
                dat[i-1]=t;
            }
}

4.实验题

编写程序统计从键盘输入的一行文本中各个字母的个数。
输入以回车键结束。
不区分大小写,大写字母与相应的小写字母按照同一个字母看待。
要求输出按照各个字母出现的个数从大到小进行排序,出现的个数相同的,按照字母在字母表中的先后顺序进行排序。
***输入格式:调用getchar()函数依次输入每个字符
***输出格式:"%c(%c):%d\n"
例如输入以下文本:
Hello World
程序将输出:
L(l):3
O(o):2
D(d):1
E(e):1
H(h):1
R(r):1
W(w):1
A(a):0
B(b):0
C(c):0
F(f):0
G(g):0
I(i):0
J(j):0
K(k):0
M(m):0
N(n):0
P(p):0
Q(q):0
S(s):0
T(t):0
U(u):0
V(v):0
X(x):0
Y(y):0
Z(z):0

#include <stdio.h>
#include<stdlib.h>
void bubble_sort(int a[], int c[],int n);
int main(void)
{int i;
int c[27]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
 char j;
 char a;                                       
 int b[26]={0};                      
 int count[26]={0};
 while ((a = getchar()) != '\n')     
   {
   for (j='A';j<='Z';++j)               
       {
           if (a == j || a == j+32)
           {
               b[j-'A']++;count[j-'A']++;
           }
   
       }
   }
   bubble_sort(b,c,26);
   for (i=0;i<26;++i)
   {
        printf("%c(%c):%d\n",c[i]-32,c[i],b[i]);
           
   }
}
    
void bubble_sort(int a[],int c[], int n)
{
    int i, j, temp;
    for (j = 0; j < n - 1; j++)
        for (i = 0; i < n - 1 - j; i++)
        {
            if(a[i] < a[i + 1])
            {
                temp = a[i];
                a[i] = a[i + 1];
                a[i + 1] = temp;
                temp = c[i];
                c[i] = c[i + 1];
                c[i + 1] = temp;
            }
        }
}

这道题是我做过后觉得比较难的,可能算法并不是很简便,如果各位大神有什么好的方法请一定告诉我。