Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strcpy和printf多维字符数组C_C_Printf_Arrays_Strcpy - Fatal编程技术网

strcpy和printf多维字符数组C

strcpy和printf多维字符数组C,c,printf,arrays,strcpy,C,Printf,Arrays,Strcpy,假设我有一个数组 char messages[10][2][50]; strcpy的正确语法是什么,以便将数据放入其中一个字符串(最内部的字符数组大小为50),然后按照相应的约定通过%s将数据提供给printf 就此而言,我是否按照正确的顺序声明数组下标?它将是10对(2对)弦。每条线宽50个字符 01{{50 chars},{50 chars}} 02{{50 chars},{50 chars}} ... 09{{50 chars},{50 chars}} 10{{50 chars},{50

假设我有一个数组

char messages[10][2][50];
strcpy的正确语法是什么,以便将数据放入其中一个字符串(最内部的字符数组大小为50),然后按照相应的约定通过%s将数据提供给printf

就此而言,我是否按照正确的顺序声明数组下标?它将是10对(2对)弦。每条线宽50个字符

01{{50 chars},{50 chars}}
02{{50 chars},{50 chars}}
...
09{{50 chars},{50 chars}}
10{{50 chars},{50 chars}}
各种互联网来源似乎在哪个下标上存在冲突,无论我尝试什么,似乎都会产生意想不到的结果

e、 你能把下面的空白填一下吗

strcpy(message???, "Message 1 Part 1");
strcpy(message???, "m1 p2");
strcpy(message???, "m2 p1");
strcpy(message???, "m2 p2");
strcpy(message???, "m3 p1");
strcpy(message???, "m3 p1");
//So on...

int i;
for(i=0;i<10;i++)
    printf("%s, %s\n", message???, message???);
和产出本身

信息1第1部分,m2 p2

m2,p2

m3,p3

等等


您可以指定最大订阅(例如,它是10),因为编译器可以根据剩余订阅计算它。 要传递50个元素的层,请使用指针:(*消息)[10][2]-将是50个元素层上的指针

我将使用:

假设您想复制到
char*new\u buff

memcpy(new_buff, messages, 10*2*50);
您可以执行3嵌套循环并使用
strncpy


不要使用strcpy。。。它是不安全的

我刚刚写了一个快速程序来显示您询问的内容。。。在声明时加载它们,将strncpy放入其中一个,然后打印出来

希望能有帮助

编辑:我有点讨厌魔法数字,所以我几乎完全删除了它们
编辑:我已经添加了Tommi Kyntola和我在评论中提到的备选方案

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

// safe string copy macro, terminates string at end if necessary
// note: could probably just set the last char to \0 in all cases
// safely if intending to just cut off the end of the string like this

#define sstrcpy(buf, src, size) strncpy(buf, src, size); if(strlen(src) >= size) buf[size-1] = '\0';

#define MSGLIMIT 10
#define MSGLENGTH 30
#define MSGFIELDS 2
#define MSGNAME 0
#define MSGTEXT 1


int main(void) {
    char messages[MSGLIMIT][MSGFIELDS][MSGLENGTH] = { {"bla", "raa"},
                                                      {"foo", "bar"}
                                                    };
    int i;

    char *name1 = "name16789012345678901234567890";
    char *text1 = "text16789012345678901234567890";

    char *name2 = "name26789012345678901234567890";
    char *text2 = "text26789012345678901234567890";

    char *name3 = "name36789012345678901234567890";
    char *text3 = "text36789012345678901234567890";


    // doesn't set last char to \0 because str overruns buffer
    // undocumented result of running this, but likely to just get the name2 string
    // as that'll be the very next thing in memory on most systems

    strncpy(messages[2][MSGNAME], name1, MSGLENGTH); // 2 because it's the next empty one
    strncpy(messages[2][MSGTEXT], text1, MSGLENGTH);

    // alternative suggested by Tommi Kyntola
    // printf family are more complicated and so cost more cpu time than strncpy
    // but it's quick and easy anywhere you have string.h and fine most of the time

    snprintf(messages[3][MSGNAME], MSGLENGTH, "%s", name2);
    snprintf(messages[3][MSGTEXT], MSGLENGTH, "%s", text2);

    // uses the define macro at the top of the page to set the last char to \0 if
    // otherwise not set by strncpy, adds a little weight but still the better option
    // if performance of this section of code is important

    sstrcpy(messages[4][MSGNAME], name3, MSGLENGTH);
    sstrcpy(messages[4][MSGTEXT], text3, MSGLENGTH);


    for(i = 0; i < 5; i++) // 5 because that's how many I've populated
            printf("%s : %s\n", messages[i][MSGNAME], messages[i][MSGTEXT]);

    return 0;
}
#包括
#包括
//安全字符串复制宏,必要时在末尾终止字符串
//注意:在所有情况下,可能只需将最后一个字符设置为\0
//如果打算像这样切断绳子的末端,那就安全了
#定义sstrcpy(buf,src,size)strncpy(buf,src,size);如果(strlen(src)>=size)buf[size-1]='\0';
#定义MSIT 10
#定义MSGLENGTH 30
#定义MSGFIELDS 2
#定义MSGNAME 0
#定义msgtext1
内部主(空){
字符消息[MSGLIMIT][MSGFIELDS][MSGLENGTH]={{{“bla”,“raa”},
{“foo”,“bar”}
};
int i;
char*name1=“name16789012345678901234567890”;
char*text1=“text16789012345678901234567890”;
char*name2=“name 267890123456788901234567890”;
char*text2=“text267890123456788901234567890”;
char*name3=“name367890123456788901234567890”;
char*text3=“text367890123456788901234567890”;
//未将最后一个字符设置为\0,因为str溢出了缓冲区
//运行此命令的未记录结果,但很可能只得到name2字符串
//因为这将是大多数系统内存中的下一件事
strncpy(messages[2][MSGNAME],name1,MSGLENGTH);//2,因为它是下一个空的
strncpy(消息[2][MSGTEXT],文本1,MSGLENGTH);
//Tommi Kyntola建议的替代方案
//printf系列更复杂,因此比strncpy花费更多的cpu时间
//但是,只要你有绳子,它就很快很容易。大多数时候都很好
snprintf(messages[3][MSGNAME],MSGLENGTH,“%s”,name2);
snprintf(消息[3][MSGTEXT],MSGLENGTH,“%s”,text2);
//如果需要,使用页面顶部的define宏将最后一个字符设置为\0
//否则不是由strncpy设置的,会增加一点权重,但仍然是更好的选项
//如果这段代码的性能很重要
sstrcpy(消息[4][MSGNAME],名称3,MSGLENGTH);
sstrcpy(消息[4][MSGTEXT],文本3,MSGLENGTH);
对于(i=0;i<5;i++)//5,因为这就是我填充的数量
printf(“%s:%s\n”,消息[i][MSGNAME],消息[i][MSGTEXT]);
返回0;
}

正如已经指出的,最好使用strncpy,或者在下面的示例中,使用断言,以防止可能的缓冲区溢出。与strncpy相比,strcpy的性能略有提高

    #define FIRST_OF_PAIR 0
#define SECOND_OF_PAIR 1

    int message_num = 7;

    char messages[10][2][50];

    char *string = "hello";

    assert(strlen(string) < 50);
    assert(message_num > 0 &&  message_num < 10);

    strcpy(messages[message_num][SECOND_OF_PAIR], "Hello");

    printf("%s", messages[message_num][SECOND_OF_PAIR]);
#定义_对0中的第一个_
#定义_对1中的第二个_
int message_num=7;
字符信息[10][2][50];
char*string=“你好”;
断言(strlen(string)<50);
断言(message_num>0&&message_num<10);
strcpy(messages[message_num][SECOND_OF_PAIR],“Hello”);
printf(“%s”,messages[message_num][SECOND_OF_PAIR]);
它将是

strcpy(message[0][0], "Message 1 Part 1");
strcpy(message[0][1], "m1 p2");
strcpy(message[2][0], "m2 p1");
strcpy(message[2][1], "m2 p2");
strcpy(message[3][0], "m3 p1");
strcpy(message[3][1], "m3 p2");


for(i=0;i<10;i++)
    printf("%s, %s\n", message[i][0], message[i][1]);
strcpy(消息[0][0],“消息1第1部分”);
strcpy(消息[0][1],“m1 p2”);
strcpy(信息[2][0],“m2 p1”);
strcpy(信息[2][1],“m2 p2”);
strcpy(信息[3][0],“m3 p1”);
strcpy(信息[3][1],“m3 p2”);

对于(i=0;ii如果你有一个固定长度的数组,
strcpy
看起来像是自杀。如果有的话,可以使用
strncpy
,或者干脆使用
memcpy
整个过程。直到现在还没有找到它们之间的差异。感谢所有回答的人。我从每一个答案中都学到了一些东西。也许我的问题措辞不正确y、 我有上面的字符串数组(3D字符数组),需要填充给定的单个字符串(或1D字符数组)。类似的方法会起作用吗?我认为最好不要将assert放入生产代码中。相反,最好使用strncpy,然后检查返回值以查看复制的字符是否比预期的少。是的,通常只在调试版本中放置assert,通常使用#ifdef debug围绕它们进行调试。实际上,assert通常由我们编译出来在包含assert.hI-am之前,先定义NDEBUG。根据行主要值填充数据。您也可以填充列主要值。strncpy通常需要一些额外的处理。如果达到消息长度,它会保留空终止符!这在大多数情况下不是程序员想要的。请确保空终止符存在或使用snprintf(buf,“%s”,str),即使它被截断也会终止。是的,实际上这是真的,使用strncpy需要检查字符串是否大于目标值,如果大于目标值,则进行处理(只需将最后一个字符设置为“\0”简单解决方案)。snprintf(buf,大小,“%s”,str)但是,如果你的程序要重复很多次,那么就有可能
strcpy(message[0][0], "Message 1 Part 1");
strcpy(message[0][1], "m1 p2");
strcpy(message[2][0], "m2 p1");
strcpy(message[2][1], "m2 p2");
strcpy(message[3][0], "m3 p1");
strcpy(message[3][1], "m3 p2");


for(i=0;i<10;i++)
    printf("%s, %s\n", message[i][0], message[i][1]);