【问题标题】:What's an alternate way of getting the char's int value to increment?让char的int值增加的另一种方法是什么?
【发布时间】:2021-01-14 06:50:38
【问题描述】:

在制作字符串函数的过程中,我尝试构建一个类似于strlwr() 的函数,我将其命名为lowercase()

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

char *lowercase(char *text);

int main() {
    char *hello = "Hello, world!";
    printf("%s\n", lowercase(hello));
}

char *lowercase(char *text) {
    for (int i = 0; ; i++) {
        if (isalpha(text[i])) {
            (int) text[i] += ('a' - 'A');
            continue;
        } else if (text[i] == '\0') {
            break;
        }
    }
    return text;
}

我了解到大写字母和小写字母的间隔是 32,这就是我使用的。但后来我得到了这个错误:

lowercase.c:14:13: error: assignment to cast is illegal, lvalue casts are not supported
            (int) text[i] += 32;
            ^~~~~~~~~~~~~ ~~

如果 char 被认为是来自 A-Z 的字母,我想增加它的值。事实证明我不能,因为 char 在数组中,而且我这样做的方式似乎对计算机没有意义。

问:我可以使用哪些替代方法来完成此功能?您能否进一步解释为什么会出现此错误?

【问题讨论】:

  • 你想把它转换成int,增加它,然后把它塞回char吗?如果是这样:text[i] = (int) text[i] + x。请记住,这只是乞求看似奇怪的溢出错误,因为这两种表示方式截然不同。
  • 为什么不只是 text[i] |= 32 而忘记 int 转换?
  • 旁注: 如您所见,hello 指向 指向一个字符串常量 [可能已加载到 R/O 内存中]。要让它工作,请执行以下操作:char hello[] = "Hello, world!"; 现在,array 字符在堆栈上(即可修改)。
  • 您可能会在此处遇到 未定义的行为,因为您正在尝试修改(通过指针)字符串文字的数据(其中编译器完全有权存储在只读代码段中)。
  • 不要硬编码32。如果你打算这样做,为了未来读者的理智,请写'a' - 'A'

标签: c char c-strings string-literals function-definition


【解决方案1】:

演员表是不必要的。 chars 是整数类型,可以在没有大张旗鼓的情况下递增:

text[i] += 32;

正如一些评论者所指出的,您还应该将您的字符串更改为可修改的字符串。 char *hello = "..." 声明一个只读字符串文字。使用数组语法使其可写。

char hello[] = "Hello, world!";

您还需要将isalpha() 切换为isupper(),以便您只修改大写字母。

顺便说一句,如果您将 else if 检查移到 for 循环的测试条件中,您可以同时摆脱 breakcontinue

for (int i = 0; text[i] != '\0'; i++) {
    if (isupper((unsigned char) text[i])) {
        text[i] += 32;
    }
}

【讨论】:

  • 更短:for ( unsigned char *p = text; *p; p++ ) *p = toupper( *p );
  • @AndrewHenle BPML 发布我已修复的评论时出现了一个错误。
【解决方案2】:

虽然在 C 中字符串字面量具有非常量字符数组的类型,但您不能更改字符串字面量。

char *hello = "Hello, world!";

来自 C 标准(6.4.5 字符串文字)

7 不确定这些数组是否不同,前提是它们的 元素具有适当的值。 如果程序试图 修改这样的数组,行为未定义。

所以你应该像一个字符数组一样声明标识符hello

char hello[] = "Hello, world!";

在函数中你不应该使用像32 这样的幻数。例如,如果编译器使用 EBCDIC 编码,您的函数将产生错误的结果。

并且在循环中,您必须使用 size_t 类型而不是 int 类型,因为 int 类型的对象可能无法存储 size_t 类型的所有值,这是sizeof 运算符或函数strlen

此声明

(int) text[i] += 32;

没有意义,因为在表达式的左侧由于强制转换而存在右值。

该功能可以通过以下方式实现

char * lowercase( char *text ) 
{
    for ( char *p = text; *p; ++p ) 
    {
        if ( isalpha( ( unsigned char )*p ) ) 
        {
            *p = tolower( ( unsigned char )*p );
        } 
    }

    return text;
}

【讨论】:

猜你喜欢
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2015-05-15
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
相关资源
最近更新 更多