我在 C 中将 argv 转换为 upper 时遇到问题

问题描述

我正在尝试将固定大小的 argv 转换为上限和下限,但它要么给我分段错误,要么只是在 var 上存储乱码。我试过这个:

#include <stdlib.h>
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(int argc,string argv[])
{
    string lower = "abcdefghijklmnopqrstuvwxyz";
    string upper = "abcdefghijklmnopqrstuvwxyz";

    for (int i = 0,n = 26; i < n; i++)
    {
        lower[i] = tolower(argv[1][i]);
        upper[i] = toupper(argv[1][i]);
    }
}

或:

string lower = "";
string upper = "";

//check if repeated chars or numbers
for (int i = 0,n = 26; i < n; i++)
{
    printf("%c\n",(char) argv[1][i]);
    printf("%c\n",tolower(argv[1][i]));
    printf("%c\n",toupper(argv[1][i]));
    lower += tolower(argv[1][i]);
    upper += toupper(argv[1][i]);
}

最奇怪的部分是 printf 给出了正确的值,但它们没有存储在 lowerupper 中。我在这里干什么?

解决方法

不能在 C 中使用 += 附加到字符串。

<cs50.h>string 定义为 char *。然后 string lower = "";lower 定义为 char * 并将其设置为指向 "" 的第一个字符。 "" 表示空字符串,即第一个也是唯一一个字符为空(零值)字符的字符串,表示字符串的结束。

当应用一个指针时,+= n 会尝试将指针向前移动 n 元素所指向的类型。例如,如果指针 p 指向数组的元素 3,则 p += 4 将使其指向元素 7。

由于 lower 指向只有一个元素的数组元素,因此空字符 lower += tolower(argv[1][i]) 试图使其指向数组外。 C 标准未定义该行为。 (除了它可能在 C 实现中,其中 tolower 应用于该字符产生值为 1 的字符。这将修改 lower 以指向数组中的最后一个元素,这是一个特殊的允许进行指针运算的位置。)

使用string lower = "abcdefghijklmnopqrstuvwxyz";,您有更多空间进行数组运算;对 lower 进行一些添加将起作用。然而,tolower(argv[1][i]) 可能太大而无法保留在数组中。

此外,即使指针算法有效,lower += … 也只会改变指针。它不会改变它指向的字符。

为了使您的代码工作,您需要分配足够的内存来保存结果字符串,包括空字符,并且您必须设置 lower 指向该内存,对于 upper 也是如此。您需要的字符数为 strlen(argv[1][i]) + 1。如果您已经学会了如何使用 malloc,则可以使用它。如果你有一个固定的赋值来保证 argv[1] 正好是 26 个字符,你可以定义 lower 并通过用 char lower[27]; 声明它来为其提供内存,对于 {{1} }.

然后,您必须将字符复制到该内存中,这可以使用 upper 来完成。当您完成将字符复制到数组中时,您应该在它的末尾写一个空字符,以形成一个完整的 C 字符串。 (如果您不打算将数组打印为字符串或以其他方式将其用作字符串,则可以省略此项。)

,

如果您调用 man toupper,您将了解到该函数不接受字符串而是一个字符。因此,实现您所追求的目标的一种方法是遍历命令行参数中的每个字符,对其调用 toupper,然后将结果存储回来。

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

void main(int argc,char *argv[])
{
  printf("before: %s\n",argv[1]);

  for (unsigned int i = 0,n = strlen(argv[1]); i < n; i++) {
    argv[1][i] = (char) toupper(argv[1][i]);
  }

  printf("after:  %s\n",argv[1]);  
}