【问题标题】:Printing char arrays from a list从列表中打印字符数组
【发布时间】:2015-09-02 16:39:43
【问题描述】:

自从我不得不处理 C 指针以来已经有一段时间了,我在一个项目上遇到了麻烦。这是我为突出我的问题而制作的一些示例代码。我只需要能够将字符串添加到“wordList”并能够稍后检索它们。

// This typedef is in the header file
// typedef char Word[ WORD_LEN + 1 ];

Word wordList[ MAX_WORDS ];

int main () {
  Word message = "HEllO";
  Word message2 = "OHHO";

  *wordList[ 0 ] = malloc ( sizeof( char ) * ( strlen( message ) + 1 ) );
  *wordList[ 0 ] = *message;

  *wordList[ 1 ] = malloc ( sizeof( char ) * ( strlen( message2 ) + 1 ) );
  *wordList[ 1 ] = *message2;

  printf( "%s\n", &wordList[0]);
  printf( "%s\n", &wordList[1]);
}

目前不打印单词,只会打印第一个字母。任何关于我可能在哪里搞砸的提示都会令人难以置信。谢谢!

【问题讨论】:

  • 这一行:typedef char Word[ WORD_LEN + 1 ]; 可能是错误的。您似乎试图生成的是一个二维(二维)字符数组),因此您可以使用:typedef char Word; 然后在源代码中:Word wordlist[WORD_LEN+1][MAX_WORDS];
  • @user3629249: "typedef char Word[ WORD_LEN + 1 ]; 是为char 数组创建别名的合法语法"
  • @alk,但不是指向字符数组的指针数组的合法语法。
  • 好吧,我明白你的想法是什么...... @user3629249 但是这个“typedef char Word; Word wordlist[WORD_LEN+1][MAX_WORDS];”也确实not定义了一个“指向字符数组的指针数组"m 但正是 OP 当前拥有的,如 wordList
  • 关于这两行:*wordList[ 0 ] = malloc ( sizeof( char ) * ( strlen( message ) + 1 ) ); *wordList[ 0 ] = *message; 1) *wordList[0] 将第一个条目视为有效指针,但它实际上是一个简单的字符数组。 2) 表达式sizeof(char) 定义为 1,因此对传递给 malloc 的参数绝对没有影响,并且确实使代码混乱。建议删除该表达式。 3) 始终检查 (!=NULL) malloc 的返回值以确保操作成功

标签: c


【解决方案1】:

Use good ol' strcpy,不用玩指针了。

Word message = "HEllO";
strcpy(wordList[0], message);

printf("%s\n", wordList[0]);

甚至@alk 指出的strncpy

strncpy(wordList[0], message, sizeof(wordList[0]) - 1);
wordList[0][WORD_LEN] = '\0'; 

【讨论】:

  • ... 甚至更好的strncpy() 以避免溢出目标。
【解决方案2】:

wordList 是一个 C-“字符串”数组。所以像这样使用它们:

Word message = "HEllO";

size_t size_max = sizeof wordList[0] - 1;

strncpy(wordList[0], message, size_max);
wordList[0][size_max] = '\0';

【讨论】:

    【解决方案3】:

    现在 wordList 是一个 Word 数组,每个单词都是一个字符数组。当您定义Word wordList[ MAX_WORDS ] 时,已在全局部分中分配了 MAX_WORDS 个大小为 WORD_LEN+1 的字的空间,因此您无需为此分配更多空间。

    要将消息插入单词中,您将使用 strcpy (http://www.cplusplus.com/reference/cstring/strcpy/) 而不是分配空间并分配消息。所以将消息插入 wordList[0] 看起来像strcpy( wordList[0], message)。 strcpy 接受两个 char * ,第一个是副本的目标,第二个是源。

    这里是一些你应该尝试做的示例代码:

    #include <stdio.h> 
    #include <stdlib.h>
    #include <string.h>
    
    typedef char Word[ 10 ];
    Word wordList[ 10 ];
    int main(){
        Word message = "Hello";
        strcpy( wordList[0], message);
        printf("%s", wordList[0]);
        return 0;
    }
    

    ** 为了更安全,您可以使用 strncpy (http://www.cplusplus.com/reference/cstring/strncpy/) 代替 strcpy。您可以在此处指定要复制的字符数作为参数。除了将 strcpy 更改为 strncpy 并添加要复制多少字符的第三个参数之外,所有代码看起来都相同。

    【讨论】:

    • 为什么是演员?
    • 我认为它们是必需的,但我猜不是。 strcpy 是否在内部强制转换它们,还是从不需要强制转换,因为尽管它们是 Word 类型,但它们只是 char 数组。
    • 你编译所有警告时告诉你什么? ;-) 当wordList[0] 被传递给函数时,它会衰减到其第一个元素的地址,即char,因此函数会接收到char*
    【解决方案4】:

    由于 Word 已经被定义为 char 数组(C 字符串),因此无需使用 malloc 在数组中分配内存。本质上,wordList 是一个数组数组,您只需将字符串(单词)的内容复制到所需索引处即可。请参阅下面的代码以获取有效的实现。

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    // some magic numbers
    #define WORD_LEN 50
    #define MAX_WORDS 20
    
    typedef char Word[ WORD_LEN + 1 ];
    Word wordList[ MAX_WORDS ];
    
    int main () {
        Word message = "HEllO";
        Word message2 = "OHHO";
    
        //wordList[ 0 ] = malloc ( sizeof( char ) * ( strlen( message ) + 1 ) );
        //*wordList[ 0 ] = *message;
        strncpy(wordList[0], message, sizeof(Word));
    
        //wordList[ 1 ] = malloc ( sizeof( char ) * ( strlen( message2 ) + 1 ) );
        //*wordList[ 1 ] = *message2;
        strncpy(wordList[1], message2, sizeof(Word));
    
        printf( "%s\n", wordList[0]);
        printf( "%s\n", wordList[1]);
    }
    

    【讨论】:

    • 为什么使用memcpy()的复杂方式 strlen()。有strcpy()/strncpy() 这个你的代码也不能保护目标不被溢出。
    • 这个发布的答案有很多问题,让我们简单地说:“它不编译”。我几乎不会称其为“工作实施”
    • @user3629249 它编译时甚至没有对我发出警告(至少在两个不同的操作系统上)。你在什么环境下工作?尝试过 Linux/gcc 和 OpenVMS。
    • 应用于printf()s 的agruments 的地址确实是错误的。其他都还好。
    • -Wall -Wextra -pedantic 是你的朋友! ;-)
    猜你喜欢
    • 2017-06-26
    • 2021-07-24
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 2019-06-29
    • 2016-02-15
    相关资源
    最近更新 更多