文字列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);
}

このQ&Aに関連する最新のQ&A

A 回答 (8件)

★追記。


・一時コピーする領域は『buff』を用意しなくても引数『str』に上書きしてもいいですよ。
 今回の場合は文字の削除ですから。→挿入して領域が増加する場合は『buff』などを用意する
 必要があります。
・以上。おわり。
    • good
    • 0

★たくさん回答がありますが、もう一つサンプルを付けます。


・実現方法ですが、引数の『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』関数の完成
 です。あまり、難しく考えすぎない方ないいでしょう。→コピーと文字変換を組合わせただけです。
・以上。おわり。
    • good
    • 0

 


 ごめん、訂正。
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;
}
 
    • good
    • 0

 


 文字列を扱う時点で、"ポインタを使わずに"というのは無理だけど、

#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;
}
 
    • good
    • 0

まず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;
}
    • good
    • 0

コードの途中に、途中経過を確認するための


printf関数を適宜入れてみましょう。

ところで、del_digit関数の仕様は
「文字列str内の全ての数字を削除する」だけではないですよね。
「結果をすべて大文字にする」も含んでいてよいのですね?
    • good
    • 0

質問に書かれている方法だと、


 char ctr[] = {'0'};
はサイズ1の配列(ctr[1]と同じ)になってしまいますので
その後のループで配列の範囲外にアクセスしてエラーになります。

なので、配列ctrのサイズは、入力された文字数よりも大きくしないといけません。
とりあえず、512や1024といった数字で試してみてください。

あと、最初のwhileループ内で文字チェックをするように変えれば
2番目のループの回数が減りますよ。
それをさらにステップアップさせたのが、No.1さんの方法ですね。

こちらは 文字列が (結果の文字数)≦(入力文字数) となることを利用していますが、
処理を1ステップずつ紙に書いていけば理解しやすいと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
配列の範囲を広げたら、おしいところまでいきました!
ただそれだけだと、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';

お礼日時:2007/02/16 12:13

そのような形にしたいなら、



void del_digit(char str[])
{
unsigned i = 0, j = 0;

while (str[i] != '\0') {
if (str[i] < '0' || str[i] > '9')
{
str[j] = str[i];
j++;
}
i++;
}
str[j] = '\0';
}

みたいにしますけど…(参考まで)
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
処理も少なくてスムーズに、きれいにできました。
ありがとうございます。

お礼日時:2007/02/16 12:04

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QRGB値の3っつの数字に付く単位は?

 よろしくお願いします。
色を表現する方法の一つににRGB値がありますが、
例えば 255-100-20といった3つの数字の組み合わせですが、この数字にはどんな単位が付くのですか?
単位が無いことは無いと思うのですが、RGB値の個々の数字に単位が付いているのを見たことが有りません。省略しているのでしょうか?
 例えば先にあげたRGB値の255の後ろにはどんな単位が
付くのですか?
 ※ちなみRGBが光の三原色のことはわかります。
また数値が大きいほどそれに対応する色がその色に含まれている量が多い事になるのは知っております。

Aベストアンサー

再び失礼します。#1です。
補足します。

階調は、人が見たときの明るさが視覚的に概ね等間隔になるように刻んだものです。

何が言いたいかといいますと、

実際の明るさというか光の強度は等間隔でありません。

ですから、例えば、3階調と4階調との間の光量差と、200階調と201階調との間の光量差は、違います。(前者のほうが光量が小さいです。)
ということで、100階調と200階調では、人間が見た目の明るさでは2倍ぐらいになりますけども、光の実際の量は2倍どころではなく、もっと大きい差になります。

では、その刻みがどういう規則に則っているかというと、これがまた確固たる規則は規定されていなくて、例えば液晶ディスプレイですと、階調電源をいじることにより「ガンマ(γ)」という値を自在に変えられるようになっています。

以上、長くなりましたが
階調の値と言うのは物理量ではなくて、ある人間がある条件で決めた勝手な数値ということです。

Qchar AA[]{"全角文字"};から"全"という一字を取り出したい

 今晩は、Cの初心者です、宜しくお願いします。
 全角文字の入ったchar AA[]{"全角文字"};から"全"という文字一字を取り出す時にAA[0]とかくとエラーになります。
 どのようにしたら取り出せるのでしょう。
 ポインタを使う方法と使わない方法を教えて下さい。
 宜しくお願いします。

Aベストアンサー

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出す必要があります。

>char AA[]={'全','角'};

char AA[]="全角";
とし
>printf("%s%s\n" , AA[0],AA[1] ) ;

printf("%c%c\n" , AA[0],AA[1] ) ;
とすれば、「全」だけを表示する事が可能と思われます。

日本語を文字列で表示する為の文字コードについては
Shift-JISだけでなく、UnicodeやUTF・EUC・JISなどがあります。

もう少し詳しく記載してあるホームページはないか探してみましたが、ちょっと無理でした。

参考URL:http://marupeke296.com/CPP_charUnicodeWideChar.html

お疲れ様です。

まずお伺いしたのがOSおよび開発するためのコンパイラです。

