2010-12-02 9 views
2

更新版:C-Mallocの問題(多分何か他のもの)

私はこのコードをscanf/fgetsを使わずに動作させようとしています。ユーザーから文字を取得し、forループでネストされたwhileループを使用してポインタ配列に配置します。

 
#define WORDLENGTH 15 
#define MAXLINE 1000 

int main() 
{ 
    char *line[MAXLINE]; 
    int i = 0; 
    int j; 
    int n; 
    char c; 


    for (n=0; c!=EOF; n){ 
     char *tmp = (char *) malloc(256); 
     while ((c=getchar())!=' '){ 
      tmp[i]=c;  // This is no longer updating for some reason. 
      i++; 
      } 
     line[n++]=tmp; // 
     i=0; 
     printf("\n%s\n",line[n]); //Seg fault here 
    } 

    for(j = 0; j (lessthan) n; j++){ 
     printf("\n%s\n", line[j]); 
     free (line[j]); 
    } 

    return 0; 

ここで、私はsegフォルトを取得しています。 tmp [i]が正しく更新されない理由はわかりません。まだそれに取り組んでいます。

私は今までのところ、学期全体を通してプログラミングに関するこのことを学んだことはありません。私が学ぶのを助けてください。私はそれを愛している。

答えて

3

sizeof(WORLDLENGTH)、1つは間違っています。 mallocは整数をとり、WORLDLENGTHは整数です。 sizeof(WORLDLENGTH)は32ビットシステム用にコンパイルすると4の整数を与え、4バイトを割り当てます。

Btw - while ((c=getchar())!=' '||c!=EOF) - ここであなたの意思は何ですか? (a!=b || a!=c)のような条件は、bとcの両方にaがないため、b!= cの場合は常にtrueを返します。

他の人が指摘しているように、私はいつも0であるline[i]を印刷しています。おそらくline[n]を意味します。そして、あなたはtmp文字列を終了しません。

オーバーフローチェックはありません。したがって、単語がWORDLENGTHより長い場合、悪いバグに遭遇します。

+0

えーえ、私は完全にそれについて忘れていたが、私はもうしません!しかし、同じ問題をまだ得ている\\ – user527179

+1

あなたはmalloc(sizeof(char)* WORDLENGTH)を行う必要があります。 –

+0

sizeof(char)は、標準に従って1になることが保証されています。 – EboMike

4

line[i]を印刷し、直前にiを0に設定してください。代わりにline[n]を印刷してください。

また、終了文字0を忘れてしまった。そして、tmpを文字配列にしてstrdupとすると、line[n]に代入するとコードが簡単になります。

+0

0文字終了しますか?あなたは\ 0を意味しますか? – user527179

+0

'\ 0' == 0なので、私は通常後者を使用します:) –

1

printf行を変更してください - ではなくline[n]を印刷する必要があります。

1

まず、あなたのmalloc関数の式は、あなたの言葉のな長さのためにはsizeof文字enought回を割り当てる必要が

​​

