通过添加' 0'将整数转换为char。 - 怎么了?

时间:2015-05-04 11:43:32

标签: c char

我有一个像这样的简单程序:

#include <stdio.h>

int main(void)
{
    int numbers[] = {1, 2, 3, 4, 5};
    char chars[] = {'a', 'i'};
    char name[] = "Max";

    name[1] = chars[1];

    printf("name (before) = %s\n", name);

    name[1] = numbers[1];

    printf("name (after) = %s\n", name);

    return 0;
}

编译并运行:

$ gcc -std=c11 -pedantic -Wall -Werror ex8_simple.c
$ ./a.out
$ name (before) = Mix
$ name (after) = Mx

这不是我想要的。然后我挖出问题Store an integer value in a character array in C并改变了这个程序:

name[1] = '0' + numbers[1];  //replacing  >> name[1] = numbers[1];

然后它按照我的期望工作:

$ gcc -std=c11 -pedantic -Wall -Werror ex8_simple.c
$ ./a.out
$ name (before) = Mix
$ name (after) = M2x

我不明白发生在幕后的事情,特别是没有'0' + …的版本真的很奇怪。为什么字符串被截断?#34;怪异&#34;通往Mx的方式?

供参考,这是exercise 8 of Learn C The Hard Way的简化版本。

3 个答案:

答案 0 :(得分:8)

每个符号都有一个数字表示,所以基本上每个字符都是一个数字。这是字符及其值的表格。

http://www.asciitable.com/index/asciifull.gif

因此,在您的代码 05-04 08:01:33.850 23385-23454/? E/dalvikvm﹕ Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.ff.a 05-04 08:01:33.880 23385-23454/? E/dalvikvm﹕ Could not find class 'android.app.Notification$Builder', referenced from method com.google.android.gms.common.ff.b 05-04 08:01:36.010 10233-23463/? E/TalkProvider﹕ replaceContactWithContactId: contactId==0!!! pablogarces123@gmail.com, acct=1 05-04 08:01:36.010 10233-23463/? E/TalkProvider﹕ insert presence failed for account=1 username=pablogarces123@gmail.com client_type=2 status= cap=0 priority=0 mode=3 05-04 08:01:36.090 10233-23463/? E/TalkProvider﹕ replaceContactWithContactId: contactId==0!!! pablogarces123@gmail.com, acct=1 05-04 08:01:36.090 10233-23463/? E/TalkProvider﹕ insert presence failed for account=1 username=pablogarces123@gmail.com client_type=2 status= cap=0 priority=0 mode=3 05-04 08:01:37.469 23385-23466/? E/dalvikvm﹕ Could not find class 'android.os.UserManager', referenced from method com.google.android.gms.common.util.a.b 05-04 08:01:37.469 23385-23466/? E/dalvikvm﹕ Could not find class 'android.os.UserManager', referenced from method com.google.android.gms.common.util.a.c 05-04 08:01:37.469 23385-23466/? E/dalvikvm﹕ Could not find class 'android.os.UserManager', referenced from method com.google.android.gms.common.util.a.e 05-04 08:01:37.499 23223-23241/? E/﹕ statfs /mnt/secure/asec failed, errno: 13 05-04 08:01:40.499 23223-23233/? E/﹕ statfs /mnt/secure/asec failed, errno: 13 05-04 08:01:49.679 10207-10207/? E/Launcher﹕ setWindowOpaque() 05-04 08:01:49.729 10207-10207/? E/Launcher﹕ MTP-LAUNCHER: media scanning not yet finished. 05-04 08:01:57.119 10079-23504/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:01:57.159 10079-23506/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:01:57.179 10079-23508/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:01:57.199 10079-23510/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:01:57.219 10079-23512/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:01:57.239 10079-23514/? E/PlayerDriver﹕ Creating Non-Tunnel mode playback - uncompressed MIO 05-04 08:02:04.759 23530-23530/? E/dalvikvm﹕ Could not find class 'android.database.sqlite.SQLiteCantOpenDatabaseException', referenced from method com.google.android.gms.plus.provider.PlusProvider.a 05-04 08:02:15.619 10233-10233/? E/AuthorizationBluetoothService﹕ Proximity feature is not enabled. 05-04 08:02:16.169 23602-23602/? E/dalvikvm﹕ Could not find class 'android.database.sqlite.SQLiteCantOpenDatabaseException', referenced from method com.google.android.gms.plus.provider.PlusProvider.a 05-04 08:02:17.359 10233-10233/? E/AuthorizationBluetoothService﹕ Proximity feature is not enabled. 05-04 08:02:25.849 23551-23551/? E/Finsky﹕ [1] InstallerTask.requireInternalStorageOrCancel: Cancel download of com.google.android.gms because insufficient free space 05-04 08:03:25.599 23641-23641/? E/dalvikvm﹕ Could not find class 'android.database.sqlite.SQLiteCantOpenDatabaseException', referenced from method com.google.android.gms.plus.provider.PlusProvider.a 05-04 08:03:26.139 10233-10233/? E/AuthorizationBluetoothService﹕ Proximity feature is not enabled. 05-04 08:03:26.759 23641-23656/? E/dalvikvm﹕ Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.ff.a 05-04 08:03:26.759 23641-23656/? E/dalvikvm﹕ Could not find class 'android.app.Notification$Builder', referenced from method com.google.android.gms.common.ff.b 05-04 08:03:27.959 23641-23656/? E/dalvikvm﹕ Could not find class 'android.security.KeyPairGeneratorSpec$Builder', referenced from method com.google.android.gms.auth.e.a.a 05-04 08:03:30.809 23641-23664/? E/dalvikvm﹕ Could not find class 'android.os.UserManager', referenced from method com.google.android.gms.common.util.a.b 中,您将name[1] = numbers[1];分配给name[1],它等于上面ASCII表中的符号2,这不是可打印的字符,这就是你输出错误的原因。

当您向STX添加'0'时,它等于name[1],因此编号为add 48 to 2的符号为50,即&#39 ;为什么你得到正确的输出。

答案 1 :(得分:4)

  

这不是我想要的。

但是,您只为此编写了代码。让我解释一下这个场景。

  • 如果是

    name[1] = chars[1];
    

name[1]a已被chars[1]i取代。所以,o / p是Mix

  • 如果是

    name[1] = numbers[1];
    

name[1]a被替换为numbers[1]或2,(不是'2'),这是不可打印的。(#note)因此,输出为Mx

然而,在你的第二种方法中,

 name[1] = '0' + numbers[1];

您通过添加'2'来存储ASCII等效值'0'。因此,该打印在输出中包含character '2'的表示。

替代方法:

如果您修改yout int数组以存储数字char的{​​{1}}表示的十进制等值,那么您不需要添加0-9,像

'0'

int numbers[] = {'1', '2', '3', '4', '5'};

会给你所需的o / p。

建议:请记住,name[1] = numbers[1]; 中的数组索引基于C

#注意:请参阅此ASCII table以供参考。

答案 2 :(得分:2)

在这一行:name[1] = numbers[1];中,您要为int分配char name[1]值,以便将numbers[1]中的int值视为某些char的Ascii代码,并且该char存储在name[1]中。

执行name[1] = '0' + numbers[1];时,数字(2)会添加到数字0的ascii代码中,因此您可以获得实际数字。 0的ascii代码为48,为其添加2,得到50,这是2的ascii代码。

以前,当您仅分配name[1] = numbers[1];而没有0时,会打印带有ascii代码0的字符。因为它不是一个正确的可打印字符,所以没有显示任何内容(在我的机器中它显示为一些奇怪的表情符号)。