2016-08-27 4 views
2

this HackerRank problemを解決しようとしているときにこの現象が発生しました。このサイトでは、scanfを使用して、適切な形式のデータをユーザーのコードに渡します。ここまでは順調ですね。scanf - 奇妙な動作:2つの連続した呼び出しが1つの異なる文字列と正しい文字列になります

p文字列のペアがあり、各文字列は別々の行にあります。各ペアについて、共通の部分文字列を持つかどうかによって、YESまたはNOを一度だけ印刷する必要があります。まあまあ。しかし、私は明らかな理由がないためにテストケースに失敗しています。

printfでデバッグした後に、何らかの理由でscanfを2回呼び出すと、最初の文字列が短いバージョンになり、2番目の文字列が追加されてオーバーラップします。 2番目の文字列は通常次の行に表示されます。 (デバッグモードでは、あなたがそうするかどうか)

問題のコード:失敗したテストケースの一つの

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

int main() { 
    int p; 
    scanf("%d", &p); 

    char *s1 = malloc(sizeof(s1)); 
    char *s2 = malloc(sizeof(s2)); 
    int len1, len2; 
    char *answers[] = { "NO", "YES"}; 
    int answers_i; 
    for(int i = 0; i < p; ++i) { 
     scanf("%s", s1); 
     scanf("%s", s2); 
     printf("%s\n%s\n", s1, s2); 
     len1 = strlen(s1); 
     len2 = strlen(s2); 
     answers_i = 0; 
     for(int j = 0; j < len1 && answers_i == 0; ++j) { 
      for(int k = 0; k < len2; ++k) { 
       if(s1[j] == s2[k]) { 
        // printf("s1[%d]=%c s2[%d]=%c\n", j, s1[j], k, s2[k]); 
        answers_i = 1; 
        break; 
       } 
      } 
     } 
     // printf("%s\n", answers[answers_i]); 
    } 

    return 0; 
} 

入力:

10 
dapkqnowwvdrknfvcmanjuroumppajrzklucroxvpfmcsclqa 
ivtnjtgiogmwhqybjaxlktqbwsdhqrwovoavetymkpcco 
hrtybirxncuiailznohfawjwipdtupnxnisbwcplozwrzt 
ngdmqotxkpnuhmpfmajthzdtnztrqyugendiublcwp 
rmpwlddwttapjzhdldjmuhmgruufltzszprzdcziigc 
bbvvkeqkqekqqennyxqxkxnyxnyqnnybnbvnyqqe 
annbjookwtqkoivcgbqckqtvgvktobctktgkkjiac 
zsspfhmzpurrrlurdsdlrfldzyldfhudfedrszdpmsudh 
yuuuydwovzawzamvydaaadkakukpynwfmpnmuaazokxkmjxawo 
rqiqbhgscsetgihrrrgsqrlqgcbcbrettlehbeistbiqbisie 
ibvmfltfdvlmentbfdemebbnvllfneeefnaamtblt 
gukzzrqruyxsrqhyuggkrjujkwjhqhqsrqgkrkqxpszrzk 
nakqzfroqouhgunxqvqbxwtibfodsvoilqrpvhtgzoholxd 
bqluorjgkkrvmiptnxegxwlhrstiiafbfoxodzyguhdwi 
oyvgelovlyevhhedoeolyhdevcvhgceydcdehgvoc 
wsqswjnjpiarszzzxpmptrquwbnbzqiqqtzqnbajnpsjfaxr 
hvkmgwawagozzabgmdmdvbbaxadawmbazvxohxzv 
sfiltrslqepytjpfffqlrpejiueftrnisnnppnlpuficrjys 
nvsovybaljmzenkfgayfoxzcjantbdidxflbkhbixgzk 
qdphnbrjmznztnphhutkdbwjzmjwugtxggxchzcidngplj 

が出力