ロケール等の話は分かりませんが、昔のC言語で日本語を扱う場合には全角文字1文字で2個つのchar領域を使用していました。
(マルチバイト文字セットと言います。)

詳細は参考URLを参照の事。

windowsでVCと仮定した場合、charを使われていると言うことは、多分、shift-jis(シフトJIS)で文字列を扱っていると思われます。

結論として全角文字1文字だけを取り出したいという場合は、結局char2個分のデータを取り出...続きを読む

Q数字だけを入れれば良かったのに単位まで入れてしまい、困っています。

本当は半角で数字だけを入れないといけないのに「1冊」「2頁」などのようにひとつのセルに数字と単位を一緒に入れてしまいました。これらを数字だけにできないでしょうか?「1冊」を「1」とする方法は無いでしょうか?しかも数字を半角で入れないといけないに全角で入れてしまいました。なんとか短時間で変換する方法がないでしょうか?今からやり直しても時間が間に合いそうに無いので、少しでも早くできる方法を教えて下さい。よろしくお願いいたします。

Aベストアンサー

Ctrl+Hで、検索する文字列に「冊」を入力し、置換後の文字列には何も入力せずに全置換すれば大丈夫だと思います。
試してみましたが、全角の数字も自動的に半角になってくれました。
但し、セルの書式は標準になっている必要があります。

Qchar *str; と char* str;

char *str; と char* str;
どっちも同じことを意味しているんですか?

Aベストアンサー

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染むのでしょう。ちなみにそういう風な人たちは

char *str1, *str2;

とは、書けない体になっています。

char* str1;
char* str2;


変数の宣言だと、C に慣れていれば、char* str というのはちょっと違和感があるのは
私も分かりますが、関数のプロトタイプ宣言だと、どちらの方がすっきりしますか?

extern char *memcpy(char *, const char *);

extern char* memcpy(char*, const char*);


# まあ、どっちが正しい、っていうんじゃ無いんですよね

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染む...続きを読む

Q校閲お願いします。 長さ、重さの単位変換です 数字に誤りがないか確認してください お願いします 左

校閲お願いします。
長さ、重さの単位変換です
数字に誤りがないか確認してください
お願いします

左下は関係ありません

Aベストアンサー

重量で、「1分」が正式に単位として用いられていたかどうか知りませんが、1分 = 1/10 匁 とすると
 1分 = 0.375 g = 0.000378 kg
です。kg の数値が違っています。同様に
 1匁 = 3.75 g = 0.00378 kg

 尺貫法の「375 g 」の単位が何なのか読めませんが、あまり聞いたことがないような。

 あとは、目的が不明ですが、ヤードポンド法の重量「1ポンド」には
 1 lb = 453.59237 g = 0.45359237 kg
と kg を追加した方がよいと思います。

 それから、ヤードポンド法の ton は非常に紛らわしいので、何らかの「英トン」「米トン」「メートル法のトン」を区別する表記が必要かと思います。ここに書かれているのは「英トン」のようですが。
 「1 ship」と書かれているのが「米トン」のようですが、「ship」という単位表記は見たことがありません。

Qchar gyou[1024];でcharの表現範囲は-128~127間でと!gyou[1024]の

#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
char gyou[1024];
int gyousuu = 0;
if ( argc < 2 ){
printf("file mei ga nai\n");
return -1;
}
fp = fopen(argv[1], "r");
if ( fp == NULL ){
printf("fopen dekinai\n");
return -2;
}
while(fgets(gyou, sizeof(gyou), fp) != NULL){
gyousuu++;
}
fclose(fp);
printf("gyousuu=%d\n", gyousuu);
return 0;
}
 以上のプログラムは行数を計算してくれるプログラムです。
  計算結果が
  gyousuu=22 とでます。
 さて、char gyou[1024];でcharの表現範囲は-128~127間ですが、
 gyou[1024]の[1024]とは関係はありますでしょうか!?
  [1024]の意味は”要素数”と参考書に鉛筆書きがありました。
 charの表現範囲である1024は、はるかに超えているみたいですが?
  dharの表現範囲を1024が超えたとしても特に問題はなさそうです!
  このプログラムは動いていますのでは正常です。
  私の
  考え方としまして、何か誤りがありますでしょうか?
  よろしくお願いいたします。

#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
char gyou[1024];
int gyousuu = 0;
if ( argc < 2 ){
printf("file mei ga nai\n");
return -1;
}
fp = fopen(argv[1], "r");
if ( fp == NULL ){
printf("fopen dekinai\n");
return -2;
}
while(fgets(gyou, sizeof(gyou), fp) != NULL){
gyousuu++;
}
fclose(fp);
printf("gyousuu=%d\n", gyousuu);
return 0;
}
 以上のプログラムは行数を計算してくれるプログラムです。
  計算結果が
...続きを読む

Aベストアンサー

