さきほども上げたのですがカテゴリが間違っていたのでもう一回書き込みました
まだプログラムの勉強をはじめた初心者なのですが、
テキストファイルから文字を読みこみ、大文字ならば小文字に変換し辞書順に並びかえるプログラムを作っているのですがどうしてもうまくいきません。
例えばtest.txtに
XXX YYY YY XX
BBB aaa aa BB
とあれば
aa
aaa
bb
bbb
xx
xxx
yy
yyy
と表示されるよにしたいんです。
自分が作ったプログラむはこれです。
まだテキストファイルからでなくキーボードからの入力になっていますが・・・
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <ctype.h>
int soto( const void *x, const void *y);
int main(int argc, char *argv[]){
FILE *input;
char str1[1000];
int i, j;
for (i = 1; i < argc; i++){
qsort(argv[i], 1000, sizeof( char *), soto);
strcpy(str1, argv[i]);
for(j = 0; j < 100; j++){
str1[j] = tolower( str1[j] );
}
printf("%s\n", str1);
}
return 0;
}
int soto( const void *a, const void *b){
char *x, *y;
x = (char*)a;
y = (char*)b;
return x-y;
}
これだと小文字にはなるんですがソートされずに表示されてしまいます・・・
どのようにすればいけるのかご指摘のほどおねがいします
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
この例だと、qsort()してから小文字変換しようとしてますね。
小文字にした状態で並べ替えるのなら、ソートの前にtolower()を全ての文字列に対し実行する必要があります。
それはさておき、qsort()関数のやってることに対する理解不足が、このプログラム開発を難しくしているようです。
まず最初に、qsort()を含めてsort系の関数は値を比較し、値の交換をして目的の並びへと変換します。
文字列は、文字という値の連続なので、そのままではソートできません。
つまり、[A][C][D][B][\0] という文字の並びを、[A][B][C][D][\0]と並べ替えることはできます。
しかし、[A][B][C][D][\0] , [A][A][A][B][C][\0] , [A][A][A][\0] という風に、
長さも内容も違う文字列を比較するのは
専用の関数を使う必要がありますし、文字列の交換は、qsort関数ではできません。
よって、一般的な対応策は次のようになります。
qsort()のコールバック関数soto()は、内部でstrcmpを使うか、同様の機能を実装する。
qsort()で並べ替える値は、文字列そのものでなく、文字列を指すポインタの配列、ポインタ配列を利用する。
ということです。
具体的な用法については、
http://www.geocities.jp/ky_webid/c/061.html
トップページは:http://www.geocities.jp/ky_webid/index.html
が詳しいと思います。
注意点として、このページの例ではchar* str_table[] = { "ccc", "ddd", "aaa", "bbb", "eee" };
という変数が用いられていますが、これは分かりやすく言うと、
「char型の、ポインタ配列str_tableを定義する。内容は"ccc", "ddd", "aaa", "bbb", "eee"の5つ」
となりますが、あなたの場合ポインタ配列の個数が未定義なので、大き目の固定長とするか、mallocで確保する必要があります
char *str_table[100];
int i;
for(i = 1; i < argc; i++){
str_table[i] = argv[i];
}
そして、上記のように全ての文字列をポインタ配列に登録してやる必要があります。
がんばってください。
No.4
- 回答日時:
> 例えばtest.txtに
> XXX YYY YY XX
> BBB aaa aa BB
> とあれば
> aa
> aaa
> bb
> bbb
> xx
> xxx
> yy
> yyy
> と表示されるよにしたいんです。
この要求を実現するには、
1.読み込む方法はどうするか。
2.読み込んだ文字列はどうメモリに格納するか。
3.大文字を小文字にどの段階で処理するのか。
4.ソートはqsort()を使うとして比較関数をどう使うか。
などの問題を決めて置かなければプログラムを組むことはできません。
このような現実に「初心者ではきつい」ように私も思います。
以下に回答例を示しますが、UNIX的リダイレクトを使って処理するものです。
Windowsの場合はリダイレクトに嫌悪感があるらしくほとんど使われないやり方ですが、どうしてもプロフラム中からtest.txtファイルを開いて行いたい場合は回答例に
fp=fopen("test.txt", "r")
などを加えれば動くように配慮したつもりです。このとき、fclose(fp)を忘れないでください。
/* UNIX的リダイレクト用のサンプル・プログラム */
#include <stdio.h> //for fscanf() etc.
#include <string.h> //for strcmp()
#include <stdlib.h> //for qsort()
#define SIZE 100 //行の大きさ
#define LEN 16 //列の大きさ
int compare(const void *x, const void *y){
return strcmp((char *)x, (char *)y);
}
int main(void){
char str[SIZE][LEN], *p; //SIZE行、LEN列の格納用文字配列strを用意
int j, k, n=0;
FILE *fp=stdin; //標準入力パスから読み込む
/* データの読み込み */
fscanf(fp, "%s %s %s %s", str[n], str[n+1], str[n+2], str[n+3]);
while(!feof(fp)){
printf("%s %s %s %s ", str[n], str[n+1], str[n+2], str[n+3]);
n += 4;
fscanf(fp, "%s %s %s %s", str[n], str[n+1], str[n+2], str[n+3]);
}
printf("\n");
/* 小文字へ変換 */
for(j=0; j<n; j++){ //j行目
for(k=0; str[j][k]; k++){ //k列の文字について
p=&str[j][k]; //文字のアドレスをセットし、
if('A' <= *p && *p <= 'Z') *p += 0x20; //補正
}
}
/* ソート */
qsort(str, n, LEN, compare);
/* ソート結果 */
for(j=0; j<n; j++){
printf("%s ", str[j]);
}
printf("\n");
return 0;
}
/* --- ./a.out < test.txt 実行結果 ---
XXX YYY YY XX BBB aaa aa BB
aa aaa bb bbb xx xxx yy yyy
Windowsの場合
○○○.exe < test.txt
*/
No.3
- 回答日時:
全体的にいくつかの致命的な問題があります。
・qsort の使い方が違う
・文字列と文字が混同されている
などなど。
初心者には難しい課題だと思います。
参考までにコードを書いてみました。
--
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_ENTRIES 1000
#define DELIM " \t\r\n,;"
static void
strtolower ( char * s )
{
while( *s ){ *s = tolower( *s ); s++; }
}
static int
strcmp_p ( const void * p1, const void * p2 )
{
return strcmp( *(char * const *)p1, *(char * const *)p2 );
}
static void
read_words ( FILE * file, char *** p )
{
char buf[4096];
while( fgets( buf, sizeof buf, file ) ){
char * token = strtok( buf, DELIM );
if( token ) do {
**p = strdup( token );
strtolower( **p );
(*p)++;
} while( ( token = strtok( NULL, DELIM ) ) );
}
}
extern int
main ( int argc, char ** argv )
{
char ** words = malloc( sizeof (char *) * MAX_ENTRIES );
char ** p = words;
if( argc == 1 ){
read_words( stdin, &p );
}
else while( 0 < --argc && *++argv ){
FILE * file = fopen( *argv, "r" );
if( ! file ){ perror( *argv ); continue; }
read_words( file, &p );
fclose( file );
}
qsort( words, p - words, sizeof (char *), strcmp_p );
while( words < p ){ fprintf( stdout, "%s\n", *words++ ); }
return EXIT_SUCCESS;
}
No.2
- 回答日時:
くわしくは見てませんが、
> int soto( const void *a, const void *b){
> char *x, *y;
>
> x = (char*)a;
> y = (char*)b;
>
> return x-y;
>
> }
return x-y; は単にポインタの引き算をしているだけで、文字列の比較をしていることにはなりませんよ。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C#からC言語で作成したDLLに文...
-
ftoa の作り方
-
-'0'の意味について
-
charからLPTSTRへの変換方法
-
fgetsなどのときのstdinのバッ...
-
プログラミング(関数reverseを...
-
str系関数を使わずに二つの文字...
-
文字列から空白を取り除きたい...
-
C言語の入力した文字を反転させ...
-
double型の値をchar配列に変換...
-
”あいうえお” を ”おえういあ...
-
バイナリファイルをコピーする...
-
入力された文字列から整数だけ...
-
絶対パスからのファイル名の切...
-
配列をnビットシフトする
-
Win32APIでのエディットボック...
-
C言語のfor文です。 繰り返しの...
-
'const char *' 型は 'char *' ...
-
構造体の各メンバにfor文からア...
-
C言語 バイナリファイルをfloa...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
CStringをwchar_tに変換したい
-
charでの計算?
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
'const char *' 型は 'char *' ...
-
テキストデータをそのままバイ...
-
配列をnビットシフトする
-
半角カナ→16進
-
double型の値をchar配列に変換...
-
sprintfに同じ変数は使えるか
-
ファイル名である文字列からbas...
-
ネットワークにつながっている...
-
ftoa の作り方
-
間接操作のレベルとは
-
型変換
-
C言語です
-
C言語のfor文です。 繰り返しの...
-
Win32APIでのエディットボック...
-
【C言語】文字型と整数型の違い
おすすめ情報