この記事は、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()の説明
-
C言語でキーボードデータを読み取る場合、通常はバッファ付きのデータ入力であり、「行」データの入力確認を完了するにはEnterキーを押す必要があります。①Scanf()は、値のデータまたは文字列(空白文字とは、キャリッジリターン、スペース、TABキー)を読み取るときに、先行する空白文字を自動的に無視します。つまり、最初の非空白文字から読み取りを開始し、再び空白に遭遇します。文字は、このタイプのデータの入力を終了します。②scanf()が文字データを読み込むと、空白文字も読み込まれます。
-
コードの8行目には、文字を読み取るscanf()関数が3つあり、最初の行の入力 "eqw"の最後にある復帰文字は入力バッファーに残ります。したがって、次の「文字」操作関数(getchar()、scanf( "%c")、gets()など)が実行されるときに、キャリッジリターンが読み取られます。
-
したがって、キャリッジリターンを吸収するためにscanf()の後にgetchar()を続ける必要があるかどうかは、次の入力データのタイプによって異なります。これが文字読み取り操作の場合は、さまざまな方法で対処できます。
-
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"、)の説明
- 上記のコードを実行すると、出力lenが実際の長さよりも大きく、出力の2進数も文字化けしていることがわかります。
- gets()またはscanf( "%s"、str)は、入力の終わりの後にstrの終わりに自動的に「\ 0」を追加し、上記のように単一の文字が割り当てられている場合、strの終わりに「\ 0」はありません。
- 関数strlen()のパラメータは文字列である必要があります。strlenは文字列の終わりを「\ 0」に基づいて判断するため、終わりが0でない場合、strの外側のメモリが読み取られ、lenの値が実際の値より大きくなります文字列の値で、文字化けした文字を出力します。
- printf( "%s \ n"、str);を使用します。strを出力する場合も同様です。 '\ 0'に達するまで1文字ずつ読み取られますが、strの最後には '\ 0がありません。 '、それはstr以外のメモリを読み取り、文字化けした文字を出力します。
- 解決策:①メイン関数の外で配列を直接開くと、配列はすべて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言語の初期割り当てには、以下の規定があります。
- 一部の要素にのみ初期値を割り当てることができます。{}の値の数が要素の数より少ない場合、要素の前の部分のみが割り当てられます。例:int a [10] = {0,1,2,3,4};は、a [0]〜a [4]の5つの要素のみが割り当てられ、次の5つの要素には自動的に値0が割り当てられることを意味します。
- 配列全体ではなく、要素に値を1つずつ割り当てることができます。たとえば、10個の要素すべてに1つの値を割り当てるには、次のようにのみ記述できます:int a
[10] = {1,1,1,1,1,1,1,1,1,1};次のように記述することはできません:int a [10] = 1; - すべての要素に値を割り当てる場合、配列の説明に配列要素の数が記載されていない場合があります。例:int a [5] =
{1,2,3,4,5};このように書くことができます:int a [] = {1,2,3,4,5};動的割り当てはプログラム実行の過程にあります、配列に動的に
値を割り当てます。このとき、loopステートメントをscanf関数で使用して、配列要素に値を1つずつ割り当てることができます。
4.初期化されていない配列の場合
- ローカル配列の場合:
①int a [100];この書き込み方法は初期化されていないため、100要素はすべてマシンガベージ値です
。②int a [100] = {0、2、3};この書き込み方法は最初3各要素は0、2、3に初期化され、残りは0に設定されます
。③int a [100] = {0};この書き込みメソッドは、100要素すべてを0に初期化します。 - グローバルな配列または静的プロパティとして変更された配列の
場合:初期化された場合、上記の②、③と同じです;初期化されていない場合、すべての要素は自動的に0に設定されます。
5.初期化されていない変数の場合
-
グローバル変数と静的変数のみが自動的に0に初期化されます。
-
通常のローカル変数は、初期化されていない場合、ランダムデータです。