2016-10-20 6 views
0

リンクリストから母音を削除する際に問題が発生しています。プログラムはコマンドライン引数を受け取り、それらを1つの文字列で結合し、リンクされたリストに各文字をノードとして追加します。単独リンクリストから母音を削除できません

コマンドライン引数 "lemon"でプログラムを実行しようとすると、母音が正常に削除されます。すなわち、引数が結果的母音を含まない場合、母音は正常に削除される。 一方、私がコマンドライン引数 "aeiou"で同じことをしようとすると、プログラムがメッセージセグメンテーションフォールト(コアダンプ)でクラッシュします。これを処理する方法がわかりません。

プログラムはグローバル変数を作成してはいけませんので、私はダブルポインタを使用しました。 すべての関数が正しく動作しています。この問題は、locate()およびremoveVowels()関数の間違いのために発生する可能性がありますが、間違いが何であるか把握できません。

この問題はダブルポインタを使用して解決できますか? 私はこのプログラムで何が間違っているのか理解できません。私はプログラミングの初心者です。このことで私を助けてください。私を訂正してください。 ありがとうございます。出力用のスクリーンショットがある

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

struct linkedList { 
    char ch; 
    struct linkedList *node; 
}; 
void printMenu(void); 
char* combineWithNoSpaces(int, char *[]); 
void addTolinkedList(char *, struct linkedList **, int *); 
void printLinkedList(struct linkedList **); 
struct linkedList *locate(struct linkedList**); 
int delHead(struct linkedList **); 
void removeVowels(struct linkedList**); 
int isEmpty(struct linkedList **); 

int main(int argc, char *argv[]) { 
    int choice, indexer = 0; 
    struct linkedList *s; 
    char *string; 
    if (argc == 1) { 
     printf("Parse a sentence"); 
    } else { 
     s = (struct linkedList *) malloc(sizeof(struct linkedList)); 
     string = combineWithNoSpaces(argc, argv); 
     addTolinkedList(string, &s, &indexer); 
     while (1) { 
      printMenu(); 
      scanf("%d", &choice); 
      if (choice == 1) { 
       printLinkedList(&s); 
      } else if (choice == 2) { 
       if (!delHead(&s)) 
        printf("Failed.Empty linked list"); 
      } else if (choice == 3) { 
       removeVowels(&s); 

      } else if (choice == 4) { 
       if(isEmpty(&s)){ 
        printf("Empty LinkedList"); 
       } 
       else 
        printf("Not Empty"); 
      } else if (choice == 5) { 
       break; 
      } else 
       printf("Invalic choice"); 
      printf("\n"); 
     } 
    } 
    return 0; 
} 

int isEmpty(struct linkedList **s){ 
    if(*s == NULL) 
     return 1; 
    else 
     return 0; 
} 

struct linkedList *locate(struct linkedList **s) { 
    if ((*s)->node->ch == 'a' || (*s)->node->ch == 'e' || (*s)->node->ch == 'i' 
      || (*s)->node->ch == 'o' || (*s)->node->ch == 'u' 
      || (*s)->node->ch == 'A' || (*s)->node->ch == 'E' 
      || (*s)->node->ch == 'I' || (*s)->node->ch == 'O' 
      || (*s)->node->ch == 'U') { 
     return *s; 
    } else if ((*s)->node->node == NULL) { 
     return NULL; 
    } else 
     return locate(&((*s)->node)); 
} 
void removeVowels(struct linkedList **s) { 
    struct linkedList *temp, *tag; 
    /* Checking whether the first node is null or not */ 
    if ((*s)->ch == 'a' || (*s)->ch == 'e' || (*s)->ch == 'i' 
      || (*s)->ch == 'o' || (*s)->ch == 'u' 
      || (*s)->ch == 'A' || (*s)->ch == 'E' 
      || (*s)->ch == 'I' || (*s)->ch == 'O' 
      || (*s)->ch == 'U') 
     delHead(s); 
    do { 
     tag = locate(s); 
     if (tag != NULL) { 
      temp = tag->node->node; 
      free(tag->node); 
      tag->node = temp; 
     } 

    } while (tag != NULL); 
} 
int delHead(struct linkedList **s) { 
    struct linkedList *temp; 
    if ((*s) == NULL) { 
     return 0; 
    } else { 
     temp = (*s)->node; 
     free(*s); 
     *s = temp; 
     return 1; 
    } 
} 
void printLinkedList(struct linkedList **s) { 
    if ((*s) != NULL) { 
     printf("%c", (*s)->ch); 
     printLinkedList(&(*s)->node); 
    } 
    return; 
} 
void addTolinkedList(char *str, struct linkedList **s, int *indexer) { 
    if (*indexer == strlen(str)) { 
     *s = NULL; 
     return; 
    } else { 
     (*s)->ch = *(str + *indexer); 
     (*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList)); 
     ++*indexer; 
     addTolinkedList(str, &(*s)->node, indexer); 
    } 
} 
char * combineWithNoSpaces(int argc, char *argv[]) { 
    int i, j; 
    int count = 0; 
    int memory = 0; 
    char *str; 
    for (i = 1; i < argc; i++) { 
     for (j = 0; j < strlen(argv[i]); j++) { 
      ++memory; 
     } 
    } 
    str = (char *) malloc(memory * sizeof(char) + 1); 
    for (i = 1; i < argc; i++) { 
     for (j = 0; j < strlen(argv[i]); j++) { 
      *(str + count) = argv[i][j]; 
      ++count; 
     } 
    } 
    return str; 
} 
void printMenu(void) { 
    printf("\n\n" 
      "1. print input arguments (no spaces)\n" 
      "2. remove first character\n" 
      "3. remove vowels\n" 
      "4. is the linked list empty?\n" 
      "5. exit program\n" 
      "Enter your choice>"); 
} 

