文字列に数字を含むデータのソートを行うプログラムを
C言語で作成したいのですが、どうすれば良いでしょうか?

具体的に言うと、a12、a2、a10という順序で並んでいる
データを昇順にソートした場合にa10、a12,a2というように
ソートせず、ちゃんとa2,a10,a12とソートされるように
したいのですが、簡単にできるものでしょうか?

質問がわかりにくいかもしれないのですが、どうかご回答をお願いします。

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

A 回答 (4件)

a1b12c6


a15b6
a1b12c3
a1b2...z26
こんな状況でしょうか。

ソートアルゴリズムを選択するときの基本は「データ数」と「キーの性質」、「未ソート状態のデータ並び」を把握することです。

場合によっては「第1キー~第nキーを使って全データを対象に一気にソートする」ことが正しい場合もあります。
ことによると「上位キーが同一値であったデータだけを対象として再帰的に部分ソートを繰り返す」ことが最良の場合があります。
    • good
    • 0
この回答へのお礼

どうもありがとうございます。大変参考になりました。
これを踏まえてもう少し考えて作成してみたいと思います。

お礼日時:2002/03/09 14:14

こういう「ちょっとややこしいデータ構成」にぶつかった場合は「データ構造の一般化」を試みます。



この場合、『数字以外の文字列』と『数字列』が連結されており、全体が'\0'で終結している文字列です。

と、言うことは2つの部分を分割すれば話は単純になります。
1.数字以外の文字列
2.数字列を数値化したもの
より簡単にするには構造体で置き換えた方が良いでしょう。

文字列から数字列の先頭を取り出すにはstrpbrk()を使うと簡単です。
char *strpbrk(char *str, char *accept);
対象の文字列をstrに、探すべき文字の集合(この場合'0'~'9')をacceptに指定します。
戻り値はacceptにある文字が見つかった最初のアドレスまたはNULL(見つからなかった)です。

だから、
#define ACCEPT "0123456789"
struct TAG {
char str[文字列の最大長+1];
int val ;
} tabl[データ数] ;/* <-ソート対象のテーブル */
char *pp ;
この状態でループして
strcpy(table[ii].str, data[ii]) ;
if ((pp = strpbrk(table[ii].str, ACCEPT)) == NULL) {
/* 数字無し */
table[ii].val = 0 ;
} else {
/* 数字あり */
table[ii].val = atoi(pp) ;
*pp = '\0' ;
}
を実行すれば『文字列』と『数値』に分割された配列にソート対象データが収容されます。
(元データが必要であればtable内に元データへのポインタを置いておきます)

table内で『文字列』と『数値』が分離しているのでソート処理自体は2つのキーによるソート処理を行えばいいだけです。


aの部分の仕様が不明だったので汎用的に考えましたが、固定で'a'が入っているのなら単純に無視するtakebouさんの回答が最適でしょう。

この回答への補足

数字文字列が複数存在して、その数も任意であるとすると、
最大の分割数のキーでソートすれば良いという考えであってます
でしょうか?

補足日時:2002/03/09 12:44
    • good
    • 0

すべてのデータのaの部分が一緒なのであれば、


aを切り離して数字部分をint型に変換すれば良いでしょう。
ちなみに文字列をint型に変える関数はatoi()です。
    • good
    • 0

こういうときは a2 とはせずに a02 とするのが


一般的だと思いますよ。

この回答への補足

回答ありがとうございます。
私もそう思います。でも今回求められているものは
桁合わせ的なことがされない任意の文字列なのです。

補足日時:2002/03/09 12:32
    • good
    • 0

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

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

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

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

Q2 ~ 200 の素数 a, b, c (a < b < c) が、b - a = c - b を満たすa,b,cをビット操作を用いて求め、すべてを表示せよ