間違っている(また、15は、あなたがdictionnaryで最長の単語を数えていない、少し小さいようですまたは例笑 は恥ずかしがり屋のcharことはありません「iforgettoputspacesinmyphrasestoscrewtheprogrammerは」小さい、あなたは簡単に256または512を打つことができます^^

をも

printf("\n%s\n",line[i]); 

int j = 0に変更する必要があります。

for(j=0;j<i;j++){ 
    printf("\n%s\n",line[j]); 
} 

あなた私はあなたが常に

+0

私は確信がありませんでした!私は潜在的にあまりにも多くのメモリを割り当てることを恐れていますか?私はそれを修正することを確認します。 – user527179

1

その他は、すでにあなたのコードにいくつかの特定の問題を語っているが、彼らが見逃しているように見える一つのことがcintでなければならないことではなく、同じラインを印刷変更することはありませんa char。それ以外の場合、EOFとの比較は期待どおりに機能しません。また

、あなたが取得しているセグメンテーション違反があるため、この手順は次のとおりです。

line[n++]=tmp; 
printf("\n%s\n",line[n]); 

あなたはすでにを持っているあなたはそれを印刷しようとし、次の配列要素にnをインクリメント。その二行目は次のようになります。

printf("\n%s\n",line[n-1]); 

あなただけ(ライセンス「あなたはくそ十分にやりたい」無料で)動作するいくつかのコードをしたい場合は、ここに私のコードライブラリから有用な抜粋です。

私は確信していませんなぜあなたはfgetsは避けるべきだと思っています。実際には非常に便利で非常に安全です。私はあなたがgetsを意味していたと仮定しています。それはあまり便利でなく、完全に安全ではありません。スペースやファイルの終わりではない文字がたくさんある場合は、割り当てられた領域の終わりを超えて楽しい書き込みをするため、コードのバッファオーバーランも発生しやすくなります。あなた自身を教育しているが、その一部は、それ行うことができる方法を確認するために、生産・テスト防弾コードを調べる必要がある場合、すべての手段によって

は、独自のコードを記述します。そして、あなたがでない場合は、あなた自身を教育している、あなたは自由に利用可能なコードを使用しないことで自分自身をやっている。

スニペットは、以下:

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

#define OK  0 
#define NO_INPUT 1 
#define TOO_LONG 2 
static int getLine (char *prmpt, char *buff, size_t sz) { 
    int ch, extra; 

    // Get line with buffer overrun protection. 
    if (prmpt != NULL) { 
     printf ("%s", prmpt); 
     fflush (stdout); 
    } 
    if (fgets (buff, sz, stdin) == NULL) 
     return NO_INPUT; 

    // If it was too long, there'll be no newline. In that case, we flush 
    // to end of line so that excess doesn't affect the next call. 
    if (buff[strlen(buff)-1] != '\n') { 
     extra = 0; 
     while (((ch = getchar()) != '\n') && (ch != EOF)) 
      extra = 1; 
     return (extra == 1) ? TOO_LONG : OK; 
    } 

    // Otherwise remove newline and give string back to caller. 
    buff[strlen(buff)-1] = '\0'; 
    return OK; 
} 

 

// Test program for getLine(). 

int main (void) { 
    int rc; 
    char buff[10]; 

    rc = getLine ("Enter string> ", buff, sizeof(buff)); 
    if (rc == NO_INPUT) { 
     printf ("No input\n"); 
     return 1; 
    } 

    if (rc == TOO_LONG) { 
     printf ("Input too long\n"); 
     return 1; 
    } 

    printf ("OK [%s]\n", buff); 

    return 0; 
} 

それだfgetsと同じバッファオーバーフロー保護機能を有しており、あまりにもあり、ユーザによって入力された行を検出することができる有用なライン入力機能長いです。長すぎる行の残りの部分をスローし、次の入力操作に影響を与えないようにします。何が価値があるため

pax> ./qq 
Enter string> hello 
OK [hello] 

pax> ./qq 
Enter string> 
No input 

pax> ./qq 
Enter string> dfgdfgjdjgdfhggh 
Input too long 

pax> _ 

(と自分自身としてこれを手はありません:

サンプルは、「こんにちは」、CTRLD、そして大きすぎる文字列で実行されますあなたがほぼ確実に盗作に巻き込まれてしまうからです。半分くらいのレベルの教育者は、最初のこととしてあなたのコードをネット上で検索します)、これは私がそれにアプローチする方法です。

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

#define WORDLENGTH 15 
#define MAXWORDS 1000 

int main (void) { 
    char *line[MAXWORDS]; 
    int numwords = 0; // Use decent variable names. 
    int chr, i; 

    // Code to run until end of file. 

    for (chr = getchar(); chr != EOF;) {   // First char. 
     // This bit gets a word. 

     char *tmp = malloc(WORDLENGTH + 1);  // Allocate space for word/NUL 
     i = 0; 
     while ((chr != ' ') && (chr != EOF)) {  // Read until space/EOF 
      if (i < WORDLENGTH) {     // If space left in word, 
       tmp[i++] = chr;     // add it 
       tmp[i] = '\0';      // and null-terminate. 
      } 
      chr = getchar();      // Get next character. 
     } 
     line[numwords++] = tmp;     // Store. 

     // This bit skips space at end of word. 

     while ((chr == ' ') && (chr != EOF)) { 
      chr = getchar(); 
     } 
    } 

    // Now we have all our words, print them. 

    for (i = 0; i < numwords; i++){ 
     printf ("%s\n", line[i]); 
     free (line[i]); 
    } 

    return 0; 
} 

これを読んでコメントを書くことで、どのように動作しているかを知ることができます。コメント欄に質問があればお気軽に答えてください。


は、ここでサンプル実行です:

pax$ echo 'hello my name is pax andthisisaverylongword here' | ./testprog 
hello 
my 
name 
is 
pax 
andthisisaveryl 
here 
+0

私は、教師が助けを受けて何かの理由でそれを気に入らず、人々が自分のものよりも役に立つ答えを提供するので、私はそれを使用してはならない割り当てにfgetsを使いたくない現在あなたに教えています。なぜ彼らはこれを行うのですか私には分かりません。私はこの例を本当に感謝しています!私が持っているものよりずっと優れていますが、私はこのシナリオを強制する必要があります。私はそれも良いプログラミングの練習は、ボックスにはまっていると思う= \ – user527179

+1

その後、私は非常に貴重なアドバイスを提供します。 _Know_どのくらいのメモリを割り当てていますか?すでに書き込んだメモリの量を知ることができます。 _Never_後者が前者を超えるようにしましょう:-)いずれにせよ、私は自分の研究をしている学生に拍手を送るでしょう。 'fgets'を見て、それを理解してください。あなたがそれを求められたら、あなたはその場合にあなたの選択を守ることができます。教育者がそれ以上のことを知って私に印を付けると、私は教育機関にそれを伝えます。 YMMV。 – paxdiablo

+0

おそらく、なぜ私は現在セグメンテーション違反を受けているのですか? = \それは作業にとても近かったので、コードを変更します:Segフォルト。それを元に戻しますか?セグフォルト。 Whyyyyyyyyyyy – user527179

関連する問題