C言語での変数と配列への値の割り当てに関するいくつかの質問

この記事は、C言語を最初に学習したときにエラーが発生しやすい部分なので、記録しました。
これは、C言語を初めて使用する学生に役立つはずです。

1. Scanfは文字入力時にキャリッジリターンを吸収します

次の質問から始めましょう

ASCIIソート

3文字入力後、各文字のASCIIコードの小さい順から大きい順に3文字を出力します。

入力

入力データには複数のグループがあり、各グループは1行を占め、スペースなしの3文字で構成されています。

出力

入力データのグループごとに1行が出力され、文字はスペースで区切られます。

入力例

qwe
asd
zxc

出力例

eqw
ads
cxz

コード

#include <cstdio>
#include <algorithm>
using namespace std;

int main(void)
{
    
    
    char a[3];
    while (scanf("%c%c%c", &a[0], &a[1], &a[2]) != EOF) {
    
    
        getchar();
        sort(a, a + 3);
        printf("%c %c %c\n", a[0], a[1], a[2]);
    }
    
    return 0;
}

この問題を実行する場合、9行目のgetchar()を無視するのは簡単です。そうすると、出力が少し奇妙であることがわかります。

scanf()およびgetchar()の説明

  1. C言語でキーボードデータを読み取る場合、通常はバッファ付きのデータ入力であり、「行」データの入力確認を完了するにはEnterキーを押す必要があります。①Scanf()は、値のデータまたは文字列(空白文字とは、キャリッジリターン、スペース、TABキー)を読み取るときに、先行する空白文字を自動的に無視します。つまり、最初の非空白文字から読み取りを開始し、再び空白に遭遇します。文字は、このタイプのデータの入力を終了します。②scanf()が文字データを読み込むと、空白文字も読み込まれます。

  2. コードの8行目には、文字を読み取るscanf()関数が3つあり、最初の行の入力 "eqw"の最後にある復帰文字は入力バッファーに残ります。したがって、次の「文字」操作関数(getchar()、scanf( "%c")、gets()など)が実行されるときに、キャリッジリターンが読み取られます。

  3. したがって、キャリッジリターンを吸収するためにscanf()の後にgetchar()を続ける必要があるかどうかは、次の入力データのタイプによって異なります。これが文字読み取り操作の場合は、さまざまな方法で対処できます。

  4. scanf()関数については、詳細に理解する価値があります。

2.文字列の最後の「\ 0」

以下のトピックからも紹介を始めます

バイナリ変換

入力
入力整数nは、(-2 ^ 31 <N <2 ^ 31)

出力は
nを対応する2進数に変換し、変換された2進数の長さと2進数のシーケンスを出力します

サンプル入力
5

出力例
101

コード

基本的な考え方は、短い除算を使用して毎回2の余りを見つけ、それを配列に格納し、最後に2進数として逆の順序で出力することです。

初期エラーコード

#include <stdio.h>
#include <string.h>

int main(void)
{
    
    
    int n, len, i = 0;
    char a[50];
    
    scanf("%d", &n);
    while(n != 0){
    
     
        a[i++] = n % 2 + '0';
        n /= 2;
    }
    len = strlen(a);
    printf("二进制数长度:%d\n", len);
    printf("二进制数:");
    for (i = len - 1; i >= 0; i--)
    	printf("%c", a[i]);
    puts("");
    
    return 0;
}

5を入力したときの出力:
ここに画像の説明を挿入

strlen()とprintf( "%s"、)の説明

  1. 上記のコードを実行すると、出力lenが実際の長さよりも大きく、出力の2進数も文字化けしていることがわかります。
  2. gets()またはscanf( "%s"、str)は、入力の終わりの後にstrの終わりに自動的に「\ 0」を追加し、上記のように単一の文字が割り当てられている場合、strの終わりに「\ 0」はありません。
  3. 関数strlen()のパラメータは文字列である必要があります。strlenは文字列の終わりを「\ 0」に基づいて判断するため、終わりが0でない場合、strの外側のメモリが読み取られ、lenの値が実際の値より大きくなります文字列の値で、文字化けした文字を出力します。
  4. printf( "%s \ n"、str);を使用します。strを出力する場合も同様です。 '\ 0'に達するまで1文字ずつ読み取られますが、strの最後には '\ 0がありません。 '、それはstr以外のメモリを読み取り、文字化けした文字を出力します。
  5. 解決策:①メイン関数の外で配列を直接開くと、配列はすべて0に初期化されます② '\ 0'のASCIIコードは0なので、7行目をchar a [50] = {0}に変更できます;これにより、各要素が0に初期化されます。