ちょっと考えてみました。でも、分かりません・・・まず、int型のintvalに200bitを割り当てて、intval=0としたいのですが、どうしたらいいのでしょう??
とりあえず考えてみたプログラムを誰か見て下さい!!お願いします。
#define BYTESIZE 200
#define MAX 200
main()
{
int i,j,intval=0;
for(i=2;i<=MAX/2;i++)
{
if(intval&(1<<(i-1)){}
else for(j=i*2;j<=MAX;j+=i)intval|=(1<<(j-1));
}/*素数を0、それ以外を1に
for(i=2;i<=MAX/2;i++)
for(j=2;j<=(MAX-i)/2;j++)
if((intval&(1<<(i-1))&&(intval&(i+j-1))&&(intval&(1<<(i+2*j-1)))) print("%3d %3d %3d (%3d)\n",i,i+j,i+2*j,j);
}/*三つ子の素数を調べ出力

ちょっと考えてみました。でも、分かりません・・・まず、int型のintvalに200bitを割り当てて、intval=0としたいのですが、どうしたらいいのでしょう??
とりあえず考えてみたプログラムを誰か見て下さい!!お願いします。
#define BYTESIZE 200
#define MAX 200
main()
{
int i,j,intval=0;
for(i=2;i<=MAX/2;i++)
{
if(intval&(1<<(i-1)){}
else for(j=i*2;j<=MAX;j+=i)intval|=(1<<(j-1));
}/*素数を0、それ以外を1に
for(i=2;i<=MAX/2;i++)
for(j=2;j<=(MAX-i)/2;j++)
if((intval&...続きを読む

Aベストアンサー

まずint型は200ビットもありません。通常は32ビットです。
200ビット使いたければint型を7個用意する必要があります。
つまり
int intval[7];
宣言して、
intval[0] 0~31ビット
intval[1] 32~63ビット
intval[2] 64~95ビット
.
.
.
intval[6] 182~200ビット
として使います。

第iビットの情報を取り出すときは
(intval[i>>5]>>(i&31))&1

第iビットを1にするときは
intval[i>>5]|=1<<(i&31);

とすれば良いでしょう。
関数やマクロを用意することをお勧めします。
例えば
int get(int intval[],int i)
{
return (intval[i>>5]>>(i&31))&1;/*0か1が返って来る。*/
}

void on(int intval[],int i)
{
intval[i>>5]|=1<<(i&31);
}

という感じです。

まずint型は200ビットもありません。通常は32ビットです。
200ビット使いたければint型を7個用意する必要があります。
つまり
int intval[7];
宣言して、
intval[0] 0~31ビット
intval[1] 32~63ビット
intval[2] 64~95ビット
.
.
.
intval[6] 182~200ビット
として使います。

第iビットの情報を取り出すときは
(intval[i>>5]>>(i&31))&1

...続きを読む

QSTLのlist どのデータでソートするか分からないデータでソートを行うには?

class data
{
public:
文字列型* str; //コンストラクタでN個の配列を生成
int N; //文字列の配列の個数
};

list<data> obj;
と書いて、objに対して大量にデータを追加した後、その要素をソートするところで困っています。
データを文字列型のデータの配列の特定のオブジェクトを使ってソートするのに、その方法が見つかりません。

リストのデータの一つ目
str[0] = "abc";
str[1] = "def";
リストのデータの二つ目
str[0] = "ghi";
str[1] = "jkl";
というリストのデータがあったときに、str[0]の要素でソートしたいということなのですが........

メンバのint型などについては、operator<をオーバーロードする方法が見つかったのですが........

Aベストアンサー

>list::sortの使い方がよくわかりません。
普通に data 用の比較関数を作ればよいはずです。
比較方法を都度切り替えたいような場合は、関数オブジェクトにするのもよいでしょう。

Qマウスの位置でa,bの値が変化し、a,bの値が変化することでpx,pz

マウスの位置でa,bの値が変化し、a,bの値が変化することでpx,pzの値も変化し、車の座標が変わるようにしたいのですが、以下のようにするとマウスを動かしても反応がありません。
px = a; の部分を px = 10; にしてみると車の座標が変わるため、static void mouseの部分がおかしいと思うのですが、どう間違えているか分からないでしょうか?
文字数制限の関係上、関連する部分のみ抜粋します。


#include <stdlib.h>
#include <GL/glut.h>

#define W 6
#define D 9

int s,t,a,b;

static void display(void)
{
const static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 }; /* 光源の位置 */
const static GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 }; /* 車の色   */
static GLdouble px = 0.0, pz = 0.0; /* 車の位置  */
static GLdouble r = 0.0; /* 車の方向  */

px = a;
pz = b;

/* 画面クリア */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* モデルビュー変換行列の初期化 */
glLoadIdentity();

/* 光源の位置を設定 */
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

/* 視点の移動(物体の方を奥に移す)*/
glTranslated(0.0, 0.0, -25.0);
glRotated(30.0, 1.0, 0.0, 0.0);

/* シーンの描画 */
myGround(0.0);
glPushMatrix();
glTranslated(px, 1.0, pz);
glRotated(r - 90.0, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
glutSolidTeapot(1.0);
glPopMatrix();

glFlush();
}

