c - 打印出字符串的整数表示时 Scanf 和 strtol 的属性

标签 c string scanf strtol

我知道字符串只是具有相邻内存地址的字符数组。所以当你有一个字符数组时:

char s[5];
s[0] = '1';
s[1] = '2';
s[2] = '3';
s[3] = '4';
s[4] = '5';

并将 s[1] 处的字符数组更改为“5”,然后打印这样的数组应返回“15345”。现在我的问题是关于 scanf 和 strtol 函数。当我使用 scanf 两次使用不同大小的字符串将值插入数组 s 时,为什么 strtol 函数不转换整个数组?

这是我的代码示例:

#include <stdio.h>
#include <stdlib.h>

int main(){
    char bytes[5];
    printf("enter size 1: ");
    scanf("%s", bytes);

    printf("the size is: %ld\n", strtol(bytes, NULL, 10));

    printf("enter size 2: ");
    scanf("%s", bytes);

    printf("the size is: %ld\n", strtol(bytes, NULL, 10));

    return 0;

}

想象一下这些用户输入:

10000

然后程序会打印出“大小为 10000”

然后用户输入:

100

然后程序打印“大小为 100”

为什么不再打印“大小为 1000”?我只将 100 存储为字节,第一个输入中字节的剩余数组元素不应该保持不变, strtol 应该转换数组的其余部分吗?

在我看来,当程序将第一个输入 10000 存储到数组字节中时,那一刻是这样的

字节 = {1,0,0,0,0}

那么当用户输入 100 时,数组看起来是一样的,因为它只改变了前 3 个元素的值,而数组的其余部分应该保持不变:

字节 = {1,0,0,0,0}

使用 strtol 会将整个数组转换为 10000 对吗?

当将值存储到相同的内存地址时,scanf 是否本质上“清空”了数组的其余部分?

最佳答案

I know that strings are just an array of chars with adjacent memory addresses.

不完全是。在 C 中,字符串也是以零结尾的。也就是说,字符串以第一个具有零值的字符结尾。比如

char a[6] = { 'h', 'i',  0 , 'h', 'o', 0 }; // print(a) prints "hi"
char b[6] = { 'h', 'e', 'l', 'l', 'o', 0 }; // print(b) prints "hello"
char c[5] = { 'h', 'e', 'l', 'l', 'o' };    // print(c) will attempt to print "hello" followed by whatever characters happen to follow c[4] in memory, until it hits a zero value. But that may be reading outside the memory bounds of your application, or indeed your system, so anything can happen.

So when you have a character array: <snip>

如果您将 s 扩展为 char s[6] 并设置 s[5] = 0,您对更改 的假设s[1] 打印出来就是正确的

Now my question is about scanf and strtol functions. When I insert values into the array s using scanf twice using different sized strings, Why is it that the strtol function does not convert the ENTIRE array?

首先是一个建议,在每个 scanf("%s", bytes); 行之后,插入以下内容:

printf("bytes = { %02x, %02x, %02x, %02x, %02x } (%02x)",
        bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5] );

使用该更改运行您的测试代码,并检查该行打印的内容。 如果您看到这一点,您将有望看到有关 scanfstrtol 问题的答案。

我将在下面用一些注释来注释您的代码,指出 bytes 的内容,使用 ? 作为未知:

#include <stdio.h>
#include <stdlib.h>

int main(){
    char bytes[5];
    printf("enter size 1: ");
    scanf("%s", bytes);  // 10000<return>

    // bytes {  ? ,  ? ,  ? ,  ? ,  ?  } bytes[5] = ?
    printf("the size is: %ld\n", strtol(bytes, NULL, 10));
    // bytes { '1', '0', '0', '0',' 0' } bytes[5] = 0 !!! Note overflow

    printf("enter size 2: ");
    scanf("%s", bytes);  // 100<return>
    // bytes { '1', '0', '0', 0,' 0' } Note bytes[3] changes from '0' to 0

    printf("the size is: %ld\n", strtol(bytes, NULL, 10));

    return 0;

}

简而言之,

Does scanf essentially "empty" out the rest of the array when storing values into the same memory address?

它不会清空它,但您正在读取一个字符串(格式 = "%s"),因此 scanf 将在您读取的字符串的末尾添加适当的终止零.

关于c - 打印出字符串的整数表示时 Scanf 和 strtol 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32936745/

相关文章:

C函数后链接节点丢失

Java String创建和String常量池

c - 使用 sscanf 将元素添加到每个索引的 int 数组中

c - 程序的时间复杂度

c - Ncurses 在光标后显示不需要的文本

c - 结构类型数组。在结构内部有指针

c - 从函数返回字符串(字符数组、字符指针等)

c# - 当对象不是字符串时,如何将对象转换为字符串?

c - 分别扫描 C 中的句子和数字

c - 多次scanf打印最大偶数