:引数AEIOU用 引数レモンについては
argument lemon
argument aeiou

+1

メニューおよび関連するコードを離れていたし、単に私たちに、リストを作成し、母音を削除し、その結果を出力するコードが示された場合、それは望ましいだろう - これはMCVEに近いだろうし([ MCVE])。問題に関係のないコードを歩き回る必要はありません。最小化プロセスは、しばしば問題を解決する。 –

+0

私は申し訳ありません、私は最善の方法で問題を提示しようとしました..次回はうまくいくでしょう – user3213732

+0

次回のために学びます。さて、私たちに聞いてみてください。あなたは 'isvowel()'関数を考えましたか?それは繰り返される5行のコードブロックです。静的インラインint isvowel(char c){...} '関数は読みやすさを向上させます。 –

答えて

1

このコードは私の満足に動作します

は、完全なコードを以下に示します。 。これは、より近いMCVE(Minimal, Complete, Verifiable Exampleある

私はrv19プログラムと呼ばれる、このように実行すると、それは出力が示さ与える:。。

$ rv19 apple 
[apple] 
[ppl] 
$ rv19 nutmeg 
[nutmeg] 
[ntmg] 
$ rv19 ply 
[ply] 
[ply] 
$ rv19 aeiou 
[aeiou] 
[] 
$ rv19 aardvark abstemiously facetiously aeiou minions lampoon shampoo 
[aardvarkabstemiouslyfacetiouslyaeiouminionslampoonshampoo] 
[rdvrkbstmslyfctslymnnslmpnshmp] 
$ 

コード(rv19.c):

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

struct linkedList 
{ 
    char ch; 
    struct linkedList *node; 
}; 

char *combineWithNoSpaces(int, char *[]); 
void addTolinkedList(char *, struct linkedList **, int *); 
void printLinkedList(struct linkedList **); 
struct linkedList *locate(struct linkedList **); 
int delHead(struct linkedList **); 
void removeVowels(struct linkedList **); 
void freeLinkedList(struct linkedList *); 

int main(int argc, char *argv[]) 
{ 
    int indexer = 0; 
    struct linkedList *s; 
    char *string; 
    if (argc == 1) 
    { 
     printf("Parse a sentence. Usage: %s word [word ...]\n", argv[0]); 
    } 
    else 
    { 
     s = (struct linkedList *) malloc(sizeof(struct linkedList)); 
     printf("s = %p\n", (void *)s); 
     string = combineWithNoSpaces(argc, argv); 
     addTolinkedList(string, &s, &indexer); 
     printLinkedList(&s); 
     removeVowels(&s); 
     printLinkedList(&s); 
     printf("s = %p\n", (void *)s); 
     freeLinkedList(s); 
     free(string); 
    } 
    return 0; 
} 

static inline int isvowel(char c) 
{ 
    return(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || 
      c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'); 
} 

struct linkedList *locate(struct linkedList **s) 
{ 
    if ((*s)->node == NULL) 
     return NULL; 
    if (isvowel((*s)->node->ch)) 
    { 
     return *s; 
    } 
    else if ((*s)->node == NULL) 
    { 
     return NULL; 
    } 
    else 
     return locate(&((*s)->node)); 
} 

void removeVowels(struct linkedList **s) 
{ 
    struct linkedList *temp, *tag; 
    /* Remove leading vowels */ 
    while ((*s) != NULL && isvowel((*s)->ch)) 
    { 
     //printf("Remove leading '%c'\n", (*s)->ch); 
     struct linkedList *ts = *s; 
     delHead(&ts); 
     *s = ts; 
    } 
    struct linkedList *n = *s; 
    while (n != NULL && (tag = locate(&n)) != NULL) 
    { 
     /* Remove multiple embedded or trailing vowels */ 
     while (tag->node != NULL && isvowel(tag->node->ch)) 
     { 
      temp = tag->node; 
      tag->node = tag->node->node; 
      free(temp); 
     } 
     n = tag->node; 
    } 
} 

int delHead(struct linkedList **s) 
{ 
    struct linkedList *temp; 
    if ((*s) == NULL) 
     return 0; 
    else 
    { 
     temp = (*s)->node; 
     free(*s); 
     *s = temp; 
     return 1; 
    } 
} 

void printLinkedList(struct linkedList **s) 
{ 
    struct linkedList *n = *s; 
    putchar('['); 
    while (n != NULL) 
    { 
     putchar(n->ch); 
     n = n->node; 
    } 
    putchar(']'); 
    putchar('\n'); 
} 

void addTolinkedList(char *str, struct linkedList **s, int *indexer) 
{ 
    if (*indexer == (int)strlen(str)) 
    { 
     free(*s); 
     *s = NULL; 
    } 
    else 
    { 
     (*s)->ch = *(str + *indexer); 
     (*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList)); 
     ++*indexer; 
     addTolinkedList(str, &(*s)->node, indexer); 
    } 
} 

char *combineWithNoSpaces(int argc, char *argv[]) 
{ 
    int argl[argc+1]; 
    int memory = 0; 
    for (int i = 1; i < argc; i++) 
    { 
     argl[i] = strlen(argv[i]); 
     memory += argl[i]; 
    } 
    char *str = (char *) malloc(memory + 1); 
    char *base = str; 
    for (int i = 1; i < argc; i++) 
    { 
     strcpy(base, argv[i]); 
     base += argl[i]; 
    } 
    return str; 
} 

void freeLinkedList(struct linkedList *node) 
{ 
    while (node != NULL) 
    { 
     struct linkedList *next = node->node; 
     free(node); 
     node = next; 
    } 
} 

これはまだまだ磨かれていませんが、出力の開始前と終了後にマーカーを取得するように印刷を変更しました。不要な空白やその他の文字が表示されやすくなりました。インターファックを変更するeを関数に渡すので、struct linkedList **の代わりにstruct linkedList *が必要です。 removeVowels()のコードは扱いにくいです。繰り返される初期母音を取り除くために反復する。母音以外の母音の後に繰り返される母音を取り除くために繰り返されます。 locate()関数は、次のノードに母音を持つ非母音ノードへのポインタを返すようになりました。このコードは、文字列とリストの両方を解放します(新しい関数freeLinkedList()を使用してリストを解放します)。

私はmalloc()のデバッグバージョンをいくつかチェックしましたが、リークフリーで破損していないようです。これはSVNからダウンロードした最新のコード(リビジョン16097とあった

valgrind: mmap-FIXED(0x0, 253952) failed in UME (load_segment1) with error 12 (Cannot allocate memory). 

:私はそれはMacOSのシエラ10.12でそれを構築した後、正常に実行することができませんので

私はまだvalgrindでそれを実行していません)。

+0

それは完璧に働いた..しかし、assert.hライブラリを使用せずにこれをやろうとしています.. – user3213732

+0

(1) 'assert.h'はヘッダであり、ライブラリではありません。 (2)プログラムの意味や操作を変更することなく、 'assert'を含むすべての行を単に削除することができます。 –

+0

OPからこのロジックを継承していますが、以前の再帰(および/または 'main()')の 'addTolinkedList()' clobber mallocされたメモリの最初の節で '* s = NULL; )それは決して自由になることができない? – cdlane

0

私はすべての機能を単純化しようとしました。ポインタを必要としないときに引数としてポインタを取っていたものがありました。

多くの変更のいくつかのハイライト:

メインは:switchステートメントにメイン制御構造を変更しました。空の文字列を入力するとmallocの代わりにlinkedListポインタをNULLに初期化するとaddTolinkedList()がこのメモリをリークします。終了オプションが選択されたときに、新機能freeLinkedList()を追加しました。

locate:locateVowel()という名前に変更され、removeVowel()で再構成され、母音を実際に探す場所が1つしかありません。潜在的なメモリリークを削除しました。

combineWithNoSpaces:これは文字指向ではなく文字列指向に書き換えました。

addTolinkedList:多数の問題を単純化した再帰時に増分するインデックス(er)引数を単純なintにしました。

#include <stdio.h> 
#include <ctype.h> 
#include <string.h> 
#include <stdlib.h> 
#include <stdbool.h> 

struct linkedList { 
    char ch; 
    struct linkedList *node; 
}; 

void printMenu(void); 
char* combineWithNoSpaces(int, char *[]); 
void addTolinkedList(char *, struct linkedList **, int); 
void printLinkedList(struct linkedList *); 
struct linkedList **locateVowel(struct linkedList **); 
bool delHead(struct linkedList **); 
void removeVowels(struct linkedList **); 
bool isEmpty(struct linkedList *); 
void freeLinkedList(struct linkedList *); 

int main(int argc, char *argv[]) { 
    int choice; 
    char *string; 

    if (argc == 1) { 
     fprintf(stderr, "Enter a sentence\n"); 
     return EXIT_FAILURE; 
    } 

    struct linkedList *s = NULL; 

    string = combineWithNoSpaces(argc, argv); 

    addTolinkedList(string, &s, 0); 

    free(string); 

    while (true) { 
     printMenu(); 
     (void) scanf("%d", &choice); 

     printf("\n"); 

     switch (choice) { 
      case 1: 
       printLinkedList(s); 
       break; 
      case 2: 
       if (!delHead(&s)) { 
        printf("Failed. Empty linked list\n"); 
       } 
       break; 
      case 3: 
       removeVowels(&s); 
       break; 
      case 4: 
       if (isEmpty(s)) { 
        printf("Empty LinkedList\n"); 
       } else { 
        printf("Not Empty\n"); 
       } 
       break; 
      case 5: 
       freeLinkedList(s); 
       return EXIT_SUCCESS; 
      default: 
       printf("Invalid choice\n"); 
     } 
    } 

    return EXIT_SUCCESS; 
} 

bool isEmpty(struct linkedList *s) { 
    return (s == NULL); 
} 

struct linkedList **locateVowel(struct linkedList **s) { 

    if (*s == NULL) { 
     return NULL; 
    } 

    char ch = tolower((*s)->ch); 

    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') { 
     return s; 
    } 

    return locateVowel(&((*s)->node)); 
} 

