C语言 我有一个编译器问题和一个关于它的问题

egdjgwm8  于 2023-04-29  发布在  其他
关注(0)|答案(4)|浏览(126)

这个问题似乎很容易描述,但很难理解。希望有经验的朋友可以帮助我:很简单,再一次:
1.当我通过Code::Blocks(mingw安装)编译我的C代码或程序时,它工作得非常好,并生成一个54 kb的文件,该文件完全按照预期工作。(耶)。
1.但是,当我通过gcc编译相同的C代码或程序时,无论是在cmd中还是在emacs中-编译都是成功的(41 kb文件大小),但是:我执行的时候代码就完成了一半。(??)它不打印它应该打印的东西(或任何东西)。它只是开始,然后结束(在cmd上快速)。不管我是在shell还是cmd中运行它,还是在代码块自己的cmd-thing上运行。(也就是说,如果我通过gcc编译它,然后执行main。exe文件通过代码块)。
(3.额外:问题中的程序是C编程书问题1中的问题。13:它接受一堆单词,并检查它们的长度,然后使用“”打印出垂直直方图。|当我通过Code::blocks编译它时,它执行得非常好;但是当我在emacs或cmd上通过gcc运行它时,它只是工作了一点,然后退出,根本没有打印任何行。所以我知道这是一个编译器问题,但我不知道如何修复它。我更愿意在将来通过gcc编译,但是如果编译的代码块版本更好,那么我别无选择,只能放弃gcc?你告诉我,因为我在这件事上很愚蠢。
我已经做了几个来回(删除主要。exe,并使用两者重新编译它。结果相同:代码块可以工作,GCC不行。)-是的exe文件。在这两个版本上编译都“成功”-但是gcc版本没有按它应该的那样执行。
我完全无用的猜测是,getchar()函数的行为很奇怪,这取决于使用它的编译器。
感谢您的评分
我将添加代码的问题,如果你需要它,或者如果你想判断我。(我不介意任何批评。)

#include <stdio.h>

#define MAXLENGTH 25  /* Maximum length of input. */

int main(){

    /* Histogram of length of words in its input. Vertical or Horizontal. (Vertical is hardest, so let's do that!).
     * Identify words and count characters within each, store that length in a array that represents the length for each word.
     * Draw based on the number of words, their lengths, and their maximum height (optional).
     */

    /* Identify when inside of a word, start counting. When leaving word, record c-count into array, reset count to 0 after.
     * Until entering new word.
     */
    
    //Declaration of the Counter's variables here
    //The Histogram's variables are farther down below!
    int nw, c, cCount, wordLen[MAXLENGTH];
    int i = nw = cCount = 0;
    
    //Initialize wordLen into 0 to avoid garbage results from any potential unused members of the array.
    for (i = 0; i < 25; i++) {
    wordLen[i] = 0;
    }

    //Counts characters in each word and stores inside of chronological array.
    while ((c = getchar())!= EOF){
    if (c == ' ' || c == '\t' || c == '\n'){ 
        wordLen[nw] = cCount;
        ++nw;
        cCount = 0;
        
    }
    else {
        ++cCount; 
    }
        
    
    
    }
    //Prints first 4 words lengths for comparison purposes.
    printf("%d %d %d %d\n\n", wordLen[0], wordLen[1], wordLen[2], wordLen[3]);

    //Declaration of variables for Histogram.
    int currentLvl, largestN, ii, iii, IV, V;

    //Finds and stores the  largest number from the array into var:largestN.
    for (ii = 0; ii < MAXLENGTH; ii++) {
    if (wordLen[ii] >= largestN)
        largestN = wordLen[ii];
    }

    //Declare and initialize array for comparison purposes for later use in the Histogram generation process.
    int level[largestN];
    level[0] = 0;
    for (iii = 1; iii < largestN + 1; iii++){
    level[iii] = iii;
    }
    // printf("\n largest N is %d\n", largestN); //for testing
    // printf("wordLen 0 is: %d\n", wordLen[0]); //for testing
    

    /* Histogram generation:
     * The logic is simple: From Top-left, move rightwards (in chronological order) and check which of the words' lengths
     * reach the current level or height (starting from Top). Print a line at that spot if they ever do, print an empty space if
     * they do not.
     * Then move one step down, and repeat the process but comparing 1 level lower. Until bottom is reached.
     */
    //ss
    for (V = largestN; V > 0; V--){
    currentLvl = level[V];
    
    for (IV = 0; IV < MAXLENGTH; IV++){
        if (wordLen[IV] >= currentLvl)
        printf("|");
        
        else {
        printf(" ");
    }
        printf(" ");
    }
    printf("\n");
    
    
    }
    

    
    return 0;
}

编辑1:
当我编译+运行它通过代码块的例子:

这是一个句子:

asdasdasd
4 2 1 8

            |
          | |
          | |
          | |
          | |
    |     | |
    |     | |
    | |   | |
    | | | | |


这是使用emacs(使用gcc编译器后)- shell:

B:\c-programs\Examples〉main.exe main.exe
这是一个句子asdasdasd
B:\c-programs\Examples〉Process shell完成

哦,我忘了说一句:我必须做ctrl-d或ctrl-c来“完成”程序后,键入句子,以便它开始打印图形。也许这跟它有关系?
编辑2:这里看起来很奇怪,但在cmd屏幕上的注解字段/中看起来很好(代码块)。
编辑3:* 修复编辑部分中的一些缺失信息。*
编辑4:解决感谢大家的投入,我会阅读和学习,我可以从你们每一个人!问题是,我似乎没有初始化largestN(如你所说),但我也学到了很多其他的东西,我会尝试吸收!所以谢谢你!祝你好运,我也有你的项目!!

vohkndzv

vohkndzv1#

您的代码中可能有一些错误。在这里,您将wordLen[ii]与未初始化且可能具有任何值的largestN进行比较。

int currentLvl, largestN, ii, iii, IV, V;

//Finds and stores the  largest number from the array into var:largestN.
for (ii = 0; ii < MAXLENGTH; ii++) {
    if (wordLen[ii] >= largestN)
        largestN = wordLen[ii];
}

如果largestN持有像641346这样的值,你试图用它创建一个数组:

int level[largestN];

顺便说一句,你可以有一个变量的多个循环。

//int i, ii, iii, IV, V;    // dont do this
int i;    // do this
for (i = 0; i < N; i++){
    // do something
}
for (i = 0; i < N; i++){    // use the same variable again
    // do something
}
ma8fv8wu

ma8fv8wu2#

请注意,第45行定义的largestN没有初始化,并且可以包含非常大的值。像Code::blocks这样的IDE很可能会将所有变量归零,而gcc生成的更多优化编译则不会。因此,你可能会得到非常高的“酒吧”,基本上混乱了你的屏幕,使它很难看到什么是键入。
只需按以下方式更改第45行,这可能会给予您一些更合理的结果:

//Declaration of variables for Histogram.
int currentLvl, largestN = 0, ii, iii, IV, V;

另外,如果你已经在使用它,就不需要i,ii,iii等等,因为你在每次循环中都重置这个计数器,你可以在任何地方使用相同的变量'i'。此外,它不是标准的C语言,但所有现代编译器都允许你在for循环中定义一个变量,这更安全(注意for循环中的“int i”):

for (int i = 0; i < MAXLENGTH; i++)
{
    // do something with i here. 
}
l7wslrjt

l7wslrjt3#

正如其他答案所说,您正在与未初始化的largestN进行比较,并调用undefined behavior。这里有另一个潜在的解决方案

// pretend that wordLen[0] is the largest value. Now, largestN
// is initialized
largestN = wordLen[0];
// loop, now starting at the 2nd index since we know
// largestN == wordLen[0]
for (i=1; i<MAXLENGTH; i++)
{
   // use > here instead of >=. If equal, largestN already contains that
   // value, no sense in overwriting it with the same value
   if (wordLen[i] > largestN)
        largestN = wordLen[i];
    }
}

