C言語演習(夏期後半)

ここに画像の説明を挿入します


序文

大事なことは3回言いましょう!
勉強!勉強!勉強!


1. 表情判定

コード スニペットについては、次の説明が正しいです ( )

t=0;
while(printf("*"))
{
    
    
    t++;
    if (t<3)
        break;
}

A: ループ制御式は 0 と同等です
B: ループ制御式は「0」と同等です
C: ループ制御式は不正です
D: 上記のステートメントはどれも正しくありません

質問分析:
print("*") 関数呼び出しの戻り値は文字列内の文字数、つまり 1 であるためです。
したがって、while の後の条件は常に true となるため、ループ制御式は '0' と等価になります (文字 '0' は 0 ではありません)。
正解はB

問題の答え:
B


2. Assii コードの理解と応用

以下のプログラムを実行した場合、1abcedf2df <Enter>を入力すると出力結果は( )となります。

#include <stdio.h>
int main()
{
    
    
    char ch;
    while ((ch = getchar()) != '\n')
    {
    
    
        if (ch % 2 != 0 && (ch >= 'a' && ch <= 'z'))
        ch = ch - 'a' + 'A';
        putchar(ch);
    }
    printf("\n");
    return 0;
}

A: 1abcedf2df
B: 1ABCEDF2DF
C: 1AbCEdf2df
D: 1aBceDF2DF

問題分析:
ch の ASCII コード値が奇数であるかどうかを考慮し、次に小文字であるかどうかをチェックし、両方を満たす場合は大文字に変更します。

質問の答え:
C


3. ループジャンプ判定

C 言語の Break ステートメントは、最も近いループからのみジャンプできることはわかっていますが、場合によっては複数のループからジャンプする必要がある場合があります。以下の複数のループからジャンプする正しい方法は [複数選択] ( ) A: を記述します。関数としてプログラムする
return で関数を終了してループから抜け出す
B: 外側のループ条件を変更します。たとえば

for( int i = 0 ; i < MAX1 ; i ++ )
{
    
    
    for( int j = 0 ; j < MAX2 ; j ++ )
    {
    
    
        if( condition )
        {
    
    
            i = MAX1;
            break;
        }
    }
}

C: 外側のループに判定条件を設定する例

for( ; symbol != 1 && condition2 ; )
{
    
    
    for( ; symbol != 1 && condition3 ; )
    {
    
    
        if( condition1 )
        symbol = 1 ;
    }
}

D: たとえば、外側のループの後にブレークを追加します。

for( ; condition2 ; )
{
    
    
    for( ; condition3 ; )
    {
    
    
        if( condition1 )
            symbol = 1 ;
    } 
        if(symbol == 1 )
             break ;
}

問題分析:
この問題は、多重レベルのループから抜け出す方法を整理することを目的としています。各選択肢は正解です。コードは疑似コードであり、条件は論理式を表します。

質問の答え:
ABCD


4. 数値が昇順配列に出現する回数

質問リンクOJ リンク
ここに画像の説明を挿入します

問題分析:
トラバーサルでも解決できますが、配列は降順ではありません。二分探索の考え方が最適です。最初に二分探索で左端のデジタル位置を見つけ、次に右端のデジタル位置を二分探索します。 2 つの位置の減算 + 1 が長さです。
中央の値が探している値より大きい場合: 探している数字は右側にある必要があり、左側 = Mid + 1;
中央の値が探している値より小さい場合: 探している数字は左側にある必要があり、右側 = 中央 - 1;
中央の値は探している値と同じです。値は同じです:
検索する左端の数値: Mid が左の場合は Mid を返し、そうでない場合は right=mid-1 にリセットし、中心を左に継続的にシフトします。検索する右端の数値: Mid が右の場合は Mid を返します
。 left=mid+1 にリセットし、継続的に中心を右にシフトします

