文字列の2次元配列

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
asahi
記事: 8
登録日時: 1年前

文字列の2次元配列

#1

投稿記事 by asahi » 7ヶ月前

課題を解きましたが、別の解き方がないか探しています。

課題内容:
入力された英単語を複数形にするプログラムを作成する

やりたいこと
a 入力された英単語をそれぞれ配列english_words[]に保存
b english_words[]に保存さえた英単語を複数形に変換してenglish_words_plural[]に保存
c 出力

example
入力文字
cat
dog

処理a
english_wordsの配列0番目にcatを保存する
english_wordsの配列1番目にdogを保存する

処理b
english_words_pluralの配列0番目にcatsを保存する
english_words_pluralの配列1番目にdogsを保存する

処理c
出力

しかし、文字列の2次元配列の扱い方がわかりませんでした。
どなたかよい書き方ありましたらご教授お願いいたします。

<↑のやり方がわからなかったので一回ループ事に判定させたプログラム>

コード:

#include <stdio.h>
#include <string.h>
#define WORDS_NUM_MAX       256
#define WORDS_LENGTH_MAX    256
#define WORDS_LENGTH_MAX_BYTE WORDS_LENGTH_MAX/8
int main(void){
    // 自分の得意な言語で
    // Let's チャレンジ!!

    int words_num = 0;  /*入力単語数*/
    int words_mem_i = 0;
    int word_length = 0;                        /*英単語文字数*/
    int plural_offset = 0;                      /*複数形にするための文字オフセット*/
    char english_words[WORDS_NUM_MAX];          /*入力英単語*/
    char english_words_plural[WORDS_NUM_MAX];   /*複数形英単語*/
    
    scanf("%d",&words_num);
    
    for(words_mem_i = 0;words_mem_i<words_num; words_mem_i++)
    {
        memset(english_words_plural,'\0',WORDS_LENGTH_MAX_BYTE);
        scanf("%s",english_words);
        //printf("入力文字は%s\n", english_words);
        
        /*文字列長さ判断*/
        word_length = strlen(english_words);
        plural_offset = word_length -1;
        /*確認*/
        //printf("文字長さ%d\n",word_length);
        /*文字判断*/
        if(strstr(english_words+plural_offset,"s") != '\0' || strstr(english_words+plural_offset-1,"sh") != '\0' || strstr(english_words+plural_offset-1,"ch") != '\0' || strstr(english_words+plural_offset,"o") != '\0' ||strstr(english_words+plural_offset,"x") != '\0')/*末尾が s, sh, ch, o, x のいずれかである英単語の末尾に es を付ける*/
        {
            /*複数形*/
            strcpy(english_words_plural,english_words);
            strcat(english_words_plural,"es");
            printf("%s\n",english_words_plural);
        }
        else if(strstr(english_words+plural_offset,"f") != '\0')/*末尾が f, fe のいずれかである英単語の末尾の f, fe を除き、末尾に ves を付ける*/
        {
            /*複数形*/
            strncpy(english_words_plural,english_words,word_length-1);
            strcat(english_words_plural,"ves");
            printf("%s\n",english_words_plural);
        }  
        else if(strstr(english_words+plural_offset-1,"fe") != '\0')
        {
            /*複数形*/
            strncpy(english_words_plural,english_words,word_length-2);
            strcat(english_words_plural,"ves");
            printf("%s\n",english_words_plural);            
        }
        else if(strstr(english_words+plural_offset,"y") != '\0' && (strstr(english_words+plural_offset-1,"a") == '\0' && strstr(english_words+plural_offset-1,"i") == '\0' && strstr(english_words+plural_offset-1,"u") == '\0' && strstr(english_words+plural_offset-1,"e") == '\0' && strstr(english_words+plural_offset-1,"0") == '\0'))/*末尾の1文字が y で、末尾から2文字目が a, i, u, e, o のいずれでもない英単語の末尾の y を除き、末尾に ies を付ける*/
        {
            /*複数形*/
            strncpy(english_words_plural,english_words,word_length-1);
            strcat(english_words_plural,"ies");
            printf("%s\n",english_words_plural);            
        }           
        /*上のいずれの条件にも当てはまらない英単語の末尾には s を付ける*/
        else
        {
            /*複数形*/
            strcpy(english_words_plural,english_words);
            strcat(english_words_plural,"s");
            printf("%s\n",english_words_plural);            
        }
        
        //printf("リセットenglish %s\n",english_words_plural);
    }
    
  
    
    return 0;
}

かずま

