文字列str内の全ての数字を削除する関数
void del_digit(char str[]) を作成。
(例えば、"ab1C9"を受け取ったら、"ABC"にする)
という関数を作りたいのですが、うまくいきません。
過去に似たような『文字列内の数字削除』の質問をされた方が
いましたが、ポインタを使っていました。
http://okwave.jp/qa1775576.html
ポインタを使わずにするには、どうしたらよいのでしょうか?
途中まで作ってみたのですが、うまく動きません。
#include <stdio.h>
#include <ctype.h>
void del_digit(char str[])
{
unsigned i = 0, j = 0;
char ctr[] = {'0'};
while (str[i] != '\0') {
ctr[i] = str[i];
i++;
}
i = 0;
while (ctr[i] != '\0') {
if (ctr[i] < '0' || ctr[i] > '9') {
str[j] = toupper(ctr[i]);
j++;
}
i++;
}
str[j] = '\0';
}
int main(void)
{
char str[100];
printf("文字列を入力してください:");
scanf("%s", str);
del_digit(str);
printf("%s\n", str);
return (0);
}
A 回答 (8件)
- 最新から表示
- 回答順に表示
No.8
- 回答日時:
★追記。
・一時コピーする領域は『buff』を用意しなくても引数『str』に上書きしてもいいですよ。
今回の場合は文字の削除ですから。→挿入して領域が増加する場合は『buff』などを用意する
必要があります。
・以上。おわり。
No.7
- 回答日時:
★たくさん回答がありますが、もう一つサンプルを付けます。
・実現方法ですが、引数の『str』から数字部分以外を別領域へコピーする仕組みがメインです。
・そして、別領域にコピーするときに英字の『小文字』を『大文字』に変換する方法も一緒に
記述すれば良いと思います。
・あと数字文字の判定は『isdigit』関数で行い、小文字ならば大文字に変換するには知っての
通り『toupper』関数を使います。
・最後に別領域へコピーした内容を引数『str』にコピーしなおせば完成です。
サンプル:
void del_digit( char str[] )
{
char buff[ 256 ]; ←一時コピーする別領域
int i; ←コピー先の配列の添え字カウンタ
int j; ←コピー元の配列の添え字カウンタ
for ( i = j = 0 ; str[j] != '\0' ; j++ ){
if ( !isdigit(str[j]) ){ ←数字以外を処理
buff[ i++ ] = (char)toupper( str[j] ); ←大文字変換してコピー
}
}
buff[ i ] = '\0'; ←最後にNULL文字をセット
strcpy( str, buff ); ←引数 str にコピー
/*
for ( i = j = 0 ; buff[j] != '\0' ; i++, j++ ){
str[ i ] = buff[ j ];
}
str[ i ] = '\0'; ←最後にNULL文字をセット
*/
}
最後に:
・上記のサンプルは『del_digit』関数の部分のみです。main 関数は質問者さんのものでいいです。
・また、引数 str の文字列に漢字文字が含まれると文字化けを起します。つまり、漢字非対応です。
・あと『strcpy』の部分を自分でコピーする場合は、『/*』…『*/』の部分になります。
・これで『数字』部分を取り除いて、『小文字』を『大文字』に変換する『del_digit』関数の完成
です。あまり、難しく考えすぎない方ないいでしょう。→コピーと文字変換を組合わせただけです。
・以上。おわり。
No.6
- 回答日時:
ごめん、訂正。
void del_digit(char *str)
{
int i, j;
for(i = j = 0; str[i] != '\0'; i ++){
if(!isdigit(str[i])){
str[j] = toupper(str[i]);
j ++;
}
}
str[j] = '\0';
return;
}
No.5
- 回答日時:
文字列を扱う時点で、"ポインタを使わずに"というのは無理だけど、
#include <stdio.h>
#include <ctype.h>
void del_digit(char *str)
{
int i, j;
for(i = j = 0; str[i] != '\0'; i ++){
str[j] = toupper(str[i]);
j += !isdigit(str[i]);
}
str[j] = '\0';
return;
}
int main(void)
{
char str[] = "a1b2c3d4e5";
puts(str);
del_digit(str);
puts(str);
return 0;
}
No.4
- 回答日時:
まずC言語には、『文字列そのもの』という概念はなく、変わりに『1文字を表現するchar型の配列で文字列を表現する』という考え方があります。
なので、文字列操作をしようと思うと、文字列を成す各char型の配列を操作しなければなりません。配列の先頭はポインタ変数です。char型の文字列の場合だと、先頭のデータを表現するchar*型の変数だけということになります。通常は、このchar*変数にインクリメントしたりデクリメントしたりして、配列内の要素にchar*変数を移動させて各要素を操作しますが、それがトリッキー見にえて嫌なら、文字列の先頭を指すchar*変数に添え字を付けても配列の各要素を操作することが出来ます。いかがその関数です。適当に書きましたので参考までに。void hoge(char*str){
int a,s;
//a番目の文字が終端文字'\0'でないならば、
//aを++して繰り返し
for(a=0;str[a];++a){
//a番目の文字が数値ならば
if(str[a]>='0'&&str[a]<='9'){
//数値の削除
for(s=a;str[s];++s) str[s]=str[s+1];
--a;
}
}
return;
}
No.3
- 回答日時:
コードの途中に、途中経過を確認するための
printf関数を適宜入れてみましょう。
ところで、del_digit関数の仕様は
「文字列str内の全ての数字を削除する」だけではないですよね。
「結果をすべて大文字にする」も含んでいてよいのですね?
No.2
- 回答日時:
質問に書かれている方法だと、
char ctr[] = {'0'};
はサイズ1の配列(ctr[1]と同じ)になってしまいますので
その後のループで配列の範囲外にアクセスしてエラーになります。
なので、配列ctrのサイズは、入力された文字数よりも大きくしないといけません。
とりあえず、512や1024といった数字で試してみてください。
あと、最初のwhileループ内で文字チェックをするように変えれば
2番目のループの回数が減りますよ。
それをさらにステップアップさせたのが、No.1さんの方法ですね。
こちらは 文字列が (結果の文字数)≦(入力文字数) となることを利用していますが、
処理を1ステップずつ紙に書いていけば理解しやすいと思います。
回答ありがとうございました。
配列の範囲を広げたら、おしいところまでいきました!
ただそれだけだと、sacanfでstr[0]に数字を入力すると
文字バケの表示が文字列の最後についてしまったため?
ctr[i] = '\0';
を追加したらうまくいきました。
まだ、おかしいところあるかもしれませんが、大変参考に
なりました。ありがとうございます。
void del_digit(char str[])
{
unsigned i = 0, j = 0;
char ctr[1000];
while (str[i] != '\0') {
ctr[i] = str[i];
i++;
}
ctr[i] = '\0';
i = 0;
while (ctr[i] != '\0') {
if (ctr[i] < '0' || ctr[i] > '9') {
str[j] = toupper(ctr[i]);
j++;
}
i++;
}
str[j] = '\0';
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のmemcpy関数について質問...
-
C言語:小文字を大文字に変換す...
-
char型の文字列をウィンドウに...
-
C言語のintとcharの違いってな...
-
char型について【初心者です】
-
GDIによるメモリ上からの画像デ...
-
ポインタで詰まりました;
-
文字列の途中から途中までを抽出
-
const char* s1とただのchar s1...
-
プログラムの中身の意味
-
エクセルのMID関数は、C言語では?
-
C言語で文字列置き換え
-
C言語のプログラムについてです
-
関数から配列を返すには?
-
リッチテキストボックスの中身...
-
クイックソートの比較交換回数...
-
C言語 配列の長さの上限
-
2次元配列を確保したいのですが、
-
%dなどの違い
-
セグメントエラー
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
strcat関数を自作したいです
-
C言語のプログラムについてです
-
DWORDとcharの変換
-
const char* s1とただのchar s1...
-
char型にint型の数値を代入する。
-
文字列の途中から途中までを抽出
-
new charとnew char[N]の違いは?
-
文字列内の数字削除
-
char 文字列型 の表現範囲が-12...
-
fgetc( )の戻り値はなぜ整数??
-
csvファイルをfscanfで読み込む...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
ポインタを使って回文かどうか...
-
ポインタ配列
おすすめ情報