> さて、char gyou[1024];でcharの表現範囲は-128~127間ですが、
> gyou[1024]の[1024]とは関係はありますでしょうか!?
ない。
1024 のほうはただ単に領域の個数を表しているだけで、読み込もうとするファイルの 1 行のバイト数がこれを超えない限り別に 1000 でも 3327 でも構わない(ある程度以上大きくなると別の問題が出てくるが)。
ただ単に 1024 = 2^10 でプログラマにはよく見る数字、かつ、普通のテキストなら 1 行が収まりそうな長さなだけ。

QExcelの数字とその単位のセルの連携移動について

「Excelのセルの数字の移動について教えてください」と下記の質問をさせて頂き、

Excel 2007のセルA1、B1、C1において、
(1)A1に数字が有ればB1に数字が有る無しに関係なく、C1にA1の数字が設定される。
(2)A1に数字がなくてB1に数字が有れば、C1にB1の数字が設定される。
(3)A1に数字がなくてB1にも数字がない場合は、C1は空欄とする。
ご存知の方はぜひ教えてください。
よろしくお願いいたします。

下記のご回答を頂き    ・・・           =IF(A1&B1="","",IF(A1="",B1,A1))
は「ベストアンサー」にさせて頂きましたが、
A1にはその単位X1が・・・B1にはその単位Y1があり、
C1にA1の数字が設定された場合はD1にX1が設定され、
C1にB1の数字が設定された場合はD1にY1が設定され
C1が空欄の場合はD1は空欄となる方法は如何でしょうか。
ご存知の方はぜひ教えてください。お待ちしております。よろしくお願いいたします。

Aベストアンサー

D1に以下の数式を入力してください。
=IF(OR(C1="",NOT(OR(C1=A1,C1=B1))),"",IF(C1=A1,X1,Y1))

Qchar *name1[4] とchar name2[][4] の違いについて

C言語のことで質問があります。

char *name1[4]は
char *name1[4] = {"abcdefghi","jkl","l","mn"};
と宣言でき,ポインタを4つ確保した形となりました。

char name2[][4]は
char name2[][4] = {"abc","def","ghi","jkl","mno","pqr","stu","vwx"};
と4文字以内の文字列を初期化した数だけ確保した形となりました。

この結果からchar *name1[4]の意味は,char name2[][4]ではなくchar name2[4][]に近いと思いました。
しかし,char name2[4][]ではポインタを4つ確保した事にはならないみたいでコンパイルが通りません。
*name1[4]では4つのポインタを確保できるのに~と思ってしまいます。

ポインタと配列は別物と考えるべきなのでしょうか?
訳の分からない質問かもしれませんが,
何卒ご指導いただくようよろしくお願いします。

Aベストアンサー

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり、この場合のa1は、
変数ではなく、定数のようなものなのです。

複合的なケースについて見てみましょう。
char **q1; ポインタへのポインタ
 q1,*q1,**q1,q1[0],*q1[0],q1[0][0] のいずれも変数として
 扱うことができます。(値を代入することが文法的に許されます。
 ただし、実行時にはアクセス違反になる場合もあります。)
char q2[4][4]; 二次元配列
 q2,q2[0]は変数として扱うことができません。q2[0][0]のように
 して、初めて変数として扱えるようになります。
char *q3[4]; ポインタの配列
 q3は変数として扱うことができませんが、q3[0],*q3[0],q3[0][0]
 はいずれも変数として扱うことができます。
 なお、この定義は char *(q3[4]); とした場合と全く同じ意味です。
char (*q4)[4]; 配列へのポインタ
 q4,(*q4)[0],q4[0][0]はいずれも変数として扱うことができます。
 しかし、*q4,q4[0]は変数として扱うことができません。

char *name1[4]; と char name2[4][]; は確かに似ています。しかし
違うところもあります。それは、name1[0] が変数として扱えるのに
対し、name2[0] には値を代入できないという点です。(データの
具体的な構造については、inthefloiさんが書いておられる通りです。
> char name2[4][]ではポインタを4つ確保した事にはならないみたい
というのも、全くその通りで、配列の定義では、ポインタ変数の領域
を確保する余地はないのです。

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり...続きを読む

Q数字の単位を何万と表したいのですが。

同じ列にある数字を自動的に任意の単位で表したいのですが。
 例  11,000 20,000 125,000これらの数字がそれぞれ11万 2万 12.5万と表示させたいのですが、どうすれば良いのでしょうか?
すみませんが、どなたか教えて貰えないでしょうか。よろしくお願いします。 

Aベストアンサー

エクセルなら
=A1/10000 & "万"
でいいんじゃないですか?

Qchar c = 'a'; char h[1] = c; エラー

char型のものを char[]型に代入したいです。

char c = 'a';
char h[1] = c;

として、

h[0] は \x97
h[1] は \x00

にしたいです。
型変換の方法を教えてください。

Aベストアンサー

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数を確保します。
後半で、その中を初期化しています。
添え字は 0 からはじまるので、この場合、h[0] に c の内容が代入されます。
1個しか場所を確保していないので、 h[1] の位置のデータは内容が不定です。
文字列として h を扱いたいのであれば、 C の文字列には終端として 0 が必要ですから、
char c = 'a';
char h[2] = { c, '\0'};

のような書き方が必要になります。
これで、お望みのデータになると思います。

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報