static void resize(int w, int h){
s = w/2;
t = h/2;
}

static void mouse(int u, int v) //
{
if((s - u) > 0){
a = 10;
}else if((s - u) < 0){
a = -10;
}
if((t - v) > 0){
b = 10;
}else if((t - v) < 0){
b = -10;
}

}

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
glutPassiveMotionFunc(mouse);//マウスドラッグ時
return 0;
}

マウスの位置でa,bの値が変化し、a,bの値が変化することでpx,pzの値も変化し、車の座標が変わるようにしたいのですが、以下のようにするとマウスを動かしても反応がありません。
px = a; の部分を px = 10; にしてみると車の座標が変わるため、static void mouseの部分がおかしいと思うのですが、どう間違えているか分からないでしょうか?
文字数制限の関係上、関連する部分のみ抜粋します。


#include <stdlib.h>
#include <GL/glut.h>

#define W 6
#define D 9

int s,t,a,b;

static void display(void)
{
...続きを読む

Aベストアンサー

glutMainLoop();
glutPassiveMotionFunc(mouse);//マウスドラッグ時

どうしてglutMainLoopのあとでglutPassiveMotionFuncをコールしてるの?

Q1,1,2,3,5,8,13の合計

初心者ですみませんが、1,1,2,3,5,8,13の合計を出すプログラミングがどうしてもわかりません。どなたかご教示頂けましたら助かります。
宜しくお願いいたします。

Aベストアンサー

#include <stdio.h>

int main(void)
{
   printf("%d\n", 1+1+2+3+5+8+13);
}

Q昇順ソート

sort.txtから読み込んだ値を
昇順でソートして出力するにはどうしたらよいでしょうか?

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

/* 比較関数 */
int strcmp_asc(const void *, const void *);

int main(void)
{

FILE*fin, *fout;
inti;
intlength;
chars[256], s2[256];

if( (fin=fopen("sort.txt","r"))==NULL) {
printf("入力ファイルがオープンできません\n");
exit(EXIT_FAILURE);
}
if( (fout=fopen("file2.txt","w"))==NULL) {
printf("出力ファイルがオープンできません\n");
exit(EXIT_FAILURE);
}

while(fgets(s, 256, fin) != NULL) {

/* 要素数を求める */
length = sizeof(s) / 256;

/* 昇順でソート */
qsort(s, length, 256, strcmp_asc);

/*memset(s2, NULL, sizeof(s2));
for (i = 0; i < length; i++)
{

}
*/

fprintf(fout,"%s\n",s2);
}

fclose(fin);
fclose(fout);
return 0;
}

int strcmp_asc(const void *sa, const void *sb)
{
return strcmp((char *)sa, (char *)sb);
}


sort.txt
50
45
35
25
15
10
5
1
32
46
8
7
9
19
18
14
16
13
12
17
11
20
40
30
31
3
2
37
38
36
33
39
34
49
47
48
4
6
44
42
43
41
21
22
26
24
28
29
27
23

sort.txtから読み込んだ値を
昇順でソートして出力するにはどうしたらよいでしょうか?

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

/* 比較関数 */
int strcmp_asc(const void *, const void *);

int main(void)
{

FILE*fin, *fout;
inti;
intlength;
chars[256], s2[256];

if( (fin=fopen("sort.txt","r"))==NULL) {
printf("入力ファイルがオープンできません\n");
exit(EXIT_FAILURE);
}
if( (fout=fopen("file2.txt","w"))==NULL) {
prin...続きを読む

Aベストアンサー

★アドバイス
>sort.txtから読み込んだ値を
>昇順でソートして出力するにはどうしたらよいでしょうか?
 読み込み部分が正しくないありませんね。
 ファイルに数値のみしかないならfscanf()関数を使って
 すべてを配列に代入してからソートすれば良いでしょう。
・下にサンプルを載せておきます。

サンプル:
int data[ 10000 ]; ←ちょっと多めに宣言
int max;

// fscanfで読み込み
for ( max = 0 ; max < 10000 ; max++ ){
 if ( fscanf(fin,"%d\n",&data[max]) != 1 ){
  break;
 }
}
// ここでソート
qsort( data, max, sizeof(int), strcmp_value );

注意事項:
・比較関数の strcmp_value は作り直して下さい。
 作り方分かりますよね。
 ポイントは整数値の比較ですよ。


人気Q&Aランキング

おすすめ情報