2017-07-13 9 views
1

文字列テストに文字を追加しようとすると、セグメンテーションエラーが発生します。私は複数の反復を試みたが、なぜエラーが出るのか理解できない。テストを\0に設定しようとしました。私は外部テストにどのようにアクセスしているのか分かりません。文字列と文字を連結しようとしたときのCのセグメンテーションエラー

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

#define _XOPEN_SOURCE 
#include <unistd.h> 
#include <crypt.h> 

//this intializes the argument count and argument vector 
int main(int argc, string argv[]) { 
    //this makes sure it is a string 
    if (argv[1] != NULL) { 
     //this makes sure that the user typed 2 arguments, 
     // the second being the keyword 
     if (argc != 2) { 
      printf("no hash inputed\n"); 
      return 1; 
     } 

     //main program once the keyword has been verified 
     int h_len = strlen(argv[1]); 
     string hash = argv[1]; 
     string test = "A"; 
     int p_len = 0; 
     printf("H len is %i and P len is %i\n", h_len, p_len); 
     printf("%s and test: %s\n", hash, test); 

     //this will iterate through the 1st space and test the charachters 
     for (int j = 0; j < 4; j++) { 

      //iterates through the characters that can be used in the password 
      //for (int i = A; i < z; i++) 
      //for (char ch = 'A' ; ch <= 'z' ; ch == 'Z' ? ch = 'a' : ++ch) 
      for (char i = 'A'; i <= 'z'; i++) { 
       //this skips the ASCII inbetween Z and a 
       if (i > 'Z' && i < 'a') { 
        i = 'a'; 
       } 
       printf("%c", i); 
       //test[j] = test[j] + (char)i; 
       test = strncat(test, &i, 1); 
       printf(" test is %s\n", test); 
       ... 
+3

あなたは 'argv'をチェックする前に' argv [1] 'にアクセスする必要があります。 –

+1

テスト用に1文字を割り当ててから追加しようとしました。 – Spaceghost

+1

コードには '//これはユーザが2つの引数をタイプしたことを確認します '。これらは 'argv [1]'と 'argv [2]'にあり、同じ引数に渡されるときに '' one two ''のような引用符で囲まなければなりません。しかし、コードには、if(argc!= 2)という引数が1つだけ**テストされています - 最初は実行可能ファイルの名前です。 –

答えて

-1

すべてがここで間違っている

あなたカントstrcatのはchar *と、その文字の後にゼロがある場合は、あなたが知っていることはないと文字のアドレス。文字列が短すぎるため、1つの文字列よりも長い文字列には対応できません。次に、testが文字列リテラルを指しているので、ROメモリを使って何かをしようとします。

購入C

+0

'' strncat'は、1を渡すとNULL終止符を必要としません。文字列は短すぎますが、大部分は配列ではないポインタなので、サイズは何でもセグメンテーションされます –

+0

ええとstrcat –

+1

@ Jean-FrançoisFabre:より正確には、文字列リテラル*を指しているため未定義の動作です。 – chqrlie

0

に関する良い本あなたはそれで一つの文字(テスト=「A」)で文字列を持っているので、それが2(A +ヌル文字)の長さを有し、他の文字を追加しようとしていますそれで、それはテストの外にアクセスします。この宣言で

+1

不完全な答え。 'test'は文字列リテラルを指します:それを修正しようとすると、未定義の動作が起こります。 – chqrlie

4

string test = "A"; 

リテラル"A"文字列へのポインタtestが宣言されています。文字列リテラルは変更できません。

C標準(6.4.5文字列リテラル)

7によれば、これらの配列は、それら 要素が適切な値を有する別個設けられているかどうかを指定されていません。 にプログラムの試みは、このような配列を変更した場合、動作は

test = strncat(test, &i,1); 

この声明の中でしかし

未定義であるリテラルは、ポインタ testによって指される文字列を変更しようとする試みがあります。

追加の文字を格納するのに十分なスペースがある文字配列を宣言する必要があります。また

あなたは関数が常に終端ゼロを付加しますので、あなたがn + 1文字のコピー先の配列にメモリを確保する必要があり、ソース文字列からnの文字をコピーする機能strncatを使用している場合。

ある(C規格、7.23.3.2 strncat関数、302脚注)

302)したがって、 配列で終わることができる文字の最大数は、S1によって指さがstrlen関数であります(s1)+ n + 1となる。この恐ろしいCS50で、stringは、char *として定義されていること

+1

@chuxこれを明確にするために、私は標準からの脚注に答えを追加しました:) –

+0

この脚注はここで明快さを加えただけでなく、私が3つの更新を義務づけてきた様々な投稿を再検討しました。 – chux

+1

@chux:はい、 'strncat()'は 'strncpy()'よりもはるかに美味です。実際には文字列の切り捨てを実装するにはまともな方法です: 'char dest [10] =" "; strncat(dest、src、sizeof(dest)-1); ' – chqrlie

1

注のでstring test = "A";長さ1とNULLの文字列定数にテストポイントを行いますchar *test = "A";と同等です!

何かを連結するのに十分な長さであっても、それは読み取り専用であり、読み取り専用ではないにしても不可能ではありません。

関連する問題