C中的基本字符串数组操作

时间:2017-02-25 13:23:36

标签: c

我有这个:

int main()
{
    char m[] = "12aa34"; 
    for (int i = 0; m[i] != '\0'; i++)
    {
        //printf("%c\n", m[i]);
        m[i] = m[i] + (isdigit(m[i]) ? -2 : 1);
        puts(m);
        printf("\n");
    }
    //printf("\n");
    //puts(m);
    return 0;
}

puts(m) output: /2aa34
                /0aa34 
                /0ba34 
                /0bb34 
                /0bb14
                /0bb12

关于puts(m)输出的第一个问题: 经过一番挖掘后我想到它与ASCII有关。是否可以说代表级别的操作?我检查了它并以某种方式与/的结果相关联(即1的十进制值为49 => 49 - 2 = 47 /),然后2为{{{ 1}}是50 => 50 - 2 = 48,然后0a 97 => 97 + 1 = 98,依此类推。

关于第一个评论b的第二个问题:

printf是指针的焦点吗?现在不应该更改m[]修改字符串以给我新值而不是旧值?

3 个答案:

答案 0 :(得分:1)

字符是整数值,从中添加/减去1会影响整数值。如果那是你在"代表级别"的操作的意思,那么 - 是 - 这就是发生的事情。

对于ASCII字符集,'0' - 1(即从字符1中减去数值'0')是字符'/'。请注意,虽然很多实现(编译器,库)支持ASCII,但C标准实际上并不需要它。但是,还没有任何标准化字符集,字符'0'的数值为零。

关于你的第二个问题......首先,你的声明" m[]是一个指针的焦点"是不正确的(事实上,这是没有意义的)。 mchar的数组。其次,在实际修改该字符之前,注释掉的printf在循环的每次迭代中打印出m[i](数组i中的m个字符)。使用语句(对于循环的每次迭代)

    printf("%c\n", m[i]);
    m[i] = m[i] + (isdigit(m[i]) ? -2 : 1);
    puts(m);
    printf("\n");

有一系列固定的事件。第一个printf()语句输出m[i]的值,然后修改m[i](即m中只有一个字符),然后puts(m)输出整个数组{ {1}},然后输出换行符。如果您希望在第一个m之前修改m[i],那么您需要再次思考。源文件中的语句顺序很重要。

答案 1 :(得分:0)

你是对的,C中字符的表示是一个数字。

就是在C,一个' char'通常是一个签名的字母'或者是一个字节数,范围是-128 .. 127.您可以为其指定字符,例如m [1] =' a',但这仍然是整数赋值。唯一的区别是它只有-128 .. 127

的范围

ASCII字符集为0 .. 127,但char也可以表示负数。

如果您使用的是无符号字符,则该范围将被视为代表0..255,而127以上的字符则称为控制字符。

本声明

char m[] = "12aa34";

表示在堆栈上创建一个7字节数组,并使用对应于' 1',' 2'' a&#39的ascii字符的字节值对其进行初始化;,'一个'&#39 3'' 4'' \ 0' (NUL)

当你使用它时,唯一可以被认为是指针的是变量m本身。但是这里m存储将分配在堆栈上,而不是堆。 当您编译程序时,编译器会存储字符串" 12aa34 \ 0"在编译的代码中。当你的函数被调用时,编译的代码将通过递增堆栈指针在堆栈上分配至少7个字节,然后通过从" 12aa34"复制它们来初始化这7个字节。存储在代码中的字符串。因此,完全允许您的代码更改堆栈中m变量中的值。

如果你这样做了:

char *m = "12aa34";

然后代替m在堆栈上有7个字节的存储空间,这是字节值' 1' (49),' 2' (50)等。相反,m指的是在堆栈上分配的8个字节的位置,它是指向直接指向" 12aa34"的指针(64位存储器地址)。内存中的字符串,由编译器存储在可执行文件中,并在执行程序时加载到内存中。在这种情况下,不应该允许修改m [i],因为加载可执行代码的内存部分通常是只读的。 这在C ++中更清晰,其中' type'一个字符串文字"例子"不只是" char *",但" char const *",表示您无法修改char值。

在您的示例代码中,您的注释printf确实应该在更改之前打印每个未修改的字符。

为了帮助解决正在发生的事情,请尝试以下方法:

char *orig = ”12aa34";
char *another = "12aa34";
char m[] = "12aa34";

printf(" %p  %s\n",  orig,orig);
printf("%p %s\n", another, another);

printf("%p %s\n", m, m);

m[0] = 'x';
printf("%p %s\n", m, m);

你会发现,' orig'的指针和字符串值。和另一个'将是完全相同的。

而为' m'打印指针值。虽然字符串值最初会相同,但在修改之后会有所不同。

答案 2 :(得分:-2)

我并没有真正解读你的问题,但我正在努力提供帮助。

在循环中,首先修改字符串的一个字符,然后打印整个字符串stdout。因为正如你所说,那些输出字符是由ASCII字符集引起的。

char m [] = "foo";  

与写作相同

char * m = "foo";  

唯一的区别是,您可以在编写

时使用第一种方法初始化空字符串
char m [20];  
m [19] = '\0';  

您将创建一个长度为20个字符的空字符串。您必须将最后一个字符设置为\ 0,以便终止字符串

使用char *方式时,您必须创建稍微不同的循环,例如:

char * ptr;
for (ptr = m; * ptr != '\0'; ptr++){
    //Do something, * ptr is used to get and modify the current value
}

访问没有索引的char [],比如(只是名称)引用数组或字符串中第一个元素的指针。

我希望这是你想要的,如果没有,请告诉我。