C语言或JAVA实现《算法4》习题。

基础题

给出以下表达式的值

a. ( 0 + 15 ) / 2
b. 2.0e-6 * 100000000.1
c. true && false || true && true

2.0e-6 为科学计数法,表示2.0 * 10e-6,即2乘以10的-6次幂.

#include <stdio.h>

#define TRUE 1
#define FALSE 0

int main() {

        printf( "( 0 + 15 ) / 2 = %d\n", ( 0 + 15 ) / 2 );
        printf( "2.0e-6 * 100000000.1 = %10.7f\n", 2.0e-6 * 100000000.1 );
        printf( "true && false || true && true = %s\n", TRUE && FALSE || TRUE && TRUE ? "true" : "false");

        return 0;
}

***  output  ***
7    // 整型
200.0000002    // 浮点型
true    // 布尔型

给出以下表达式的类型和值

a. ( 1 + 2.236 ) / 2
b. 1 + 2 + 3 + 4.0
c. 4.1 >= 4
d. 1 + 2 + ‘3’

C语言中当’3’与整型运算时,自动转换为其ASCII表里对应的数值.

#include <stdio.h>
        
int main() {
        
        printf( "( 1 + 2.236 ) / 2 = %4.3f\n", ( 1 + 2.236 ) / 2 );
        printf( "1 + 2 + 3 + 4.0 = %.1f\n", 1 + 2 + 3 + 4.0 );
        printf( "4.1 >= 4 = %s\n", ( 4.1 >= 4 ) ? "true" : "false");
        printf( "1 + 2 + \'3\' = %d\n", 1 + 2 + '3' );
 
        return 0;
}

***  output  ***
1.618  // 浮点数
10.0  // 浮点数
true  // 1 
54  // 整型

比较参数

编写程序,从命令行获取整数参数,都相等打印equal,否则打印not equal.

atoi将输入字符转换为对应数值.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

        int a = argv[1] ? atoi(argv[1]) : 0;
        int b = argv[2] ? atoi(argv[2]) : 0;
        int c = argv[3] ? atoi(argv[3]) : 0;


        printf( "a = %d\n", a );
        printf( "b = %d\n", b );
        printf( "c = %d\n", c );
        printf( "(a == b == c) = %s\n", (a == b) ? ( (b == c) ? "equal" : "not equal" ) : "not equal" );

        return 0;
}

***  output  ***
$ ./practice3 7 7 7
a = 7
b = 7
c = 7
(a == b == c) = equal

$ ./practice3 7 7 30
a = 7
b = 7
c = 30
(a == b == c) = not equal

下列语句各有什么问题(如果有的话)?

a. if (a > b) then c = 0;
b. if a > b { c = 0; }
c. if (a > b) c = 0;
d. if (a > b) c = 0 else b = 0;

a. then 关键字在C或者java中都是不存在的.
b. if后需要括号.
c. 正确.
d. c = 0 后面缺少" ; ".

判断边界

编写程序,如果double类型变量x和y都严格位于0和1之间打印true,否则打印false.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

        if ( 3 != argc ) {
                printf( "input error: 请输入两个double类型的参数." );
                return 0;
        }

        double x = argv[1] ? atof(argv[1]) : 0.0;
        double y = argv[2] ? atof(argv[2]) : 0.0;

        printf( "x = %f\n", x );
        printf( "y = %f\n", y );

        if ( (x > 0) && (x < 1) && (y > 0) && (y < 1) ) {
                printf("%s\n", "true");
        } else {
                printf("%s\n", "false");
        }

        return 0;
}

***  output  ***
x = 0.700000
y = 0.800000
true

下面这段程序会打印什么?

该代码展示了典型的斐波那契数列

int i = 0;
int f = 0;
int g = 1;
for (i = 0; i <= 15; i++) {
    printf( "f = %d\n", f );
    f = f + g;
    g = f - g;
}

***  output  ***
f = 0
f = 1
f = 1
f = 2
f = 3
f = 5
f = 8
f = 13
f = 21
f = 34
f = 55
f = 89
f = 144
f = 233
f = 377
f = 610

给出以下代码段打印的值

// a.
void FunA() {

        double t = 9.0;
        while ( fabs(t - 9.0/t) > .001 )
                t = (9.0/t + t) / 2.0;
        printf( "FunA t = %.5f\n", t );

}
//b.
void FunB() {

        int sum = 0;
        for (int i = 1; i < 1000; i++)
                for (int j = 0; j < i; j++)
                        sum++;
        printf( "FunB sum = %d\n", sum );

}
//c. 
void FunC() {

        int sum = 0;
        for (int i = 1; i < 1000; i *= 2)
                for (int j = 0; j < 1000; j++)
                        sum++;
        printf( "FunC sum = %d\n", sum );

}

***  output  ***
FunA t = 3.00009
FunB sum = 499500
FunC sum = 10000

打印结果

a. System.out.println('b');
b. System.out.println('b' + 'c');
c. System.out.println((char) ('a' + 4));

