内部变量2,而循环不会重置

时间:2017-11-22 05:06:08

标签: c

除非我的电脑疯了或者我错过了什么。当我运行代码时,变量计数在每个内部while循环后不会重置为零。 防爆。如果我输入:
XXX
YYYY
计数输出为1-9。但它应该是1-4和1-5。

int main(){

    char string[500][500];
    int letterWords[15]={0};

    printf("Enter several lines of text.\n");
    scanf("%[^\t]", string);

    int a=0, b=0;

    int count=0, i;

    while(string[a][0]!='\0'){
        while(string[a][b]!='\0'){
            count++;
            b++;
            printf("%d\n", count);
        }
        printf("\n");
        count-=2;
        letterWords[count]++;
        a++;
        b=0;
        count=0;  //the count doesn't reset to 0 for some reason
    }

    for(i=0;i<15;i++){
        if(letterWords[i]==0){
            continue;
        }
        printf("%d %d\n", i+1, letterWords[i]);
    }

}

4 个答案:

答案 0 :(得分:0)

与您的想法不同,scanf仅扫描string[0]中的行。 其他人没有初始化。试图阅读它们是未定义的行为。

现在再次在string中传递scanf有一件事。价值方面,它包含相同的 价值与string[0]的价值相同。所以它基本上读取string[0]中的行。

假设scanf现在没有失败,你进入了while循环。 第一次检查是多余的。当a不是0时,它将调用未定义的行为。

通过增加count来计算长度。令人惊讶的是,你试图在letterWords中增加价值。 当值count不是<=14时,您再次访问数组索引超出范围。这也是未定义的行为。

现在经过这么多未定义的行为之后,count=0的通常任务被压制了。 只是程序抱怨,然后行甚至不执行。(也许)。

为了获得多行,请使用fgets并阅读在不同\n - s中分隔的每一行(string[i])。 然后根据读取的行数运行循环。一切都会好起来的。 while(string[a][0]!='\0')并不是一种好的方式,而是根据行读数进行检查。(在您的情况下)

同样printf("%s",string[i])将打印每一行。

使用scanf()的更好方法是检查scanf()的返回值。

答案 1 :(得分:0)

我冒昧地重塑代码(否则会改变很多东西)

int main() {

    char string[500][500];
    int letterWords[15]={0}; // max line length is 14
    int a,i,count;

    printf("Enter several lines of text (end with ^D).\n");
    for(a=0 ; a < 500 && fgets(string[a], 500, stdin) ;  a++) /* nothing */;

    for(i=0 ; i<a ; i++) {
        for(count=0 ; string[i][count] && string[i][count] != '\n' ; count++)  /* nothing */ ;
        printf("Line %d: %d\n", i, count);
        letterWords[count]++;
    }

    for(i=0 ; i<15 ; i++) {
        if(letterWords[i]) {
            printf("%d %d\n", i, letterWords[i]);
        }
    }

    return 0;
}

说明:

for(a=0 ; a < 500 && fgets(string[a], 500, stdin) ;  a++) /* nothing */;

使用fgets读取给定最大长度的行。行计数器为a 要完成输入,用户在空行处按 Control-D EOF)。
fgets满足(或发生错误)时,NULL会返回EOF

for(i=0 ; i<a ; i++) {

istrings中的索引,从0a-1

    for(count=0 ; string[i][count] && string[i][count] != '\n' ; count++)  /* nothing */ ;

不需要其他变量。 count计算该行中的字符数,并在符合\n\0时停止。

    printf("Line %d: %d\n", i, count);
    letterWords[count]++; // Increment the line-counter
}

请注意,任何行都不应超过14个字符。最后,

for(i=0 ; i<15 ; i++) {
    if(letterWords[i]) {
        printf("%d %d\n", i, letterWords[i]);
    }
}

打印结果Length Number_of_lines_of_that_length

答案 2 :(得分:0)

读取输入行时,请使用面向行的输入函数,例如fgets或POSIX getlinescanf充满了陷阱,等待新的C程序员陷入其中。

虽然您的代码(尤其是linewords)有点难以理解,但您尝试捕获其中的长度以打印带有字符的所有行。

你必须要理解的一件事是将一个scanf放在首位 - 只读一个输入。这使得你的嵌套循环在徒劳无功中付出了巨大的努力。相反,您需要在外循环中移动读取,这样您就可以在每个循环中读取一行输入(技术术语)。

不是使用嵌套循环,只需使用单个循环循环不断获取用户输入,直到用户生成EOF Ctrl + d Ctrl + z 在windoze上)。在那里,您只需验证读取(字符串实际上适合您的分配存储)并修剪尾随的\n'读取并通过面向行的输入函数包含在缓冲区中。

虽然您可以自由地将每个字符串的长度存储在一个单独的数组中,但对于本练习,只需调用strlen即可。

完全放弃,您可以执行以下操作:

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

#define MAX 500     /* if you need constants, define them */

int main () {

    int n = 0;                          /* strings index */
    char string[MAX][MAX] = { "" };     /* 2d array of char */

    printf ("\nenter several lines of text\n"
            "[ctrl+d (ctrl+z on windows) when done]\n\n");

    for (; n < MAX;) {      /* take input until n == MAX or user EOF */
        printf ("line[%2d]: ", n);              /* prompt for input */
        if (fgets (string[n], MAX, stdin)) {    /* read line */
            size_t len = strlen (string[n]);    /* get length */
            if (len && string[n][len - 1] == '\n')  /* check last char '\n' */
                string[n][--len] = 0;   /* overwrite with nul-terminating char */
            else {  /* line too long handle error */
                fprintf (stderr, "error: line too long '%d'.\n", n);
                return 1;
            }
            n++;    /* increment line index */
        }
        else {  /* handle EOF */
            printf ("\nall done!\n\n");
            break;
        }
    }

    for (int i = 0; i < n; i++)         /* output each line read */
        printf ("string[%2d] (%3zu chars) : '%s'\n", 
                i, strlen (string[i]), string[i]);

    return 0;
}

注意:如果您的目标是跳过零长度字符串,那么只需在最终if (strlen(string[i]))之前添加printf检查即可。(您可以将它保存在最终循环中的变量中以防止调用它两次))

示例使用/输出

$ ./bin/rdstrings2d

enter several lines of text
[ctrl+d (ctrl+z on windows) when done]

line[ 0]: my dog
line[ 1]: has fleas
line[ 2]: my cat is lucky, and
line[ 3]: has none
line[ 4]:
all done!

string[ 0] (  6 chars) : 'my dog'
string[ 1] (  9 chars) : 'has fleas'
string[ 2] ( 20 chars) : 'my cat is lucky, and'
string[ 3] (  8 chars) : 'has none'

答案 3 :(得分:0)

//尝试使用此代码,这似乎可以正常工作   的#include

int main(){

char string[500];
int letterWords[15]={0};

printf("Enter several lines of text.\n");
scanf("%[^\t]", string);

int a=0, b=0;
//printf("%s",string);
int count=0, i;

while(string[a]!='\0'){
    while(string[a]!='\n'){
        count++;
        a++;
        printf("%d\n", count);
    }
    printf("\n");
    count-=1;
    letterWords[count]++;
    a++;
    b=0;
    count=0;  //the count doesn't reset to 0 for some reason
}

for(i=0;i<15;i++){
    if(letterWords[i]==0){
        continue;
    }
    printf("%d %d\n", i+1, letterWords[i]);
}

}