int get_last_or_first_idx(int* data, int len, int k,int flag) {
    
    
    int left = 0, right = len - 1, mid;//左右指针下标及中间结点下标
    while (left <= right) {
    
    
        mid = left + (right - left) / 2;//找到中间结点
        if (data[mid] > k)
            right = mid - 1;//如果中间节点大于k,则将右节点左移
        else if (data[mid] < k)
            left = mid + 1;//如果中间节点小于k,则将左节点右移
        else {
    
    //如果中间节点值等于k,则判断flag的值来区分找的是哪边
            if (flag == 0) {
    
     
                if (mid == left || data[mid - 1] != k) return mid;//如果中间结点等于k,且前一个结点不等于k,以及和left位置相同,则找到最左边的k,返回下标
                else right = mid - 1;
            } else {
    
    
                if (mid == right || data[mid + 1] != k) return mid;//如果中间结点等于k,且后一个结点不等于k,以及和right位置相同,则找到最右边的k,返回下标
                else left = mid + 1;
            }
        }
    }
    return -1;
}
int GetNumberOfK(int* data, int dataLen, int k ) {
    
    
    if (dataLen == 0) return 0;
    int left = get_last_or_first_idx(data, dataLen, k, 0);
    int right = get_last_or_first_idx(data, dataLen, k, 1);
    if (left == -1 && right == -1) return 0; 
    return right - left + 1;//左右下标相减得到k的个数
}

5. 整数変換

質問リンク: OJ リンク
ここに画像の説明を挿入します

ヒント:

A と B の範囲は [-2147483648, 2147483647] です。

質問分析:
実際、何ビット変更する必要があるかを尋ねる場合、問題は何ビットが異なるかということです。なぜなら、変更できるのは何ビットだけ異なるからです。

質疑応答:

int convertInteger(int A, int B){
    
    
    int a=A^B;//相同为0,相异为1
    double count=0;
    for(int i=0;i<32;i++){
    
    
        if((a>>i)&1==1){
    
    //通过与1与,得到求出的数二进制序列中有多少个1,从而确定个数;
            count++;
        }
    }
    return count;
}

6. ループ文の応用

次の文のうち正しいものはどれですか ( )
A:break 文はループ本体と switch 文でのみ使用できます
B:break がループ本体内の switch 文の本体にある場合、その機能は次のとおりです。 switch ステートメントの本体から飛び出て、ループ本体を終了します。C
: continue ステートメントを実行する機能は、ループ本体内の残りのステートメントを実行した後にループを終了することです。D
: continue ステートメントは、次のような場合には使用できません。 while ステートメントと do-while ステートメント。

質問分析:
Break ステートメントは通常、loop ステートメントと switch ステートメントで使用されます。switch ステートメントで Break を使用すると、プログラムは switch から抜け出して、switch の後のステートメントを実行できます。break を
do-while、for、while ループ ステートメントで使用すると、プログラムはループを終了して、つまり、条件が満たされるとループが開始されます。
continue ステートメントの機能は、ループ本体内の残りのステートメントをスキップし、次のループの実行を強制することです。選択肢 B、C、D に誤りがあります。
したがって、選択肢Aの正解は次のとおりです


7. 関数呼び出し

関数 fun と実際のパラメータグループの記述が次の形式であるとします。関数呼び出しステートメントでは、正しいものは ( ) です。

void fun(char ch,float x[]);
float a[10];

A: fun(“asd” , a[]); B: fun('x' , A); C: 楽しい('68' , 2.8); D: 楽しい(32 , a);

質問分析:
オプション A の配列にパラメーターを渡すには、配列名を記述するだけで済みます。a[] は間違っています。オプション B の 2 番目のパラメーターが大文字で書かれているのは間違いです。オプション C の 2 番目のパラメータは浮動小数点数ですが、fun 関数の 2 番目のパラメータは一致しない配列です。fun 関数のパラメータ x には、配列または float * ポインタを渡す必要があります。オプション D の形式のみ正しい。
質問の答え:
D


8. 2 つの配列の交差

質問リンク: OJ リンク
ここに画像の説明を挿入します

ヒント:

1 <= nums1.length、nums2.length <= 1000
0 <= nums1[i]、nums2[i] <=1000

質問分析:
オプション A の配列にパラメーターを渡すには、配列名を記述するだけで済みます。a[] は間違っています。オプション B の 2 番目のパラメーターが大文字で書かれているのは間違いです。オプション C の 2 番目のパラメータは浮動小数点数ですが、fun 関数の 2 番目のパラメータは一致しない配列です。fun 関数のパラメータ x には、配列または float * ポインタを渡す必要があります。オプション D の形式のみ正しい。
質疑応答:

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    
    
    static int arr[1000];//定义静态,防止销毁
    *returnSize = 0;//返回数组大小
    for (int i = 0; i < nums1Size; i++) {
    
    //将nums1中的每个数遍历nums2找到相同的数
        for (int j = 0; j < nums2Size; j++) {
    
    
            if (nums1[i] == nums2[j]) {
    
    
                int k = 0;
                for (k = 0; k < *returnSize; k++) {
    
    //遍历arr数组看是否已经存在,找到了返回下标
                    if (arr[k] == nums2[j])
                        break;
                }
                if (k == *returnSize) {
    
    //如果k等于*returnSize则说明数组中不存在该数,则向数组中加入该数
                    arr[*returnSize] = nums2[j];
                    (*returnSize)++;//返回数组长度+1
                }
            }
        }
    }
    return arr;
}