*** output ***
b
197
e

itos

编写一段代码,将正整数N用二进制表示并转换为String类型的值s.

>>>: 无符号右移,忽略符号位,空位都以0补齐

// 简洁但运行效率低的程序
public static void main(String[] argv) {
    int N = 10;
    String s = "";
    for (int n = N; n > 0; n /= 2)
        s = ( n % 2 ) + s;
    System.out.println(s);
    System.out.println(decimalToBinary(N));
}

// 效率高的写法
public static String decimalToBinary(int n) {
    String resultString = "";
    for (int i = 31; i >= 0; i--)
        resultString = resultString + (n >>> i & 1);
    return resultString;
}

***  output  ***
1010
00000000000000000000000000001010

找错

int[] a;
for (int i = 0; i < 10; i++)
a[i] = i * i;

//解答:它没有用 new 为 a[] 分配内存。这段代码会产生一个 variable a might not have been initialized 的编译错误。

打印二维数组

打印二维数组内容,*表示真,-表示假,打印出行号和列号.

#include<stdio.h>
#include <stdlib.h>

#define ROW 10
#define COL 10

void init_array(int* arr[], int row, int col);
void print2_d_array(int* arr[], int row, int col);
void destroy_array(int* arr[], int row); 

int main() {

    int* array[ROW];
    init_array(array, ROW, COL);
    print2_d_array(array, ROW, COL);
    destroy_array(array, ROW);

    return 0;
}

void init_array(int* arr[], int row, int col) {

    for (int i = 0; i < row; i++) {
            arr[i] = ( int* )malloc( col * sizeof(int) );
            for (int j = 0; j < col; j++) {
                    arr[i][j] = rand() % 2;
            }
    }
}

void print2_d_array(int* arr[], int row, int col) {

    printf( "  " );
    for(int i = 0; i < col; i++) {
            printf( "%d ", i+1);
    }
    printf( "\n" );

    for (int i = 0; i < row; i++) {
            printf( "%d ", i+1 );
            for (int j = 0; j < col; j++) {
                    if (arr[i][j]) {
                            printf( "%s ", "*" );
                    } else {
                            printf( "%s ", "-" );
                    }
            }
            printf("\n");
    }
}

void destroy_array(int* arr[], int row) {

    for (int i = 0; i < row; i++) {
            if (arr[i] != NULL) {
                    free(arr[i]);
                    arr[i] = NULL;
            }
    }
}

***  output  ***
  1 2 3 4 5 6 7 8 9 10 
1 * - * * * * - - * * 
2 - * - * * - - - - - 
3 * - * * - - - * * * 
4 * - - - * * * - * - 
5 * * * * - * - - * - 
6 * - * - - * - - - * 
7 * * - * - * - * * * 
8 - * - * - * - - * - 
9 * - - - - - * * - * 
10 - - - - * - - - - * 

以下代码的打印结果

public static void main(String argv[]) {

        int[] a = new int[10];
        for (int i = 0; i < 10; i++)
                a[i] = 9 - i;
        for (int i = 0; i < 10; i++)
                a[i] = a[a[i]];
        for (int i = 0; i < 10; i++)
                System.out.println(a[i]);
}

***  output  ***
0
1
2
3
4
4
3
2
1
0

二维数组转置

上面写过C版本的二维数组,下面写Java版本二维数组.

public static void main(String argv[]) {

    int[][] raw = {{1, 2, 3}, {4, 5, 6}};

    int[][] temp = new int[raw[0].length][raw.length];
    for (int i = 0; i < raw[0].length; i++) {
        for (int j = 0; j < raw.length; j++) {
            temp[i][j] = raw[j][i];
            System.out.print(temp[i][j] + "  ");
            if (raw.length - 1 == j){
                    System.out.println();
            }
        }
    }
}

***  output  ***
1  4  
2  5  
3  6  

不大于log2N 的最大整数

编写一个静态方法 lg(),接受一个整型参数 N,返回不大于log2N 的最大整数.

#include<stdio.h>
#include<math.h>

int lg1(int N);
int lg2(int N);

int main() {
        int N1 = 32;
        int N2 = 63;
        int N3 = 1;
        printf("不大于log2(%d)的最大整数:%d\n", N1, lg1(N1));
        printf("不大于log2(%d)的最大整数:%d\n", N2, lg2(N2));
        printf("不大于log2(%d)的最大整数:%d\n", N3, lg2(N3));

        return 0;
}

// 不用库函数
int lg1(int N) {

        int base = 1;
        int cumulative = -1;

        while ( base <= N ) {
                base *= 2;
                cumulative += 1;
        }

        return cumulative;
}

// 使用库函数,易于理解上面的代码
int lg2(int N) {

        int base = 1;
        int cumulative = 0;

        while ( base <= N ) {
                cumulative += 1;
                base = pow(2, cumulative);
        } 

        return cumulative - 1;
}

***  output  ***
不大于log2(32)的最大整数:5
不大于log2(63)的最大整数:5
不大于log2(1)的最大整数:0