void removeVowels(struct linkedList **s) { 

    struct linkedList **vowel; 

    while ((vowel = locateVowel(s)) != NULL) { 
     struct linkedList *temporary = (*vowel)->node; 

     if (temporary == NULL) { 
      free(*vowel); // a vowel with nothing following it 
      *vowel = NULL; 
      break; 
     } 

     (*vowel)->ch = temporary->ch; 
     (*vowel)->node = temporary->node; 

     free(temporary); 

     s = vowel; 
    } 
} 

bool delHead(struct linkedList **s) { 

    if (*s == NULL) { 
     return false; 
    } 

    struct linkedList *temporary = (*s)->node; 
    free(*s); 
    *s = temporary; 

    return true; 
} 

void printLinkedList(struct linkedList *s) { 
    printf("\""); 

    while (s != NULL) { 
     printf("%c", s->ch); 
     s = s->node; 
    } 

    printf("\"\n"); 
} 

void addTolinkedList(char *string, struct linkedList **s, int index) { 
    if (index == strlen(string)) { 
     *s = NULL; 
    } else { 
     *s = malloc(sizeof(struct linkedList)); 

     (*s)->ch = string[index]; 
     (*s)->node = NULL; 

     addTolinkedList(string, &(*s)->node, index + 1); 
    } 
} 

char *combineWithNoSpaces(int argc, char *argv[]) { 
    int characters = 0; 

    for (int i = 1; i < argc; i++) { 
     characters += strlen(argv[i]); 
    } 

    char *string = calloc(characters + 1, 1); 

    for (int i = 1; i < argc; i++) { 
     (void) strcat(string, argv[i]); 
    } 

    return string; 
} 

void freeLinkedList(struct linkedList *s) { 
    while (s != NULL) { 

     struct linkedList *temporary = s; 

     s = s->node; 

     free(temporary); 
    } 
} 

void printMenu(void) { 
    printf("\n" 
     "1. print string (no spaces)\n" 
     "2. remove first character\n" 
     "3. remove vowels\n" 
     "4. is the linked list empty?\n" 
     "5. exit program\n" 
     "Enter your choice: "); 
} 
関連する問題