dapkqnowwvdrknfvcmanjuroumppajrzivtnjtgiogmwhqybjaxlktqbwsdhqrwovoavetymkpcco 
ivtnjtgiogmwhqybjaxlktqbwsdhqrwovoavetymkpcco 
hrtybirxncuiailznohfawjwipdtupnxngdmqotxkpnuhmpfmajthzdtnztrqyugendiublcwp 
ngdmqotxkpnuhmpfmajthzdtnztrqyugendiublcwp 
rmpwlddwttapjzhdldjmuhmgruufltzsbbvvkeqkqekqqennyxqxkxnyxnyqnnybnbvnyqqe 
bbvvkeqkqekqqennyxqxkxnyxnyqnnybnbvnyqqe 
annbjookwtqkoivcgbqckqtvgvktobctzsspfhmzpurrrlurdsdlrfldzyldfhudfedrszdpmsudh 
zsspfhmzpurrrlurdsdlrfldzyldfhudfedrszdpmsudh 
yuuuydwovzawzamvydaaadkakukpynwfrqiqbhgscsetgihrrrgsqrlqgcbcbrettlehbeistbiqbisie 
rqiqbhgscsetgihrrrgsqrlqgcbcbrettlehbeistbiqbisie 
ibvmfltfdvlmentbfdemebbnvllfneeegukzzrqruyxsrqhyuggkrjujkwjhqhqsrqgkrkqxpszrzk 
gukzzrqruyxsrqhyuggkrjujkwjhqhqsrqgkrkqxpszrzk 
nakqzfroqouhgunxqvqbxwtibfodsvoibqluorjgkkrvmiptnxegxwlhrstiiafbfoxodzyguhdwi 
bqluorjgkkrvmiptnxegxwlhrstiiafbfoxodzyguhdwi 
oyvgelovlyevhhedoeolyhdevcvhgceywsqswjnjpiarszzzxpmptrquwbnbzqiqqtzqnbajnpsjfaxr 
wsqswjnjpiarszzzxpmptrquwbnbzqiqqtzqnbajnpsjfaxr 
hvkmgwawagozzabgmdmdvbbaxadawmbasfiltrslqepytjpfffqlrpejiueftrnisnnppnlpuficrjys 
sfiltrslqepytjpfffqlrpejiueftrnisnnppnlpuficrjys 
nvsovybaljmzenkfgayfoxzcjantbdidqdphnbrjmznztnphhutkdbwjzmjwugtxggxchzcidngplj 
qdphnbrjmznztnphhutkdbwjzmjwugtxggxchzcidngplj 

出力は入力と等しくなければなりませんが、明らかにそうではありません。最初の文字列は32文字でキャップされ、2番目の文字列全体が追加されます。しかし、2番目の文字列自体は変更されていません。この2つの間で正確に何が起きているのですかscanf

私はgets(oops、廃止予定)とgetcharを使用しましたが、問題は解決しません。文字列のサイズがわからないので、fgetsは役に立たない。私は他の標準的な選択肢を知らない。

注:誰もがHackerRankにこのコードを試してみたい場合は、Test against custom inputのためのボックスをチェックしてください&が、その後Runボタンをクリックし、上記の入力をコピー&ペースト。

+3

'char * s1 = malloc(sizeof(s1));'は4バイトまたは8バイトを割り当てます。 – mch

+0

制約によれば、入力のサイズは100000バイトまでです。 – Barmar

答えて

4

コードには未定義の動作があります。あなたのコードの問題は、メモリをs1s2に割り当てることです。ポインターのサイズであるsizeof(s1)バイトを割り当てます。ポインタのサイズよりも多くのデータを読み込むと、割り当てられたバッファを越えて書き込みが行われ、未定義の動作が発生します。

問題制約は| a |、| b |を呼び出します。 、次のように割り当てがなければならないので:

char *s1 = malloc(100000 + 1); 
char *s2 = malloc(100000 + 1); 

注ヌルターミネータのために割り当てられた余分なバイト。

機能終了時にfree(s1)free(s2)に電話する必要があります。

+0

以前の問題では、scanfはちょうどポインタを割り当てても問題ありませんでした。これは実際には未定義の動作でしたが、gccはちょうど追加メモリを自動的に割り当てるべきであると判断しましたか? –

+0

@MiroslavCetojevicプラットフォームによっては、すべての文字列の長さが3文字または7文字未満でない限り、これは実際には未定義の動作でした。 'malloc'は小さな番号を渡すときに尋ねるものより少し多くを割り当てるので、コードはUBであっても正常に動作します(コードはまだ間違っています)。 [valgrind](http://valgrind.org/)でUBのコードをテストできます。 – dasblinkenlight

+0

ええ、ほとんどの文字列は7文字を超えていました。新しいことを学びました。 –

関連する問題