Re: 文字列の2次元配列

#2

投稿記事 by かずま » 7ヶ月前

こんなのはいかがでしょうか?

コード:

#include <stdio.h>   // scanf, puts
#include <string.h>  // strchr, strcmp, strcpy

#define NUM_MAX  1000
#define LEN_MAX  64  // Pneumonoultramicroscopicsilicovolcanoconiosis

void make_plural(const char *word, char *plural)
{
	int len = strlen(word);
	const char *w = word + len;
	char *p = plural + len;
	if (len < 2)
		strcpy(plural, word), strcpy(p, "s");
	else if (strchr("sox", w[-1]) || !strcmp(w-2, "sh") || !strcmp(w-2, "ch"))
		strcpy(plural, word), strcpy(p, "es");
	else if (w[-1] == 'f')
		strcpy(plural, word), strcpy(p-1, "ves");
	else if (!strcmp(w-2, "fe"))
		strcpy(plural, word), strcpy(p-2, "ves");
	else if (w[-1] == 'y' && !strchr("aiueo", w[-2]))
		strcpy(plural, word), strcpy(p-1, "ies");
	else
		strcpy(plural, word), strcpy(p, "s");
}

int main(void)
{
	char word[NUM_MAX][LEN_MAX];
	char plural[NUM_MAX][LEN_MAX];
	int num, i;

	if (scanf("%d", &num) != 1) return 1;
	if (num > NUM_MAX) return puts("too many data"), 2;

	for (i = 0; i < num && scanf("%s", word[i]) == 1; i++) ;
	if (i != num) return puts("less data"), 3;

	for (i = 0; i < num; i++) make_plural(word[i], plural[i]);
	for (i = 0; i < num; i++) puts(plural[i]);
}
wolf -> wolves, knife -> knives ですが、
gulf -> gulfs, chief -> chiefs です。
tomato -> tomatoes ですが、piano -> pianos です。
sheep, carp は単複同形。
man -> men, mouse -> mice なんかはどうしますか?

かずま

Re: 文字列の2次元配列

#3

投稿記事 by かずま » 7ヶ月前

こっちのほうがいいでしょう。

コード:

void make_plural(const char *word, char *plural)
{
	int len = strlen(word);
	char *p = plural + len;
	strcpy(plural, word);
	if (len < 2)
		strcpy(p, "s");
	if (strchr("sox", p[-1]) || !strcmp(p-2, "sh") || !strcmp(p-2, "ch"))
		strcpy(p, "es");
	else if (p[-1] == 'f')
		strcpy(p-1, "ves");
	else if (!strcmp(p-2, "fe"))
		strcpy(p-2, "ves");
	else if (p[-1] == 'y' && !strchr("aiueo", p[-2]))
		strcpy(p-1, "ies");
	else
		strcpy(p, "s");
}

かずま

Re: 文字列の2次元配列

#4

投稿記事 by かずま » 7ヶ月前

かずま さんが書きました:
7ヶ月前

コード:

	if (strchr("sox", p[-1]) || !strcmp(p-2, "sh") || !strcmp(p-2, "ch"))
if を else if に修正します。

asahi
記事: 8
登録日時: 1年前

Re: 文字列の2次元配列

#5

投稿記事 by asahi » 7ヶ月前

かずまさん

ありがとうございます!2次元配列を用意して、各行のポインタを利用すればよかったんですね。
非常に助かりました。

1点質問があります。
なぜ、printfではなくputsを使ったのでしょうか

かずま

Re: 文字列の2次元配列

#6

投稿記事 by かずま » 7ヶ月前

asahi さんが書きました:
7ヶ月前
なぜ、printfではなくputsを使ったのでしょうか
printf より puts の方が簡潔だからです。

コード:

puts(plural[i]); 
printf("%s\n", plural[i]); 
fprintf(stdout, "%s\n", plural[i]); 
どれも実行結果は同じです。

printf は内部で、書式の解釈をするので、少し遅いと思います。

・% があるかどうかを常にチェックする
・% があると、
 ・#, 0, ' ', -, + などがあるかどうかをチェックする
 ・フィールド幅の数値があるかどうかをチェックする
 ・.精度の数値があるかどうかをチェックする
 ・l, h, ll, L などの長さ修飾子があるかどうかチェックする
 ・d, x, s, c, f, e などの変換指定子に従って可変個数引数から
  値を取り出し、文字列への変換を実行する

puts に比べて、面倒なことをたくさんやっているはずです。

返信

“C言語何でも質問掲示板” へ戻る