ソリューション①

#include <stdio.h>
#include <string.h>

char a[50];

int main(void)
{
    
    
    int n, len, i = 0;
    
    scanf("%d", &n);
    while(n != 0){
    
     
        a[i++] = n % 2 + '0';
        n /= 2;
    }
    len = strlen(a);
    printf("二进制数长度:%d\n", len);
    printf("二进制数:");
    for (i = len - 1; i >= 0; i--)
    	printf("%c", a[i]);
    puts("");
    
    return 0;
}

ここに画像の説明を挿入

ソリューション②

#include <stdio.h>
#include <string.h>

int main(void)
{
    
    
    int n, len, i = 0;
    char a[50] = {
    
    0};
    
    scanf("%d", &n);
    while(n != 0){
    
     
        a[i++] = n % 2 + '0';
        n /= 2;
    }
    len = strlen(a);
    printf("二进制数长度:%d\n", len);
    printf("二进制数:");
    for (i = len - 1; i >= 0; i--)
    	printf("%c", a[i]);
    puts("");
    
    return 0;
}

ここに画像の説明を挿入

後で改良された書き込み方法、配列の長さを記録するための添え字として直接lenを使用

#include <stdio.h>
#include <string.h>

int main(void)
{
    
    
    int n, len = 0, i;
    char a[50];
    
    scanf("%d", &n);
    while(n != 0){
    
     
        a[len++] = n % 2 + '0';
        n /= 2;
    }
    
    printf("二进制数长度:%d\n", len);
    printf("二进制数:");
    for (i = len - 1; i >= 0; i--)
    	printf("%c", a[i]);
    puts("");
    
    return 0;
}

3.アレイへのC言語の初期割り当てには、以下の規定があります。

  1. 一部の要素にのみ初期値を割り当てることができます。{}の値の数が要素の数より少ない場合、要素の前の部分のみが割り当てられます。例:int a [10] = {0,1,2,3,4};は、a [0]〜a [4]の5つの要素のみが割り当てられ、次の5つの要素には自動的に値0が割り当てられることを意味します。
  2. 配列全体ではなく、要素に値を1つずつ割り当てることができます。たとえば、10個の要素すべてに1つの値を割り当てるには、次のようにのみ記述できます:int a
    [10] = {1,1,1,1,1,1,1,1,1,1};次のように記述することはできません:int a [10] = 1;
  3. すべての要素に値を割り当てる場合、配列の説明に配列要素の数が記載されていない場合があります。例:int a [5] =
    {1,2,3,4,5};このように書くことができます:int a [] = {1,2,3,4,5};動的割り当てはプログラム実行の過程にあります、配列に動的に
    を割り当てます。このとき、loopステートメントをscanf関数で使用して、配列要素に値を1つずつ割り当てることができます。

4.初期化されていない配列の場合

  1. ローカル配列の場合:
    ①int a [100];この書き込み方法は初期化されていないため、100要素はすべてマシンガベージ値です
    。②int a [100] = {0、2、3};この書き込み方法は最初3各要素は0、2、3に初期化され、残りは0に設定されます
    。③int a [100] = {0};この書き込みメソッドは、100要素すべてを0に初期化します。
  2. グローバルな配列または静的プロパティとして変更された配列の
    場合初期化された場合、上記の②、③と同じです;初期化されていない場合、すべての要素は自動的に0に設定されます。

5.初期化されていない変数の場合

  1. グローバル変数と静的変数のみが自動的に0に初期化されます。

  2. 通常のローカル変数は、初期化されていない場合、ランダムデータです。

おすすめ

転載: blog.csdn.net/weixin_43772166/article/details/88556177