9. C言語の基礎

以下の C 言語関数の説明のうち、正しいものは [複数選択] ( )
A: C 言語では、関数は通常、関数ヘッダーと関数本体の 2 つの部分で構成されます。
B: 実際のパラメーターと関数の形式function パラメーターは同じ名前を持つことができます
C: main() で定義された変数は、呼び出される他の関数で直接使用できます
D: C プログラムでは、関数呼び出しを式ステートメントに含めることはできません

質問分析:
main 関数も関数であり、他の関数と並列関係があるため、main 関数で定義されたローカル変数は main 関数内でのみ有効です C エラー; 関数に戻り値がある場合、それは式の中に現れる可能性があります。D 誤った
答え:
AB


10. 写真の整理

質問リンク: OJ リンク
ここに画像の説明を挿入します

質問分析:
この質問は実際に文字のソートを調べます。各 ASCII 文字はメモリ内に対応する ASCII 値を持ち、メモリ内にデータを保存することでソートできます。
バブル ソート: 隣接するデータを比較および交換し、大きいデータまたは小さいデータを配列の最後に押し戻してから、
ビッグ データのバブリング プロセスの次のラウンドを開始します。

質問に対する答え:
方法 1:

#include <stdio.h>
void Qsort(char*arr,int len){
    
    
    for(int i=0;i<len;i++){
    
    //冒泡排序
        for(int j=0;j<len-i-1;j++){
    
    
            if(arr[j]>arr[j+1]){
    
    
                char temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
}
int main() {
    
    
    char arr[1001] = {
    
    0};
    while (scanf("%s", arr)!= EOF) {
    
    
        char digit[1001] = {
    
    0};//将数字入到该数组
        int digits = 0;//数字个数
        char upper[1001] = {
    
    0};//将大写字母入到该数组
        int uppers = 0;//大写字母个数
        char lower[1001] = {
    
    0};//将小写字母入到该数组
        int lowers = 0;//小写字母个数
        char* ptr = arr;
        while (*ptr) {
    
    //查找并添加
            if (*ptr >= '0' && *ptr <= '9') {
    
    
                digit[digits] = *ptr;
                digits++;
            }
            if (*ptr >= 'A' && *ptr <= 'Z') {
    
    
                upper[uppers] = *ptr;
                uppers++;
            }
            if (*ptr >= 'a' && *ptr <= 'z') {
    
    
                lower[lowers] = *ptr;
                lowers++;
            }
            ptr++;
        }  
        //进行排序      
        Qsort(digit,strlen(digit));
        Qsort(upper,strlen(upper));
        Qsort(lower,strlen(lower));
        //进行输出
        for (int j = 0; j < digits; j++) {
    
    
            printf("%c", digit[j]);
        }
        for (int j = 0; j < uppers; j++) {
    
    
            printf("%c", upper[j]);
        }
        for (int j = 0; j < lowers; j++) {
    
    
            printf("%c", lower[j]);
        }
    }
return 0;
}

方法 2:

#include <stdio.h>
int main()
{
    
    
    char str[1024] = {
    
    0};
    while(gets(str)) {
    
    
        int len = strlen(str);
        for (int i = 0; i < len; i++) {
    
    
            for (int j = 1; j < len - i; j++) {
    
    
                if (str[j] < str[j - 1]) {
    
    
                    char ch = str[j - 1];
                    str[j - 1] = str[j];
                    str[j] = ch;
                }
             }
         }
        printf("%s\n", str);
    }
    return 0;
}

11. 配列参照

int a[2][3]; という定義がある場合、次のオプションの a 配列要素への正しい参照は ( )
A: a[2][0]
B: a[2][3]
Cです。 :a[0 ][3]
D: a[1>2][1]

質問分析:
この質問は主に配列の範囲外アクセスの場合を考慮します。2 次元配列の行と列は 0 から始まります。配列 a の場合、行の添字の最大値は 1、列の添字の最大値は です。 2. オプション D では、1 >2 式の値は 0 であり、これは正しいです。他のオプションには、範囲外の行と列が含まれる可能性があります。A は行が範囲外であることを意味し、B は両方の行が範囲外であることを意味しますと列が範囲外であり、C は列が範囲外であることを示します。
質問の答え:
D


12. 配列参照

i と j は両方とも整数変数であることが知られています。次の式のうち、添字参照 X[i][j] と等価でないものは [多肢選択] ( ) A: ( X [i]
+ j )
B:
(X+i)[j]
C: *(X+i+j)
D: ( (X+i)+j)

問題分析:
この問題は 2 次元配列の要素へのアクセスをテストします。選択肢 A が正解です。X[i] は i 番目の行の配列名です。配列名は最初の要素のアドレスを表します。 +j の後の要素は、i 行目の添字が j である要素のアドレスです。全体の逆参照は X[i][j] であり、A は正しいです。オプション B は、[] の優先順位が * よりも高いため、コードは **((x+i)+j) と同等であり、X+i+j の後で境界を越えますが、これは X[i を意味しません。 ][j]、だから間違いです。選択肢 C も明らかに間違っています。D オプションは、2 桁の配列の要素にアクセスするための標準的なポインター形式です。
質問の答え:
BC


13. 文字数統計

質問リンク: OJ リンク
ここに画像の説明を挿入します

質問分析:
この質問の考え方は、0 から 127 までのさまざまな文字が配列内の assi 値に対応する位置を確実に見つけられるように、最初にサイズ 128 の配列を作成し、見つかった位置を 1 に変更し、最後に配列に値を追加して
文字タイプの質問への答えを取得します。

#include <stdio.h>
int main() {
    
    
    char arr[501]={
    
    0};
    while (scanf("%s",arr) != EOF) {
    
     
        char*ptr=arr;
        int count[128]={
    
    0};
        while(*ptr){
    
    
            int temp=*ptr;//通过Assii码值作为下标找到count数组中对应的位置
            count[temp]=1;//将值变为1;
            ptr++;
        }
        int ret=0;
        for(int i=0;i<=129;i++){
    
    //遍历相加
            ret+=count[i];
        }
        printf("%d\n",ret);
    }
    return 0;
}

14. ほとんどの要素

質問リンク: OJ リンク
ここに画像の説明を挿入します

ヒント:
n == nums.length
1 <= n <= 5 * 104
-109 <= nums[i] <= 109

質問分析:
配列内に n/2 回以上出現する数字があります。0 番目の文字から始めて、それが最も多い数字であると仮定し、同じ数字に遭遇した場合はカウントを +1 し、異なる数字に遭遇した場合はカウントを +1 します。数値の場合、カウントは -1 になります。実際には、それらは互いに消費します。カウントが 0 になると、スペルが完了したことを意味し、次の文字から再びスペルが開始されます。ただし、最終的には、次の文字の数がn/2 より多く出現する数字は大きいため、最後に残った文字でもあります。
例:「23335」はまず2文字から1を数え始め、3に出会ったら-1して残りの「335」からスタートする処理が消費されます。このとき保存されている文字は3ですが、 3 に遭遇した場合は +1、5 に遭遇した場合は -1 としてカウントし、カウントが 0 以外の場合、最後に保存される文字は n/2 を超えた文字になります

int majorityElement(int* nums, int numsSize){
    
    
    int count=1;//记录多数元素的个数与非多数元素出现个数的差
    int more=nums[0];//将第一个作为多数元素
    int i=1;
    for(i;i<numsSize;i++){
    
    
        if(more==nums[i]){
    
    //下标对应的数为多数元素,则count++
            count++;
        }
        else{
    
    //下标对应的数不是多数元素,则count--
            count--;
        }
        if(count==0){
    
    //如果count等于0,那就可能该数不是多数元素,将下一个作为多数元素继续遍历
            more=nums[i+1];
        }
    }
    if(count>0){
    
    //多数元素的个数与非多数元素出现个数的差大于0,则说明此时记录的元素多于总数的一半,为多数元素,
        return more;
    }
    else{
    
    
       return 0;
    }
}

要約する

大事なことは3回言いましょう!
来て!来て!来て!

おすすめ

転載: blog.csdn.net/mdjsmg/article/details/132533809