1

私はここ数時間、この問題と格闘してきました。これは、3 年間のプログラミング学習で遭遇した奇妙な問題の 1 つです。

stdin から argv にある文字列を連結して、スペースで区切られたより長い文字列を作成しようとしています。これは私が最初に書いたコードです:

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

#include "stringtable.h"
#include "strhash.h"
#include "auxlib.h"


int main (int argc, char **argv) {
    int c;
    char* filename;

    while((c = getopt(argc, argv, "@:Dly")) != -1){
        switch(c){
            case '@': 
                printf("@ detected\n");
                char* debugString = optarg;
                int pos_in_input = optind;
                while(argv[pos_in_input][0] != '-' && argv[pos_in_input] != NULL){
                    strcat(debugString, " ");
                    strcat(debugString, argv[pos_in_input]);
                    pos_in_input++;
                    if(argv[pos_in_input] == NULL){break;}                  
                }
                printf("%s\n", debugString);
                break;
            case 'D':
                printf("D detected\n");
                break;
            case 'l':
                printf("l detected\n");
                break;
            case 'y':
                printf("y detected\n");
                break;
            default :
                printf("default detected\n");
        }
    }
}

上記のほとんどは、未完成のオプション処理です。対象のコード セグメントは、case : "@" の下の switch ステートメントにあります。while ループは、argv で見つかった文字列を連結して debugString を作成し、文字列が "-" で始まるか、argv の最後に達したときに停止することになっています。また、「strcat(debugString, " ");」で文字列の間にスペースを追加しています。問題を引き起こしているのはスペースを追加することです。

この方法でスペースを追加せずにすべての文字列を連結すると:

            while(argv[pos_in_input][0] != '-' && argv[pos_in_input] != NULL){
                strcat(debugString, argv[pos_in_input]);
                pos_in_input++;
                if(argv[pos_in_input] == NULL){break;}                  
            }

私は以下を取得します:

 Input: -@what is going on here?
Output: @ detected
        whatisgoingonhere?

これが私が期待した方法です。ただし、スペースを追加するコードを実行すると:

            while(argv[pos_in_input][0] != '-' && argv[pos_in_input] != NULL){
                strcat(debugString, " ");
                strcat(debugString, argv[pos_in_input]);
                pos_in_input++;
                if(argv[pos_in_input] == NULL){break;}                  
            }

次に、出力として次を取得します。

 Input: -@what is going on here?
Output: @ detected
        what  going on here?

「what」と「going」の間の 2 つのスペースに注意してください。何らかの理由で単語が削除されているにもかかわらず、私のプログラムはまだスペースを正しく追加しています。私は多くの異なる入力でこれを試しましたが、削除されるのは常に入力の 2 番目の文字列です。誰が何が起こっているのか知っていますか?

PS gcc -g -O0 -Wall -Wextra -std=gnu99 -lm でコンパイル

私が作成したインクルード ファイルはこのコードでは使用されていないため、問題は私のインクルードにはありません。

4

1 に答える 1

1

関心のあるコードは次で始まります。

            char* debugString = optarg;

これにより、debugStringポインターは指している場所と同じ場所optarg指します。これは、「新しい」文字列を決して割り当てません。を呼び出すことによりstrcat(debugString, ...)、 の終了後にメモリに表示されたものをすべて上書きしますoptarg。カオスが起こります。

この問題に対処するには、次を試してください。

            char debugString[1000];
            strcpy(debugString, optarg);

これにより、文字列のビットを using に詰め込むために 1000 バイトが割り当てられますstrcat。バッファの末尾を超えて書き込みを行わないようにするのは、ユーザーのdebugString責任です (したがって、連結するバイト数が 1000 バイトを超える場合は、それをどうするかを決定する必要があります)。

于 2011-10-08T22:42:33.437 に答える