在这里,您只处理正值,因此将largestN初始化为0就可以了,但一般来说,初始化为数组中已经存在的值是更健壮的方法。如果你的数组都是负数怎么办?那么0会大于所有这些,你不会得到一个准确的结果。

sqxo8psd

sqxo8psd4#

有几个问题..
1.有几个地方发生UB。
1.存储到wordLen时,nw可以超过MAXLENGTH
1.在您的示例输入文件中,有超过25个(即即MAXLENGTH)字。
1.我们需要检查一下是否有多余的。

  1. largestNuninitialized,所以它可以有一个随机的[bad]值。
    1.后面的一些数组循环到MAXLENGTH。它们应该只循环到nw(有效元素的 * 实际 * 数量)。
    1.某些环路硬连接到25,而不是MAXLENGTH
  2. level数组定义得太小。
    1.从原点1开始的索引超出数组的末尾,并使第一个元素保持为单位化。
    这里是[大部分]更正的代码。它是一个[大多数]错误和修复的注解。它可能在打印中仍然有一些错误,但它修复了大多数严重的错误:
#include <stdio.h>
#include <stdlib.h>

#ifndef MAXLENGTH
#define MAXLENGTH 25                    /* Maximum length of input. */
#endif

int
main()
{

    /* Histogram of length of words in its input. Vertical or Horizontal. (Vertical is hardest, so let's do that!). Identify words and count characters within each, store that length in a array that represents the length for each word. Draw based on the number of words, their lengths, and their maximum height (optional). */

    /* Identify when inside of a word, start counting. When leaving word, record c-count into array, reset count to 0 after. Until entering new word. */

    // Declaration of the Counter's variables here
    // The Histogram's variables are farther down below!
    int nw,
     c,
     cCount,
     wordLen[MAXLENGTH];
    int i = nw = cCount = 0;

    // Initialize wordLen into 0 to avoid garbage results from any potential unused members of the array.
#if 0
    for (i = 0; i < 25; i++) {
#else
    for (i = 0; i < MAXLENGTH; i++) {
#endif
        wordLen[i] = 0;
    }

    // Counts characters in each word and stores inside of chronological array.
    while ((c = getchar()) != EOF) {
        if (c == ' ' || c == '\t' || c == '\n') {
// NOTE/FIX: this can overflow wordLen causing UB (it scribbles on unrelated
// memory)
#if 1
            if (nw >= MAXLENGTH) {
                printf("overflow\n");
                exit(99);
            }
#endif
            wordLen[nw] = cCount;
            ++nw;
            cCount = 0;

        }
        else {
            ++cCount;
        }

    }
    // Prints first 4 words lengths for comparison purposes.
    printf("%d %d %d %d\n\n", wordLen[0], wordLen[1], wordLen[2], wordLen[3]);

    // Declaration of variables for Histogram.
    int currentLvl,
     largestN,
     ii,
     iii,
     IV,
     V;

    // Finds and stores the largest number from the array into var:largestN.
// NOTE/BUG: some elements may not have _actual_ values and largestN is
// _unitialized_
#if 0
    for (ii = 0; ii < MAXLENGTH; ii++) {
#else
    largestN = 0;
    for (ii = 0; ii < nw; ii++) {
#endif
        if (wordLen[ii] >= largestN)
            largestN = wordLen[ii];
    }

    // Declare and initialize array for comparison purposes for later use in the Histogram generation process.
// NOTE/BUG: this defines an array that is too short
#if 0
    int level[largestN];
#else
    int level[largestN + 1];
#endif

    level[0] = 0;
// NOTE/BUG: this goes one beyond the end of the valid data and it starts with
// an origin 1 array index
#if 0
    for (iii = 1; iii < largestN + 1; iii++) {
        level[iii] = iii;
    }
#else
    for (iii = 0; iii < largestN; iii++) {
        level[iii] = iii;
    }
#endif
    // printf("\n largest N is %d\n", largestN); //for testing
    // printf("wordLen 0 is: %d\n", wordLen[0]); //for testing

    /* Histogram generation: The logic is simple: From Top-left, move rightwards (in chronological order) and check which of the words' lengths reach the current level or height (starting from Top). Print a line at that spot if they ever do, print an empty space if they do not. Then move one step down, and repeat the process but comparing 1 level lower. Until bottom is reached. */
    // ss
// NOTE/BUG: this starts at one past the valid data
#if 0
    for (V = largestN; V > 0; V--) {
#else
    for (V = largestN - 1; V >= 0; V--) {
#endif
        currentLvl = level[V];

// NOTE/BUG: not sure which of these is correct
#if 1
        for (IV = 0; IV < MAXLENGTH; IV++) {
#else
        for (IV = 0; IV < nw; IV++) {
#endif
            if (wordLen[IV] >= currentLvl)
                printf("|");
            else {
                printf(" ");
            }
            printf(" ");
        }
        printf("\n");

    }

    return 0;
}

在上面的代码中,我使用了cpp条件来表示old与新代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

注意:这可以通过unifdef -k运行文件来清理。

相关问题