简体   繁体   English

C-为什么我的数组被覆盖?

[英]C - Why is my array being overwritten?

I might start out by saying that I am usually a C++ programmer, and I am inexperienced in doing I/O with C. I am writing a simple program that is trying to read a list of words from the user, alphabetize the letters in each word (preserving capital letters), and print them back out in the order received. 我可能会以说自己通常是C ++程序员开始,并且我对使用C进行I / O经验不足。我正在编写一个简单的程序,试图从用户那里读取单词列表,并对每个单词中的字母按字母顺序排序单词(保留大写字母),然后按收到的顺序将其打印回去。

I seem to have pinpointed the problem area (emphasized near the bottom of my code), yet even with a microscope on my code, it seems to be some kind of byzantine bug to me. 我似乎已经查明了问题区域(在我的代码底部附近强调了该问题),但是即使在我的代码上装有显微镜,对我来说这似乎也是一种拜占庭式的错误。 Here is my code: 这是我的代码:

int comp (const void* left, const void* right) { //for qsort
    return ( *(char*)left - *(char*)right );
}

int main() {
    printf("Please enter a sentence. Press enter to end.\n");
    char str[500]; 
    if (!fgets(str, sizeof(str), stdin)) { //grab line
        printf("die\n");
        return 1;
    }
    str[strcspn(str, "\n")] = 0; //finds newline and kills it
    printf("You entered:\n%s\n", str);

    char abc[sizeof(str)];    //alphabetized array
    int abc_count = 0;        //keeps track of effective size of abc
    char c;   
    char* word = &c;  //will read each word from line
    char* strr = str;  //made to get around a compiler error
    int offset;
    char capitals[25]; //keeps track of capital letters
    int cap = 0;
    int i = 0;

    while (sscanf(strr, " %s%n", word, &offset) == 1) { //%n gives number of characters read by sscanf

        if (i == 0) offset++;  //fixes length of first word, which has no space preceding it
        printf("read a word of size %d\n", offset-1);
        //make sure all letters are lowercase
        cap = 0;
        for (int j = 0; j < (offset-1); j++) {
            if ( isupper(word[j])) {  //if letter is capitalized
                word[j] = tolower(word[j]);     //lowercase it for sorting
                capitals[cap] = word[j]; //remember letter for later
                cap++;
            }
        }
        qsort(word, (offset-1)/sizeof(*word), sizeof(*word), comp);    //Alphabetize. "-1" makes offset not count space in length
        //recapitalize letters
        for (int j = 0; j < (offset-1); j++) {
            for (int k = 0; k < cap; k++) {
                if (word[j] == capitals[k]) {
                    word[j] = toupper(word[j]);  //recapitalize letter
                    capitals[k] = 0;    //capital has been used
                    break;
                }
            }
        }
        //write word to abc                ///// PROBLEM AREA /////
        printf("%s\n", word);
        for (int j = 0; j < (offset-1); j++) {
            if (i == 0) printf("first word: %s\n", word); //debugging
            printf("word[%d] = %c | ", j, word[j]);      //debugging
            abc[abc_count] = word[j];
            printf("abc[%d] = %c\n", abc_count, word[j]);  //debugging
            abc_count++;
        }
        if (i == 0) printf("first word: %s\n", word);
        abc[abc_count] = ' ';
        printf("abc[%d] = space\n", abc_count);
        abc_count++;
        if (i == 0) printf("first word: %s\n", word);
        printf("so far: %s\n\n", abc);
        if (i == 0) offset--; //undo correction for first word
        strr += offset; //stops infinite loop by moving pointer. This line is the reason "strr" exists instead of using "array type" str
        i = 1;
    } //while loop                       ///// PROBLEM AREA /////

    printf("Alphabetized: \n");
    for (i = 0; i < abc_count; i++) {
        printf("%c", abc[i]);  //I write directly from memory because somehow a null char is being added to "abc" after every word entered
    }
    printf("\n");

    return 0;
}

What I have found through extensive use of "printf" debugging is that one of my strings (always the first word entered) is being overwritten, as well as the front of the line to be output. 通过广泛使用“ printf”调试,我发现我的一个字符串(总是输入的第一个单词)以及行的开头都被覆盖了。 It is very bizarre. 这很奇怪。 Here is some sample output: 这是一些示例输出:

Please enter a sentence. Press enter to end.
Chocolate word cAT
You entered:
Chocolate word cAT
read a word of size 9
aCcehloot                //word is sorted as desired. No issues
first word: aCcehloot
word[0] = a | abc[0] = a
first word: aacehloot      //here you can see the strange overwrite behavior
word[1] = a | abc[1] = a
first word: aaaehloot
word[2] = a | abc[2] = a
first word: aaaahloot
word[3] = a | abc[3] = a
first word: aaaaaloot
word[4] = a | abc[4] = a
first word: aaaaaaoot
word[5] = a | abc[5] = a
first word: aaaaaaaot
word[6] = a | abc[6] = a
first word: aaaaaaaat
word[7] = a | abc[7] = a
first word: aaaaaaaaa    //first word is completely replaced by its first alphabetical letter
word[8] = a | abc[8] = a
first word: aaaaaaaaaa?n
abc[9] = space
first word: aaaaaaaaaa n
so far: aaaaaaaaa n

read a word of size 4
dorw
word[0] = d | abc[10] = d
word[1] = o | abc[11] = o
word[2] = r | abc[12] = r
word[3] = w | abc[13] = w
abc[14] = space
so far: orw

read a word of size 3
AcT
word[0] = A | abc[15] = A
word[1] = c | abc[16] = c
word[2] = T | abc[17] = T
abc[18] = space
so far: cT

Alphabetized:
cT  aaaaa dorw AcT
//the final result is shown as: everything but the first letter of the last word, 
//a cut-off remainder of the first overwritten word, the second word, then the third word

This part looks strange: 这部分看起来很奇怪:

char c;   
char* word = &c;  //will read each word from line

Here word is a char pointer pointing to a single char (ie c ). 这里的word是指向单个char(即c )的char指针。

Yet you do: 但是您可以:

sscanf(strr, " %s%n", word, &offset)

which will read multiple chars into to the memory pointed to by word . 它将多个字符读入word指向的内存中。 In other words you write to memory beyond c which is undefined bahavior (UB). 换句话说,您将超出未定义行为(UB)的内存写入c

I would expect word to be an array of chars (or point to an array of chars) to avoid out of bounds accesses (ie UB). 我希望word是一个字符数组(或指向一个字符数组),以避免超出范围的访问(即UB)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM