【问题标题】:Program stops at for loop程序在 for 循环处停止
【发布时间】:2021-02-05 08:12:45
【问题描述】:

我正在尝试使用 C 语言并尝试通过创建一个程序来适应内存和字符串内容,该程序采用单词形式的标准输入,处理单词,将它们吐回并尝试更改单词的大写和小写.

但是,该程序似乎没有执行任何超出strcpy(key, word) 的内容。它在 for 循环处停止,甚至不执行循环后的打印语句。

到目前为止,我已经尝试了 while 循环和 for 循环来改变大小写。我通过在 for 循环上方的行上打印它来确保正确复制了密钥。我什至注释掉了 for 循环,看到 tolower() 调用了两行代码并打印出更新后的密钥。只是 for 循环出了点问题,我不知道是什么。

我该如何解决?

int main(void)
{
    char ch; 
    char *word;
    word = (char *)malloc(60 * sizeof(char)); 
    int ind = 0; 
    int cap = 60; 
    while (ch = getchar()) { 
        if (isalnum(ch)) {
            if (ind >= cap) {
                word = (char *)realloc(word, (ind + 1) * sizeof(char));
                cap++; 
            }
            word[ind] = ch; 
            ind++; 
        } else {
            word[ind] = '\0'; 
            int size = strlen(word); 
            char key[size]; 
            strcpy(key, word); 
            for (int i = 0; i < size; i++) {
                if (i = 0) {
                    key[i] = toupper(key[i]);
                } else {
                    key[i] = tolower(key[i]);
                }
            }
            fprintf(stdout, "%s\n", key);
            key[0] = tolower(key[0]);
            fprintf(stdout, "%s\n", key);
            ind = 0; 
            memset(word, 0, sizeof word);
            putchar(ch); 
            putchar('\n');
        }
    }
}

【问题讨论】:

  • char key[size]; -> char key[size + 1];,字符串 NUL 终止符需要多一个字符。不过可能还有更多问题。
  • if (i = 0) -> if (i == 0)memset(word, 0, sizeof word) 也很可疑。为什么不只是word[0] = 0*word = 0?我建议你学习如何使用你的调试器。投入的时间很快就会得到回报。
  • 哦,糟糕,忘记了 ==。我使用 memset 纯粹是因为我搜索了如何清空 char 数组,并且该论坛上的一个主题推荐了这种方式。这个想法是让用户能够继续写单词和行。我也会试试你的建议
  • 您是否尝试过在调试器中运行您的程序并检查它的作用?
  • 顺便说一句:memset(word, 0, sizeof word) 或我建议的替换不是必需的,因为您在下一次循环运行时会覆盖 word 缓冲区。

标签: c string char


【解决方案1】:

您的代码存在多个问题:

  • ch 必须使用 int 类型定义,以便正确检测 EOFfgetc() 的返回值可以是字节值(unsigned char 类型的所有值)或特殊的负值EOF。转换为 char 类型会丢失信息。

  • while (ch = getchar()) 无法检测文件结尾,它只测试从文件中读取的字节是否非零。你应该写while ((ch = getchar()) != EOF)

  • 您没有为空终止符分配空间。更准确地说,在测试目标缓冲区的重新分配时,您应该留出 2 个额外的字节。

  • 在重新分配数组时,应将cap 增加 1 以上,以避免为需要存储的每个额外字节重新分配。

  • int size = strlen(word); 可以替换为int size = ind;

  • char key[size]; 不正确:您应该通过分配一个额外的字节来允许空终止符。

  • isalnum()toupper()tolower() 和来自&lt;ctype.h&gt; 的其他函数仅针对getchar() 返回的所有值定义。与 EOF 不同的负参数值会导致未定义的行为,char 参数必须强制转换为 (unsigned char) 以避免在默认签名 char 的架构上出现未定义的行为。

  • memset(word, 0, sizeof word); 没用。

  • 你没有测试分配失败。

  • 你永远不会释放word

这是修改后的版本:

#include <ctype.h>
#include <stdio.h>

int main(void) {
    int ch; 
    int ind = 0; 
    int cap = 60;
    char *word = malloc(60); 

    if (word == NULL) {
        fprintf(stderr, "allocation failure\n");
        return 1;
    }
    while ((ch = getchar()) != EOF) { 
        if (isalnum(ch)) {
            if (ind >= cap) {
                cap += cap / 2;
                word = realloc(word, cap);
                if (word == NULL) {
                    fprintf(stderr, "allocation failure\n");
                    return 1;
                }
            }
            word[ind] = ch; 
            ind++; 
        } else {
            word[ind] = '\0'; 
            char key[ind]; 
            strcpy(key, word);
            if (ind > 0) {
                key[0] = toupper((unsigned char)key[0]);
                for (int i = 1; i < ind; i++) {
                    key[i] = tolower((unsigned char)key[i]);
                }
            }
            printf("%s\n", key);
            key[0] = tolower((unsigned char)key[0]);
            printf("%s\n", key);
            ind = 0;
            putchar(ch); 
            putchar('\n');
        }
    }
    free(word);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-18
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    • 2022-10-23
    • 1970-01-01
    相关资源
    最近更新 更多